os_linux_amd64.c (3747B)
1 /* See LICENSE for license details. */ 2 #ifndef asm 3 #ifdef __asm 4 #define asm __asm 5 #else 6 #define asm __asm__ 7 #endif 8 #endif 9 10 /* TODO: X macro that defines all of these with the appropriate function/macro */ 11 typedef enum { 12 SYS_read = 0, 13 SYS_write = 1, 14 SYS_close = 3, 15 SYS_mmap = 9, 16 SYS_mprotect = 10, 17 SYS_munmap = 11, 18 SYS_ioctl = 16, 19 SYS_pwrite64 = 18, 20 SYS_madvise = 28, 21 SYS_clone = 56, 22 SYS_execve = 59, 23 SYS_exit = 60, 24 SYS_wait4 = 61, 25 SYS_ftruncate = 77, 26 SYS_setsid = 112, 27 SYS_prctl = 157, 28 SYS_futex = 202, 29 SYS_getdents64 = 217, 30 SYS_clock_gettime = 228, 31 SYS_exit_group = 231, 32 SYS_inotify_add_watch = 254, 33 SYS_inotify_rm_watch = 255, 34 SYS_openat = 257, 35 SYS_pselect6 = 270, 36 SYS_dup3 = 292, 37 SYS_inotify_init1 = 294, 38 SYS_memfd_create = 319, 39 SYS_statx = 332, 40 } AMD64Syscall; 41 42 #define SIGCHLD 17 43 44 #define PAGE_SIZE 4096 45 46 typedef u64 sys_fd_set[16]; 47 48 #define DIRENT_RECLEN_OFF 16 49 #define DIRENT_TYPE_OFF 18 50 #define DIRENT_NAME_OFF 19 51 52 function FORCE_INLINE u64 53 syscall1(AMD64Syscall n, i64 a1) 54 { 55 u64 result; 56 asm volatile ("syscall" 57 : "=a"(result) 58 : "a"(n), "D"(a1) 59 : "rcx", "r11", "memory" 60 ); 61 return result; 62 } 63 64 function FORCE_INLINE u64 65 syscall2(AMD64Syscall n, i64 a1, i64 a2) 66 { 67 i64 result; 68 asm volatile ("syscall" 69 : "=a"(result) 70 : "a"(n), "D"(a1), "S"(a2) 71 : "rcx", "r11", "memory" 72 ); 73 return result; 74 } 75 76 function FORCE_INLINE u64 77 syscall3(AMD64Syscall n, i64 a1, i64 a2, i64 a3) 78 { 79 u64 result; 80 asm volatile ("syscall" 81 : "=a"(result) 82 : "a"(n), "D"(a1), "S"(a2), "d"(a3) 83 : "rcx", "r11", "memory" 84 ); 85 return result; 86 } 87 88 function FORCE_INLINE u64 89 syscall4(AMD64Syscall n, i64 a1, i64 a2, i64 a3, i64 a4) 90 { 91 u64 result; 92 register i64 r10 asm("r10") = a4; 93 asm volatile ("syscall" 94 : "=a"(result) 95 : "a"(n), "D"(a1), "S"(a2), "d"(a3), "r"(r10) 96 : "rcx", "r11", "memory" 97 ); 98 return result; 99 } 100 101 102 function FORCE_INLINE u64 103 syscall5(AMD64Syscall n, i64 a1, i64 a2, i64 a3, i64 a4, i64 a5) 104 { 105 u64 result; 106 register i64 r10 asm("r10") = a4; 107 register i64 r8 asm("r8") = a5; 108 asm volatile ("syscall" 109 : "=a"(result) 110 : "a"(n), "D"(a1), "S"(a2), "d"(a3), "r"(r10), "r"(r8) 111 : "rcx", "r11", "memory" 112 ); 113 return result; 114 } 115 116 function FORCE_INLINE u64 117 syscall6(AMD64Syscall n, i64 a1, i64 a2, i64 a3, i64 a4, i64 a5, i64 a6) 118 { 119 i64 result; 120 register i64 r10 asm("r10") = a4; 121 register i64 r8 asm("r8") = a5; 122 register i64 r9 asm("r9") = a6; 123 asm volatile ("syscall" 124 : "=a"(result) 125 : "a"(n), "D"(a1), "S"(a2), "d"(a3), "r"(r10), "r"(r8), "r"(r9) 126 : "rcx", "r11", "memory" 127 ); 128 return result; 129 } 130 131 /* NOTE: based on code from nullprogram (Chris Wellons) */ 132 __attribute__((naked)) 133 function i64 134 new_thread(void *stack_base) 135 { 136 asm volatile ( 137 "mov %%rdi, %%rsi\n" // arg2 = new stack 138 "mov $0x50F00, %%edi\n" // arg1 = clone flags (VM|FS|FILES|SIGHAND|THREAD|SYSVMEM) 139 "mov $56, %%eax\n" // SYS_clone 140 "syscall\n" 141 "test %%eax, %%eax\n" // don't mess with the calling thread's stack 142 "jne 1f\n" 143 "mov %%rsp, %%rdi\n" 144 "sub $8, %%rsp\n" // place a 0 return branch pointer on the child's stack 145 "push (%%rdi)\n" // push the entry point back onto the stack for use by ret 146 "1: ret\n" 147 ::: "rax", "rcx", "rsi", "rdi", "r11", "memory" 148 ); 149 } 150 151 #include "os_linux_common.c" 152 153 #if 0 154 asm ( 155 ".intel_syntax noprefix\n" 156 ".global _start\n" 157 "_start:\n" 158 " mov edi, DWORD PTR [rsp]\n" 159 " lea rsi, [rsp+8]\n" 160 " lea rdx, [rsi+rdi*8+8]\n" 161 " call linux_main\n" 162 " ud2\n" 163 ".att_syntax\n" 164 ); 165 #endif