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
extern const unsigned long sys_call_table[];

R
Roland McGrath 已提交
25 26 27 28 29 30
/*
 * 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 已提交
31
{
32
	return regs->orig_ax & __SYSCALL_MASK;
R
Roland McGrath 已提交
33 34 35 36 37
}

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

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
57
	return IS_ERR_VALUE(error) ? error : 0;
R
Roland McGrath 已提交
58 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
}

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]));
}

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

R
Roland McGrath 已提交
99 100 101 102 103 104 105 106 107
#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 已提交
108 109
		switch (i) {
		case 0:
R
Roland McGrath 已提交
110
			if (!n--) break;
R
Roland McGrath 已提交
111 112
			*args++ = regs->bx;
		case 1:
R
Roland McGrath 已提交
113
			if (!n--) break;
R
Roland McGrath 已提交
114 115
			*args++ = regs->cx;
		case 2:
R
Roland McGrath 已提交
116
			if (!n--) break;
R
Roland McGrath 已提交
117
			*args++ = regs->dx;
R
Roland McGrath 已提交
118 119
		case 3:
			if (!n--) break;
R
Roland McGrath 已提交
120 121
			*args++ = regs->si;
		case 4:
R
Roland McGrath 已提交
122
			if (!n--) break;
R
Roland McGrath 已提交
123 124
			*args++ = regs->di;
		case 5:
R
Roland McGrath 已提交
125
			if (!n--) break;
R
Roland McGrath 已提交
126 127
			*args++ = regs->bp;
		case 6:
R
Roland McGrath 已提交
128 129 130 131 132 133 134
			if (!n--) break;
		default:
			BUG();
			break;
		}
	else
# endif
R
Roland McGrath 已提交
135 136
		switch (i) {
		case 0:
R
Roland McGrath 已提交
137
			if (!n--) break;
R
Roland McGrath 已提交
138 139
			*args++ = regs->di;
		case 1:
R
Roland McGrath 已提交
140
			if (!n--) break;
R
Roland McGrath 已提交
141 142
			*args++ = regs->si;
		case 2:
R
Roland McGrath 已提交
143
			if (!n--) break;
R
Roland McGrath 已提交
144
			*args++ = regs->dx;
R
Roland McGrath 已提交
145 146
		case 3:
			if (!n--) break;
R
Roland McGrath 已提交
147 148
			*args++ = regs->r10;
		case 4:
R
Roland McGrath 已提交
149
			if (!n--) break;
R
Roland McGrath 已提交
150 151
			*args++ = regs->r8;
		case 5:
R
Roland McGrath 已提交
152
			if (!n--) break;
R
Roland McGrath 已提交
153 154
			*args++ = regs->r9;
		case 6:
R
Roland McGrath 已提交
155 156 157 158 159 160 161 162 163 164 165 166 167 168
			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 已提交
169 170
		switch (i) {
		case 0:
R
Roland McGrath 已提交
171
			if (!n--) break;
R
Roland McGrath 已提交
172 173
			regs->bx = *args++;
		case 1:
R
Roland McGrath 已提交
174
			if (!n--) break;
R
Roland McGrath 已提交
175 176
			regs->cx = *args++;
		case 2:
R
Roland McGrath 已提交
177
			if (!n--) break;
R
Roland McGrath 已提交
178
			regs->dx = *args++;
R
Roland McGrath 已提交
179 180
		case 3:
			if (!n--) break;
R
Roland McGrath 已提交
181 182
			regs->si = *args++;
		case 4:
R
Roland McGrath 已提交
183
			if (!n--) break;
R
Roland McGrath 已提交
184 185
			regs->di = *args++;
		case 5:
R
Roland McGrath 已提交
186
			if (!n--) break;
R
Roland McGrath 已提交
187 188
			regs->bp = *args++;
		case 6:
R
Roland McGrath 已提交
189 190 191
			if (!n--) break;
		default:
			BUG();
R
Roland McGrath 已提交
192
			break;
R
Roland McGrath 已提交
193 194 195
		}
	else
# endif
R
Roland McGrath 已提交
196 197
		switch (i) {
		case 0:
R
Roland McGrath 已提交
198
			if (!n--) break;
R
Roland McGrath 已提交
199 200
			regs->di = *args++;
		case 1:
R
Roland McGrath 已提交
201
			if (!n--) break;
R
Roland McGrath 已提交
202 203
			regs->si = *args++;
		case 2:
R
Roland McGrath 已提交
204
			if (!n--) break;
R
Roland McGrath 已提交
205
			regs->dx = *args++;
R
Roland McGrath 已提交
206 207
		case 3:
			if (!n--) break;
R
Roland McGrath 已提交
208 209
			regs->r10 = *args++;
		case 4:
R
Roland McGrath 已提交
210
			if (!n--) break;
R
Roland McGrath 已提交
211 212
			regs->r8 = *args++;
		case 5:
R
Roland McGrath 已提交
213
			if (!n--) break;
R
Roland McGrath 已提交
214 215
			regs->r9 = *args++;
		case 6:
R
Roland McGrath 已提交
216 217 218
			if (!n--) break;
		default:
			BUG();
R
Roland McGrath 已提交
219
			break;
R
Roland McGrath 已提交
220 221 222
		}
}

223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241
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 已提交
242 243
#endif	/* CONFIG_X86_32 */

244
#endif	/* _ASM_X86_SYSCALL_H */