1bb898558SAl Viro /* 2bb898558SAl Viro * Access to user system call parameters and results 3bb898558SAl Viro * 4bb898558SAl Viro * Copyright (C) 2008 Red Hat, Inc. All rights reserved. 5bb898558SAl Viro * 6bb898558SAl Viro * This copyrighted material is made available to anyone wishing to use, 7bb898558SAl Viro * modify, copy, or redistribute it subject to the terms and conditions 8bb898558SAl Viro * of the GNU General Public License v.2. 9bb898558SAl Viro * 10bb898558SAl Viro * See asm-generic/syscall.h for descriptions of what we must do here. 11bb898558SAl Viro */ 12bb898558SAl Viro 135e1b0075SH. Peter Anvin #ifndef _ASM_X86_SYSCALL_H 145e1b0075SH. Peter Anvin #define _ASM_X86_SYSCALL_H 15bb898558SAl Viro 16bb898558SAl Viro #include <linux/sched.h> 17bb898558SAl Viro #include <linux/err.h> 18bb898558SAl Viro 19bb898558SAl Viro static inline long syscall_get_nr(struct task_struct *task, 20bb898558SAl Viro struct pt_regs *regs) 21bb898558SAl Viro { 22bb898558SAl Viro /* 23bb898558SAl Viro * We always sign-extend a -1 value being set here, 24bb898558SAl Viro * so this is always either -1L or a syscall number. 25bb898558SAl Viro */ 26bb898558SAl Viro return regs->orig_ax; 27bb898558SAl Viro } 28bb898558SAl Viro 29bb898558SAl Viro static inline void syscall_rollback(struct task_struct *task, 30bb898558SAl Viro struct pt_regs *regs) 31bb898558SAl Viro { 32bb898558SAl Viro regs->ax = regs->orig_ax; 33bb898558SAl Viro } 34bb898558SAl Viro 35bb898558SAl Viro static inline long syscall_get_error(struct task_struct *task, 36bb898558SAl Viro struct pt_regs *regs) 37bb898558SAl Viro { 38bb898558SAl Viro unsigned long error = regs->ax; 39bb898558SAl Viro #ifdef CONFIG_IA32_EMULATION 40bb898558SAl Viro /* 41bb898558SAl Viro * TS_COMPAT is set for 32-bit syscall entries and then 42bb898558SAl Viro * remains set until we return to user mode. 43bb898558SAl Viro */ 44bb898558SAl Viro if (task_thread_info(task)->status & TS_COMPAT) 45bb898558SAl Viro /* 46bb898558SAl Viro * Sign-extend the value so (int)-EFOO becomes (long)-EFOO 47bb898558SAl Viro * and will match correctly in comparisons. 48bb898558SAl Viro */ 49bb898558SAl Viro error = (long) (int) error; 50bb898558SAl Viro #endif 51bb898558SAl Viro return IS_ERR_VALUE(error) ? error : 0; 52bb898558SAl Viro } 53bb898558SAl Viro 54bb898558SAl Viro static inline long syscall_get_return_value(struct task_struct *task, 55bb898558SAl Viro struct pt_regs *regs) 56bb898558SAl Viro { 57bb898558SAl Viro return regs->ax; 58bb898558SAl Viro } 59bb898558SAl Viro 60bb898558SAl Viro static inline void syscall_set_return_value(struct task_struct *task, 61bb898558SAl Viro struct pt_regs *regs, 62bb898558SAl Viro int error, long val) 63bb898558SAl Viro { 64bb898558SAl Viro regs->ax = (long) error ?: val; 65bb898558SAl Viro } 66bb898558SAl Viro 67bb898558SAl Viro #ifdef CONFIG_X86_32 68bb898558SAl Viro 69bb898558SAl Viro static inline void syscall_get_arguments(struct task_struct *task, 70bb898558SAl Viro struct pt_regs *regs, 71bb898558SAl Viro unsigned int i, unsigned int n, 72bb898558SAl Viro unsigned long *args) 73bb898558SAl Viro { 74bb898558SAl Viro BUG_ON(i + n > 6); 75bb898558SAl Viro memcpy(args, ®s->bx + i, n * sizeof(args[0])); 76bb898558SAl Viro } 77bb898558SAl Viro 78bb898558SAl Viro static inline void syscall_set_arguments(struct task_struct *task, 79bb898558SAl Viro struct pt_regs *regs, 80bb898558SAl Viro unsigned int i, unsigned int n, 81bb898558SAl Viro const unsigned long *args) 82bb898558SAl Viro { 83bb898558SAl Viro BUG_ON(i + n > 6); 84bb898558SAl Viro memcpy(®s->bx + i, args, n * sizeof(args[0])); 85bb898558SAl Viro } 86bb898558SAl Viro 87bb898558SAl Viro #else /* CONFIG_X86_64 */ 88bb898558SAl Viro 89bb898558SAl Viro static inline void syscall_get_arguments(struct task_struct *task, 90bb898558SAl Viro struct pt_regs *regs, 91bb898558SAl Viro unsigned int i, unsigned int n, 92bb898558SAl Viro unsigned long *args) 93bb898558SAl Viro { 94bb898558SAl Viro # ifdef CONFIG_IA32_EMULATION 95bb898558SAl Viro if (task_thread_info(task)->status & TS_COMPAT) 96*c3c9897cSLinus Torvalds switch (i) { 97*c3c9897cSLinus Torvalds case 0: 98bb898558SAl Viro if (!n--) break; 99bb898558SAl Viro *args++ = regs->bx; 100*c3c9897cSLinus Torvalds case 1: 101*c3c9897cSLinus Torvalds if (!n--) break; 102*c3c9897cSLinus Torvalds *args++ = regs->cx; 103*c3c9897cSLinus Torvalds case 2: 104*c3c9897cSLinus Torvalds if (!n--) break; 105*c3c9897cSLinus Torvalds *args++ = regs->dx; 106*c3c9897cSLinus Torvalds case 3: 107*c3c9897cSLinus Torvalds if (!n--) break; 108*c3c9897cSLinus Torvalds *args++ = regs->si; 109*c3c9897cSLinus Torvalds case 4: 110*c3c9897cSLinus Torvalds if (!n--) break; 111*c3c9897cSLinus Torvalds *args++ = regs->di; 112*c3c9897cSLinus Torvalds case 5: 113*c3c9897cSLinus Torvalds if (!n--) break; 114*c3c9897cSLinus Torvalds *args++ = regs->bp; 115*c3c9897cSLinus Torvalds case 6: 116bb898558SAl Viro if (!n--) break; 117bb898558SAl Viro default: 118bb898558SAl Viro BUG(); 119bb898558SAl Viro break; 120bb898558SAl Viro } 121bb898558SAl Viro else 122bb898558SAl Viro # endif 123*c3c9897cSLinus Torvalds switch (i) { 124*c3c9897cSLinus Torvalds case 0: 125bb898558SAl Viro if (!n--) break; 126bb898558SAl Viro *args++ = regs->di; 127*c3c9897cSLinus Torvalds case 1: 128*c3c9897cSLinus Torvalds if (!n--) break; 129*c3c9897cSLinus Torvalds *args++ = regs->si; 130*c3c9897cSLinus Torvalds case 2: 131*c3c9897cSLinus Torvalds if (!n--) break; 132*c3c9897cSLinus Torvalds *args++ = regs->dx; 133*c3c9897cSLinus Torvalds case 3: 134*c3c9897cSLinus Torvalds if (!n--) break; 135*c3c9897cSLinus Torvalds *args++ = regs->r10; 136*c3c9897cSLinus Torvalds case 4: 137*c3c9897cSLinus Torvalds if (!n--) break; 138*c3c9897cSLinus Torvalds *args++ = regs->r8; 139*c3c9897cSLinus Torvalds case 5: 140*c3c9897cSLinus Torvalds if (!n--) break; 141*c3c9897cSLinus Torvalds *args++ = regs->r9; 142*c3c9897cSLinus Torvalds case 6: 143bb898558SAl Viro if (!n--) break; 144bb898558SAl Viro default: 145bb898558SAl Viro BUG(); 146bb898558SAl Viro break; 147bb898558SAl Viro } 148bb898558SAl Viro } 149bb898558SAl Viro 150bb898558SAl Viro static inline void syscall_set_arguments(struct task_struct *task, 151bb898558SAl Viro struct pt_regs *regs, 152bb898558SAl Viro unsigned int i, unsigned int n, 153bb898558SAl Viro const unsigned long *args) 154bb898558SAl Viro { 155bb898558SAl Viro # ifdef CONFIG_IA32_EMULATION 156bb898558SAl Viro if (task_thread_info(task)->status & TS_COMPAT) 157*c3c9897cSLinus Torvalds switch (i) { 158*c3c9897cSLinus Torvalds case 0: 159bb898558SAl Viro if (!n--) break; 160bb898558SAl Viro regs->bx = *args++; 161*c3c9897cSLinus Torvalds case 1: 162*c3c9897cSLinus Torvalds if (!n--) break; 163*c3c9897cSLinus Torvalds regs->cx = *args++; 164*c3c9897cSLinus Torvalds case 2: 165*c3c9897cSLinus Torvalds if (!n--) break; 166*c3c9897cSLinus Torvalds regs->dx = *args++; 167*c3c9897cSLinus Torvalds case 3: 168*c3c9897cSLinus Torvalds if (!n--) break; 169*c3c9897cSLinus Torvalds regs->si = *args++; 170*c3c9897cSLinus Torvalds case 4: 171*c3c9897cSLinus Torvalds if (!n--) break; 172*c3c9897cSLinus Torvalds regs->di = *args++; 173*c3c9897cSLinus Torvalds case 5: 174*c3c9897cSLinus Torvalds if (!n--) break; 175*c3c9897cSLinus Torvalds regs->bp = *args++; 176*c3c9897cSLinus Torvalds case 6: 177bb898558SAl Viro if (!n--) break; 178bb898558SAl Viro default: 179bb898558SAl Viro BUG(); 180*c3c9897cSLinus Torvalds break; 181bb898558SAl Viro } 182bb898558SAl Viro else 183bb898558SAl Viro # endif 184*c3c9897cSLinus Torvalds switch (i) { 185*c3c9897cSLinus Torvalds case 0: 186bb898558SAl Viro if (!n--) break; 187bb898558SAl Viro regs->di = *args++; 188*c3c9897cSLinus Torvalds case 1: 189*c3c9897cSLinus Torvalds if (!n--) break; 190*c3c9897cSLinus Torvalds regs->si = *args++; 191*c3c9897cSLinus Torvalds case 2: 192*c3c9897cSLinus Torvalds if (!n--) break; 193*c3c9897cSLinus Torvalds regs->dx = *args++; 194*c3c9897cSLinus Torvalds case 3: 195*c3c9897cSLinus Torvalds if (!n--) break; 196*c3c9897cSLinus Torvalds regs->r10 = *args++; 197*c3c9897cSLinus Torvalds case 4: 198*c3c9897cSLinus Torvalds if (!n--) break; 199*c3c9897cSLinus Torvalds regs->r8 = *args++; 200*c3c9897cSLinus Torvalds case 5: 201*c3c9897cSLinus Torvalds if (!n--) break; 202*c3c9897cSLinus Torvalds regs->r9 = *args++; 203*c3c9897cSLinus Torvalds case 6: 204bb898558SAl Viro if (!n--) break; 205bb898558SAl Viro default: 206bb898558SAl Viro BUG(); 207*c3c9897cSLinus Torvalds break; 208bb898558SAl Viro } 209bb898558SAl Viro } 210bb898558SAl Viro 211bb898558SAl Viro #endif /* CONFIG_X86_32 */ 212bb898558SAl Viro 2135e1b0075SH. Peter Anvin #endif /* _ASM_X86_SYSCALL_H */ 214