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