syscall.h 5.2 KB
Newer Older
R
Roland McGrath 已提交
1 2 3
/*
 * Access to user system call parameters and results
 *
R
Roland McGrath 已提交
4
 * Copyright (C) 2008-2009 Red Hat, Inc.  All rights reserved.
R
Roland McGrath 已提交
5 6 7 8 9 10 11 12
 *
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU General Public License v.2.
 *
 * See asm-generic/syscall.h for descriptions of what we must do here.
 */

13 14
#ifndef _ASM_X86_SYSCALL_H
#define _ASM_X86_SYSCALL_H
R
Roland McGrath 已提交
15

16
#include <linux/audit.h>
R
Roland McGrath 已提交
17
#include <linux/sched.h>
18
#include <linux/err.h>
19
#include <asm/asm-offsets.h>	/* For NR_syscalls */
20
#include <asm/thread_info.h>	/* for TS_COMPAT */
21
#include <asm/unistd.h>
R
Roland McGrath 已提交
22

23 24
typedef void (*sys_call_ptr_t)(void);
extern const sys_call_ptr_t sys_call_table[];
25

R
Roland McGrath 已提交
26 27 28 29 30 31
/*
 * Only the low 32 bits of orig_ax are meaningful, so we return int.
 * This importantly ignores the high bits on 64-bit, so comparisons
 * sign-extend the low 32 bits.
 */
static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
R
Roland McGrath 已提交
32
{
33
	return regs->orig_ax;
R
Roland McGrath 已提交
34 35 36 37 38
}

static inline void syscall_rollback(struct task_struct *task,
				    struct pt_regs *regs)
{
39
	regs->ax = regs->orig_ax;
R
Roland McGrath 已提交
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
}

static inline long syscall_get_error(struct task_struct *task,
				     struct pt_regs *regs)
{
	unsigned long error = regs->ax;
#ifdef CONFIG_IA32_EMULATION
	/*
	 * TS_COMPAT is set for 32-bit syscall entries and then
	 * remains set until we return to user mode.
	 */
	if (task_thread_info(task)->status & TS_COMPAT)
		/*
		 * Sign-extend the value so (int)-EFOO becomes (long)-EFOO
		 * and will match correctly in comparisons.
		 */
		error = (long) (int) error;
#endif
58
	return IS_ERR_VALUE(error) ? error : 0;
R
Roland McGrath 已提交
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93
}

static inline long syscall_get_return_value(struct task_struct *task,
					    struct pt_regs *regs)
{
	return regs->ax;
}

static inline void syscall_set_return_value(struct task_struct *task,
					    struct pt_regs *regs,
					    int error, long val)
{
	regs->ax = (long) error ?: val;
}

#ifdef CONFIG_X86_32

static inline void syscall_get_arguments(struct task_struct *task,
					 struct pt_regs *regs,
					 unsigned int i, unsigned int n,
					 unsigned long *args)
{
	BUG_ON(i + n > 6);
	memcpy(args, &regs->bx + i, n * sizeof(args[0]));
}

static inline void syscall_set_arguments(struct task_struct *task,
					 struct pt_regs *regs,
					 unsigned int i, unsigned int n,
					 const unsigned long *args)
{
	BUG_ON(i + n > 6);
	memcpy(&regs->bx + i, args, n * sizeof(args[0]));
}

94 95 96 97 98 99
static inline int syscall_get_arch(struct task_struct *task,
				   struct pt_regs *regs)
{
	return AUDIT_ARCH_I386;
}

R
Roland McGrath 已提交
100 101 102 103 104 105 106 107 108
#else	 /* CONFIG_X86_64 */

static inline void syscall_get_arguments(struct task_struct *task,
					 struct pt_regs *regs,
					 unsigned int i, unsigned int n,
					 unsigned long *args)
{
# ifdef CONFIG_IA32_EMULATION
	if (task_thread_info(task)->status & TS_COMPAT)
R
Roland McGrath 已提交
109 110
		switch (i) {
		case 0:
R
Roland McGrath 已提交
111
			if (!n--) break;
R
Roland McGrath 已提交
112 113
			*args++ = regs->bx;
		case 1:
R
Roland McGrath 已提交
114
			if (!n--) break;
R
Roland McGrath 已提交
115 116
			*args++ = regs->cx;
		case 2:
R
Roland McGrath 已提交
117
			if (!n--) break;
R
Roland McGrath 已提交
118
			*args++ = regs->dx;
R
Roland McGrath 已提交
119 120
		case 3:
			if (!n--) break;
R
Roland McGrath 已提交
121 122
			*args++ = regs->si;
		case 4:
R
Roland McGrath 已提交
123
			if (!n--) break;
R
Roland McGrath 已提交
124 125
			*args++ = regs->di;
		case 5:
R
Roland McGrath 已提交
126
			if (!n--) break;
R
Roland McGrath 已提交
127 128
			*args++ = regs->bp;
		case 6:
R
Roland McGrath 已提交
129 130 131 132 133 134 135
			if (!n--) break;
		default:
			BUG();
			break;
		}
	else
# endif
R
Roland McGrath 已提交
136 137
		switch (i) {
		case 0:
R
Roland McGrath 已提交
138
			if (!n--) break;
R
Roland McGrath 已提交
139 140
			*args++ = regs->di;
		case 1:
R
Roland McGrath 已提交
141
			if (!n--) break;
R
Roland McGrath 已提交
142 143
			*args++ = regs->si;
		case 2:
R
Roland McGrath 已提交
144
			if (!n--) break;
R
Roland McGrath 已提交
145
			*args++ = regs->dx;
R
Roland McGrath 已提交
146 147
		case 3:
			if (!n--) break;
R
Roland McGrath 已提交
148 149
			*args++ = regs->r10;
		case 4:
R
Roland McGrath 已提交
150
			if (!n--) break;
R
Roland McGrath 已提交
151 152
			*args++ = regs->r8;
		case 5:
R
Roland McGrath 已提交
153
			if (!n--) break;
R
Roland McGrath 已提交
154 155
			*args++ = regs->r9;
		case 6:
R
Roland McGrath 已提交
156 157 158 159 160 161 162 163 164 165 166 167 168 169
			if (!n--) break;
		default:
			BUG();
			break;
		}
}

