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