1bb898558SAl Viro /* 2bb898558SAl Viro * Access to user system call parameters and results 3bb898558SAl Viro * 4*18c1e2c8SRoland McGrath * Copyright (C) 2008-2009 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 /* 20*18c1e2c8SRoland McGrath * Only the low 32 bits of orig_ax are meaningful, so we return int. 21*18c1e2c8SRoland McGrath * This importantly ignores the high bits on 64-bit, so comparisons 22*18c1e2c8SRoland McGrath * sign-extend the low 32 bits. 23bb898558SAl Viro */ 24*18c1e2c8SRoland McGrath static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) 25*18c1e2c8SRoland McGrath { 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) 96c3c9897cSLinus Torvalds switch (i) { 97c3c9897cSLinus Torvalds case 0: 98bb898558SAl Viro if (!n--) break; 99bb898558SAl Viro *args++ = regs->bx; 100c3c9897cSLinus Torvalds case 1: 101c3c9897cSLinus Torvalds if (!n--) break; 102c3c9897cSLinus Torvalds *args++ = regs->cx; 103c3c9897cSLinus Torvalds case 2: 104c3c9897cSLinus Torvalds if (!n--) break; 105c3c9897cSLinus Torvalds *args++ = regs->dx; 106c3c9897cSLinus Torvalds case 3: 107c3c9897cSLinus Torvalds if (!n--) break; 108c3c9897cSLinus Torvalds *args++ = regs->si; 109c3c9897cSLinus Torvalds case 4: 110c3c9897cSLinus Torvalds if (!n--) break; 111c3c9897cSLinus Torvalds *args++ = regs->di; 112c3c9897cSLinus Torvalds case 5: 113c3c9897cSLinus Torvalds if (!n--) break; 114c3c9897cSLinus Torvalds *args++ = regs->bp; 115c3c9897cSLinus 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 123c3c9897cSLinus Torvalds switch (i) { 124c3c9897cSLinus Torvalds case 0: 125bb898558SAl Viro if (!n--) break; 126bb898558SAl Viro *args++ = regs->di; 127c3c9897cSLinus Torvalds case 1: 128c3c9897cSLinus Torvalds if (!n--) break; 129c3c9897cSLinus Torvalds *args++ = regs->si; 130c3c9897cSLinus Torvalds case 2: 131c3c9897cSLinus Torvalds if (!n--) break; 132c3c9897cSLinus Torvalds *args++ = regs->dx; 133c3c9897cSLinus Torvalds case 3: 134c3c9897cSLinus Torvalds if (!n--) break; 135c3c9897cSLinus Torvalds *args++ = regs->r10; 136c3c9897cSLinus Torvalds case 4: 137c3c9897cSLinus Torvalds if (!n--) break; 138c3c9897cSLinus Torvalds *args++ = regs->r8; 139c3c9897cSLinus Torvalds case 5: 140c3c9897cSLinus Torvalds if (!n--) break; 141c3c9897cSLinus Torvalds *args++ = regs->r9; 142c3c9897cSLinus 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) 157c3c9897cSLinus Torvalds switch (i) { 158c3c9897cSLinus Torvalds case 0: 159bb898558SAl Viro if (!n--) break; 160bb898558SAl Viro regs->bx = *args++; 161c3c9897cSLinus Torvalds case 1: 162c3c9897cSLinus Torvalds if (!n--) break; 163c3c9897cSLinus Torvalds regs->cx = *args++; 164c3c9897cSLinus Torvalds case 2: 165c3c9897cSLinus Torvalds if (!n--) break; 166c3c9897cSLinus Torvalds regs->dx = *args++; 167c3c9897cSLinus Torvalds case 3: 168c3c9897cSLinus Torvalds if (!n--) break; 169c3c9897cSLinus Torvalds regs->si = *args++; 170c3c9897cSLinus Torvalds case 4: 171c3c9897cSLinus Torvalds if (!n--) break; 172c3c9897cSLinus Torvalds regs->di = *args++; 173c3c9897cSLinus Torvalds case 5: 174c3c9897cSLinus Torvalds if (!n--) break; 175c3c9897cSLinus Torvalds regs->bp = *args++; 176c3c9897cSLinus Torvalds case 6: 177bb898558SAl Viro if (!n--) break; 178bb898558SAl Viro default: 179bb898558SAl Viro BUG(); 180c3c9897cSLinus Torvalds break; 181bb898558SAl Viro } 182bb898558SAl Viro else 183bb898558SAl Viro # endif 184c3c9897cSLinus Torvalds switch (i) { 185c3c9897cSLinus Torvalds case 0: 186bb898558SAl Viro if (!n--) break; 187bb898558SAl Viro regs->di = *args++; 188c3c9897cSLinus Torvalds case 1: 189c3c9897cSLinus Torvalds if (!n--) break; 190c3c9897cSLinus Torvalds regs->si = *args++; 191c3c9897cSLinus Torvalds case 2: 192c3c9897cSLinus Torvalds if (!n--) break; 193c3c9897cSLinus Torvalds regs->dx = *args++; 194c3c9897cSLinus Torvalds case 3: 195c3c9897cSLinus Torvalds if (!n--) break; 196c3c9897cSLinus Torvalds regs->r10 = *args++; 197c3c9897cSLinus Torvalds case 4: 198c3c9897cSLinus Torvalds if (!n--) break; 199c3c9897cSLinus Torvalds regs->r8 = *args++; 200c3c9897cSLinus Torvalds case 5: 201c3c9897cSLinus Torvalds if (!n--) break; 202c3c9897cSLinus Torvalds regs->r9 = *args++; 203c3c9897cSLinus Torvalds case 6: 204bb898558SAl Viro if (!n--) break; 205bb898558SAl Viro default: 206bb898558SAl Viro BUG(); 207c3c9897cSLinus 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