xref: /openbmc/linux/arch/x86/include/asm/syscall.h (revision 37a8f7c38339b22b69876d6f5a0ab851565284e3)
1bb898558SAl Viro /*
2bb898558SAl Viro  * Access to user system call parameters and results
3bb898558SAl Viro  *
418c1e2c8SRoland 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 
16579ec9e1SEric Paris #include <uapi/linux/audit.h>
17bb898558SAl Viro #include <linux/sched.h>
18bb898558SAl Viro #include <linux/err.h>
1972142fd4SH. Peter Anvin #include <asm/asm-offsets.h>	/* For NR_syscalls */
20b7456536SWill Drewry #include <asm/thread_info.h>	/* for TS_COMPAT */
21fca460f9SH. Peter Anvin #include <asm/unistd.h>
22bb898558SAl Viro 
23eb974c62SAndy Lutomirski typedef asmlinkage long (*sys_call_ptr_t)(unsigned long, unsigned long,
24eb974c62SAndy Lutomirski 					  unsigned long, unsigned long,
25eb974c62SAndy Lutomirski 					  unsigned long, unsigned long);
261599e8fcSAndi Kleen extern const sys_call_ptr_t sys_call_table[];
27e7b8e675SMike Frysinger 
28034042ccSAndy Lutomirski #if defined(CONFIG_X86_32)
29034042ccSAndy Lutomirski #define ia32_sys_call_table sys_call_table
30034042ccSAndy Lutomirski #define __NR_syscall_compat_max __NR_syscall_max
31034042ccSAndy Lutomirski #define IA32_NR_syscalls NR_syscalls
32034042ccSAndy Lutomirski #endif
33034042ccSAndy Lutomirski 
34034042ccSAndy Lutomirski #if defined(CONFIG_IA32_EMULATION)
35034042ccSAndy Lutomirski extern const sys_call_ptr_t ia32_sys_call_table[];
36034042ccSAndy Lutomirski #endif
37034042ccSAndy Lutomirski 
38bb898558SAl Viro /*
3918c1e2c8SRoland McGrath  * Only the low 32 bits of orig_ax are meaningful, so we return int.
4018c1e2c8SRoland McGrath  * This importantly ignores the high bits on 64-bit, so comparisons
4118c1e2c8SRoland McGrath  * sign-extend the low 32 bits.
42bb898558SAl Viro  */
4318c1e2c8SRoland McGrath static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
4418c1e2c8SRoland McGrath {
458b4b9f27SPaul Moore 	return regs->orig_ax;
46bb898558SAl Viro }
47bb898558SAl Viro 
48bb898558SAl Viro static inline void syscall_rollback(struct task_struct *task,
49bb898558SAl Viro 				    struct pt_regs *regs)
50bb898558SAl Viro {
518b4b9f27SPaul Moore 	regs->ax = regs->orig_ax;
52bb898558SAl Viro }
53bb898558SAl Viro 
54bb898558SAl Viro static inline long syscall_get_error(struct task_struct *task,
55bb898558SAl Viro 				     struct pt_regs *regs)
56bb898558SAl Viro {
57bb898558SAl Viro 	unsigned long error = regs->ax;
58bb898558SAl Viro #ifdef CONFIG_IA32_EMULATION
59bb898558SAl Viro 	/*
60bb898558SAl Viro 	 * TS_COMPAT is set for 32-bit syscall entries and then
61bb898558SAl Viro 	 * remains set until we return to user mode.
62bb898558SAl Viro 	 */
63*37a8f7c3SAndy Lutomirski 	if (task->thread_info.status & (TS_COMPAT|TS_I386_REGS_POKED))
64bb898558SAl Viro 		/*
65bb898558SAl Viro 		 * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
66bb898558SAl Viro 		 * and will match correctly in comparisons.
67bb898558SAl Viro 		 */
68bb898558SAl Viro 		error = (long) (int) error;
69bb898558SAl Viro #endif
70bb898558SAl Viro 	return IS_ERR_VALUE(error) ? error : 0;
71bb898558SAl Viro }
72bb898558SAl Viro 
73bb898558SAl Viro static inline long syscall_get_return_value(struct task_struct *task,
74bb898558SAl Viro 					    struct pt_regs *regs)
75bb898558SAl Viro {
76bb898558SAl Viro 	return regs->ax;
77bb898558SAl Viro }
78bb898558SAl Viro 
79bb898558SAl Viro static inline void syscall_set_return_value(struct task_struct *task,
80bb898558SAl Viro 					    struct pt_regs *regs,
81bb898558SAl Viro 					    int error, long val)
82bb898558SAl Viro {
83bb898558SAl Viro 	regs->ax = (long) error ?: val;
84bb898558SAl Viro }
85bb898558SAl Viro 
86bb898558SAl Viro #ifdef CONFIG_X86_32
87bb898558SAl Viro 
88bb898558SAl Viro static inline void syscall_get_arguments(struct task_struct *task,
89bb898558SAl Viro 					 struct pt_regs *regs,
90bb898558SAl Viro 					 unsigned int i, unsigned int n,
91bb898558SAl Viro 					 unsigned long *args)
92bb898558SAl Viro {
93bb898558SAl Viro 	BUG_ON(i + n > 6);
94bb898558SAl Viro 	memcpy(args, &regs->bx + i, n * sizeof(args[0]));
95bb898558SAl Viro }
96bb898558SAl Viro 
97bb898558SAl Viro static inline void syscall_set_arguments(struct task_struct *task,
98bb898558SAl Viro 					 struct pt_regs *regs,
99bb898558SAl Viro 					 unsigned int i, unsigned int n,
100bb898558SAl Viro 					 const unsigned long *args)
101bb898558SAl Viro {
102bb898558SAl Viro 	BUG_ON(i + n > 6);
103bb898558SAl Viro 	memcpy(&regs->bx + i, args, n * sizeof(args[0]));
104bb898558SAl Viro }
105bb898558SAl Viro 
1065e937a9aSEric Paris static inline int syscall_get_arch(void)
107b7456536SWill Drewry {
108b7456536SWill Drewry 	return AUDIT_ARCH_I386;
109b7456536SWill Drewry }
110b7456536SWill Drewry 
111bb898558SAl Viro #else	 /* CONFIG_X86_64 */
112bb898558SAl Viro 
113bb898558SAl Viro static inline void syscall_get_arguments(struct task_struct *task,
114bb898558SAl Viro 					 struct pt_regs *regs,
115bb898558SAl Viro 					 unsigned int i, unsigned int n,
116bb898558SAl Viro 					 unsigned long *args)
117bb898558SAl Viro {
118bb898558SAl Viro # ifdef CONFIG_IA32_EMULATION
119*37a8f7c3SAndy Lutomirski 	if (task->thread_info.status & TS_COMPAT)
120c3c9897cSLinus Torvalds 		switch (i) {
121c3c9897cSLinus Torvalds 		case 0:
122bb898558SAl Viro 			if (!n--) break;
123bb898558SAl Viro 			*args++ = regs->bx;
124c3c9897cSLinus Torvalds 		case 1:
125c3c9897cSLinus Torvalds 			if (!n--) break;
126c3c9897cSLinus Torvalds 			*args++ = regs->cx;
127c3c9897cSLinus Torvalds 		case 2:
128c3c9897cSLinus Torvalds 			if (!n--) break;
129c3c9897cSLinus Torvalds 			*args++ = regs->dx;
130c3c9897cSLinus Torvalds 		case 3:
131c3c9897cSLinus Torvalds 			if (!n--) break;
132c3c9897cSLinus Torvalds 			*args++ = regs->si;
133c3c9897cSLinus Torvalds 		case 4:
134c3c9897cSLinus Torvalds 			if (!n--) break;
135c3c9897cSLinus Torvalds 			*args++ = regs->di;
136c3c9897cSLinus Torvalds 		case 5:
137c3c9897cSLinus Torvalds 			if (!n--) break;
138c3c9897cSLinus Torvalds 			*args++ = regs->bp;
139c3c9897cSLinus Torvalds 		case 6:
140bb898558SAl Viro 			if (!n--) break;
141bb898558SAl Viro 		default:
142bb898558SAl Viro 			BUG();
143bb898558SAl Viro 			break;
144bb898558SAl Viro 		}
145bb898558SAl Viro 	else
146bb898558SAl Viro # endif
147c3c9897cSLinus Torvalds 		switch (i) {
148c3c9897cSLinus Torvalds 		case 0:
149bb898558SAl Viro 			if (!n--) break;
150bb898558SAl Viro 			*args++ = regs->di;
151c3c9897cSLinus Torvalds 		case 1:
152c3c9897cSLinus Torvalds 			if (!n--) break;
153c3c9897cSLinus Torvalds 			*args++ = regs->si;
154c3c9897cSLinus Torvalds 		case 2:
155c3c9897cSLinus Torvalds 			if (!n--) break;
156c3c9897cSLinus Torvalds 			*args++ = regs->dx;
157c3c9897cSLinus Torvalds 		case 3:
158c3c9897cSLinus Torvalds 			if (!n--) break;
159c3c9897cSLinus Torvalds 			*args++ = regs->r10;
160c3c9897cSLinus Torvalds 		case 4:
161c3c9897cSLinus Torvalds 			if (!n--) break;
162c3c9897cSLinus Torvalds 			*args++ = regs->r8;
163c3c9897cSLinus Torvalds 		case 5:
164c3c9897cSLinus Torvalds 			if (!n--) break;
165c3c9897cSLinus Torvalds 			*args++ = regs->r9;
166c3c9897cSLinus Torvalds 		case 6:
167bb898558SAl Viro 			if (!n--) break;
168bb898558SAl Viro 		default:
169bb898558SAl Viro 			BUG();
170bb898558SAl Viro 			break;
171bb898558SAl Viro 		}
172bb898558SAl Viro }
173bb898558SAl Viro 
174bb898558SAl Viro static inline void syscall_set_arguments(struct task_struct *task,
175bb898558SAl Viro 					 struct pt_regs *regs,
176bb898558SAl Viro 					 unsigned int i, unsigned int n,
177bb898558SAl Viro 					 const unsigned long *args)
178bb898558SAl Viro {
179bb898558SAl Viro # ifdef CONFIG_IA32_EMULATION
180*37a8f7c3SAndy Lutomirski 	if (task->thread_info.status & TS_COMPAT)
181c3c9897cSLinus Torvalds 		switch (i) {
182c3c9897cSLinus Torvalds 		case 0:
183bb898558SAl Viro 			if (!n--) break;
184bb898558SAl Viro 			regs->bx = *args++;
185c3c9897cSLinus Torvalds 		case 1:
186c3c9897cSLinus Torvalds 			if (!n--) break;
187c3c9897cSLinus Torvalds 			regs->cx = *args++;
188c3c9897cSLinus Torvalds 		case 2:
189c3c9897cSLinus Torvalds 			if (!n--) break;
190c3c9897cSLinus Torvalds 			regs->dx = *args++;
191c3c9897cSLinus Torvalds 		case 3:
192c3c9897cSLinus Torvalds 			if (!n--) break;
193c3c9897cSLinus Torvalds 			regs->si = *args++;
194c3c9897cSLinus Torvalds 		case 4:
195c3c9897cSLinus Torvalds 			if (!n--) break;
196c3c9897cSLinus Torvalds 			regs->di = *args++;
197c3c9897cSLinus Torvalds 		case 5:
198c3c9897cSLinus Torvalds 			if (!n--) break;
199c3c9897cSLinus Torvalds 			regs->bp = *args++;
200c3c9897cSLinus Torvalds 		case 6:
201bb898558SAl Viro 			if (!n--) break;
202bb898558SAl Viro 		default:
203bb898558SAl Viro 			BUG();
204c3c9897cSLinus Torvalds 			break;
205bb898558SAl Viro 		}
206bb898558SAl Viro 	else
207bb898558SAl Viro # endif
208c3c9897cSLinus Torvalds 		switch (i) {
209c3c9897cSLinus Torvalds 		case 0:
210bb898558SAl Viro 			if (!n--) break;
211bb898558SAl Viro 			regs->di = *args++;
212c3c9897cSLinus Torvalds 		case 1:
213c3c9897cSLinus Torvalds 			if (!n--) break;
214c3c9897cSLinus Torvalds 			regs->si = *args++;
215c3c9897cSLinus Torvalds 		case 2:
216c3c9897cSLinus Torvalds 			if (!n--) break;
217c3c9897cSLinus Torvalds 			regs->dx = *args++;
218c3c9897cSLinus Torvalds 		case 3:
219c3c9897cSLinus Torvalds 			if (!n--) break;
220c3c9897cSLinus Torvalds 			regs->r10 = *args++;
221c3c9897cSLinus Torvalds 		case 4:
222c3c9897cSLinus Torvalds 			if (!n--) break;
223c3c9897cSLinus Torvalds 			regs->r8 = *args++;
224c3c9897cSLinus Torvalds 		case 5:
225c3c9897cSLinus Torvalds 			if (!n--) break;
226c3c9897cSLinus Torvalds 			regs->r9 = *args++;
227c3c9897cSLinus Torvalds 		case 6:
228bb898558SAl Viro 			if (!n--) break;
229bb898558SAl Viro 		default:
230bb898558SAl Viro 			BUG();
231c3c9897cSLinus Torvalds 			break;
232bb898558SAl Viro 		}
233bb898558SAl Viro }
234bb898558SAl Viro 
2355e937a9aSEric Paris static inline int syscall_get_arch(void)
236b7456536SWill Drewry {
237b9d989c7SAndy Lutomirski 	/* x32 tasks should be considered AUDIT_ARCH_X86_64. */
238b9d989c7SAndy Lutomirski 	return in_ia32_syscall() ? AUDIT_ARCH_I386 : AUDIT_ARCH_X86_64;
239b7456536SWill Drewry }
240bb898558SAl Viro #endif	/* CONFIG_X86_32 */
241bb898558SAl Viro 
2425e1b0075SH. Peter Anvin #endif	/* _ASM_X86_SYSCALL_H */
243