static inline void syscall_set_arguments(struct task_struct *task,
					 struct pt_regs *regs,
					 unsigned int i, unsigned int n,
					 const unsigned long *args)
{
# ifdef CONFIG_IA32_EMULATION
	if (task_thread_info(task)->status & TS_COMPAT)
R
Roland McGrath 已提交
170 171
		switch (i) {
		case 0:
R
Roland McGrath 已提交
172
			if (!n--) break;
R
Roland McGrath 已提交
173 174
			regs->bx = *args++;
		case 1:
R
Roland McGrath 已提交
175
			if (!n--) break;
R
Roland McGrath 已提交
176 177
			regs->cx = *args++;
		case 2:
R
Roland McGrath 已提交
178
			if (!n--) break;
R
Roland McGrath 已提交
179
			regs->dx = *args++;
R
Roland McGrath 已提交
180 181
		case 3:
			if (!n--) break;
R
Roland McGrath 已提交
182 183
			regs->si = *args++;
		case 4:
R
Roland McGrath 已提交
184
			if (!n--) break;
R
Roland McGrath 已提交
185 186
			regs->di = *args++;
		case 5:
R
Roland McGrath 已提交
187
			if (!n--) break;
R
Roland McGrath 已提交
188 189
			regs->bp = *args++;
		case 6:
R
Roland McGrath 已提交
190 191 192
			if (!n--) break;
		default:
			BUG();
R
Roland McGrath 已提交
193
			break;
R
Roland McGrath 已提交
194 195 196
		}
	else
# endif
R
Roland McGrath 已提交
197 198
		switch (i) {
		case 0:
R
Roland McGrath 已提交
199
			if (!n--) break;
R
Roland McGrath 已提交
200 201
			regs->di = *args++;
		case 1:
R
Roland McGrath 已提交
202
			if (!n--) break;
R
Roland McGrath 已提交
203 204
			regs->si = *args++;
		case 2:
R
Roland McGrath 已提交
205
			if (!n--) break;
R
Roland McGrath 已提交
206
			regs->dx = *args++;
R
Roland McGrath 已提交
207 208
		case 3:
			if (!n--) break;
R
Roland McGrath 已提交
209 210
			regs->r10 = *args++;
		case 4:
R
Roland McGrath 已提交
211
			if (!n--) break;
R
Roland McGrath 已提交
212 213
			regs->r8 = *args++;
		case 5:
R
Roland McGrath 已提交
214
			if (!n--) break;
R
Roland McGrath 已提交
215 216
			regs->r9 = *args++;
		case 6:
R
Roland McGrath 已提交
217 218 219
			if (!n--) break;
		default:
			BUG();
R
Roland McGrath 已提交
220
			break;
R
Roland McGrath 已提交
221 222 223
		}
}

224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242
static inline int syscall_get_arch(struct task_struct *task,
				   struct pt_regs *regs)
{
#ifdef CONFIG_IA32_EMULATION
	/*
	 * TS_COMPAT is set for 32-bit syscall entry and then
	 * remains set until we return to user mode.
	 *
	 * TIF_IA32 tasks should always have TS_COMPAT set at
	 * system call time.
	 *
	 * x32 tasks should be considered AUDIT_ARCH_X86_64.
	 */
	if (task_thread_info(task)->status & TS_COMPAT)
		return AUDIT_ARCH_I386;
#endif
	/* Both x32 and x86_64 are considered "64-bit". */
	return AUDIT_ARCH_X86_64;
}
R
Roland McGrath 已提交
243 244
#endif	/* CONFIG_X86_32 */

245
#endif	/* _ASM_X86_SYSCALL_H */