// // RMG's syscallX macros for 64-bit systems; // only syscall0 - syscall3 are supplied; these are based // on the register layout in /usr/src/linux/arch/x86/kernel/entry_64.S: // /* * Register setup: * rax system call number * rdi arg0 * rcx return address for syscall/sysret, C arg3 * rsi arg1 * rdx arg2 * r10 arg3 (--> moved to rcx for C) * r8 arg4 * r9 arg5 * r11 eflags for syscall/sysret, temporary for C * r12-r15,rbp,rbx saved by C code, not touched. * * Interrupts are off on entry. * Only called from user space. */ // put these in /usr/include/asm-x86_64/unistd.h at the end, // just before the #endif /* _ASM_X86_64_UNISTD_H_ */ #define __syscall_return(type, res) \ do { \ if ((unsigned long)(res) >= (unsigned long)(-125)) { \ errno = -(res); \ res = -1; \ } \ return (type) (res); \ } while (0) #define _syscall0(type,name) \ type name(void) \ { \ long __res; \ __asm__ volatile ("syscall" \ : "=a" (__res) \ : "0" (__NR_##name)); \ __syscall_return(type,__res); \ } #define _syscall1(type,name,type1,arg1) \ type name(type1 arg1) \ { \ long __res; \ __asm__ volatile ("syscall" \ : "=a" (__res) \ : "0" (__NR_##name),"D" ((long)(arg1))); \ __syscall_return(type,__res); \ } #define _syscall2(type,name,type1,arg1,type2,arg2) \ type name(type1 arg1,type2 arg2) \ { \ long __res; \ __asm__ volatile ("syscall" \ : "=a" (__res) \ : "0" (__NR_##name),"D" ((long)(arg1)),"S" ((long)(arg2))); \ __syscall_return(type,__res); \ } #define _syscall3(type,name,type1,arg1,type2,arg2,type3,arg3) \ type name(type1 arg1,type2 arg2,type3 arg3) \ { \ long __res; \ __asm__ volatile ("syscall" \ : "=a" (__res) \ : "0" (__NR_##name),"D" ((long)(arg1)),"S" ((long)(arg2)), \ "d" ((long)(arg3))); \ __syscall_return(type,__res); \ }