]>
Commit | Line | Data |
---|---|---|
f1ba1285 RM |
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_SYSCALL_H | |
14 | #define _ASM_SYSCALL_H 1 | |
15 | ||
ce5d1128 | 16 | #include <uapi/linux/audit.h> |
f1ba1285 | 17 | #include <linux/sched.h> |
75dddcbd | 18 | #include <linux/thread_info.h> |
f1ba1285 | 19 | |
02424d89 IM |
20 | /* ftrace syscalls requires exporting the sys_call_table */ |
21 | #ifdef CONFIG_FTRACE_SYSCALLS | |
1028ccf5 | 22 | extern const unsigned long sys_call_table[]; |
02424d89 IM |
23 | #endif /* CONFIG_FTRACE_SYSCALLS */ |
24 | ||
e9fbe686 | 25 | static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) |
f1ba1285 | 26 | { |
e9fbe686 ME |
27 | /* |
28 | * Note that we are returning an int here. That means 0xffffffff, ie. | |
29 | * 32-bit negative 1, will be interpreted as -1 on a 64-bit kernel. | |
30 | * This is important for seccomp so that compat tasks can set r0 = -1 | |
31 | * to reject the syscall. | |
32 | */ | |
33 | return TRAP(regs) == 0xc00 ? regs->gpr[0] : -1; | |
f1ba1285 RM |
34 | } |
35 | ||
36 | static inline void syscall_rollback(struct task_struct *task, | |
37 | struct pt_regs *regs) | |
38 | { | |
39 | regs->gpr[3] = regs->orig_gpr3; | |
40 | } | |
41 | ||
f1ba1285 RM |
42 | static inline long syscall_get_return_value(struct task_struct *task, |
43 | struct pt_regs *regs) | |
44 | { | |
45 | return regs->gpr[3]; | |
46 | } | |
47 | ||
48 | static inline void syscall_set_return_value(struct task_struct *task, | |
49 | struct pt_regs *regs, | |
50 | int error, long val) | |
51 | { | |
1b1a3702 ME |
52 | /* |
53 | * In the general case it's not obvious that we must deal with CCR | |
54 | * here, as the syscall exit path will also do that for us. However | |
55 | * there are some places, eg. the signal code, which check ccr to | |
56 | * decide if the value in r3 is actually an error. | |
57 | */ | |
f1ba1285 | 58 | if (error) { |
409d241b | 59 | regs->ccr |= 0x10000000L; |
1b1a3702 | 60 | regs->gpr[3] = error; |
f1ba1285 | 61 | } else { |
409d241b | 62 | regs->ccr &= ~0x10000000L; |
f1ba1285 RM |
63 | regs->gpr[3] = val; |
64 | } | |
65 | } | |
66 | ||
67 | static inline void syscall_get_arguments(struct task_struct *task, | |
68 | struct pt_regs *regs, | |
69 | unsigned int i, unsigned int n, | |
70 | unsigned long *args) | |
71 | { | |
1cb9839b | 72 | unsigned long val, mask = -1UL; |
a7657844 | 73 | |
f1ba1285 | 74 | BUG_ON(i + n > 6); |
a7657844 ME |
75 | |
76 | #ifdef CONFIG_COMPAT | |
77 | if (test_tsk_thread_flag(task, TIF_32BIT)) | |
78 | mask = 0xffffffff; | |
f1ba1285 | 79 | #endif |
1cb9839b ME |
80 | while (n--) { |
81 | if (n == 0 && i == 0) | |
82 | val = regs->orig_gpr3; | |
83 | else | |
84 | val = regs->gpr[3 + i + n]; | |
85 | ||
86 | args[n] = val & mask; | |
87 | } | |
f1ba1285 RM |
88 | } |
89 | ||
90 | static inline void syscall_set_arguments(struct task_struct *task, | |
91 | struct pt_regs *regs, | |
92 | unsigned int i, unsigned int n, | |
93 | const unsigned long *args) | |
94 | { | |
95 | BUG_ON(i + n > 6); | |
96 | memcpy(®s->gpr[3 + i], args, n * sizeof(args[0])); | |
1cb9839b ME |
97 | |
98 | /* Also copy the first argument into orig_gpr3 */ | |
99 | if (i == 0 && n > 0) | |
100 | regs->orig_gpr3 = args[0]; | |
f1ba1285 RM |
101 | } |
102 | ||
ce5d1128 EP |
103 | static inline int syscall_get_arch(void) |
104 | { | |
63f13448 RGB |
105 | int arch = is_32bit_task() ? AUDIT_ARCH_PPC : AUDIT_ARCH_PPC64; |
106 | #ifdef __LITTLE_ENDIAN__ | |
107 | arch |= __AUDIT_ARCH_LE; | |
108 | #endif | |
109 | return arch; | |
ce5d1128 | 110 | } |
f1ba1285 | 111 | #endif /* _ASM_SYSCALL_H */ |