Commit | Line | Data |
---|---|---|
badcbf0e DM |
1 | #ifndef __ASM_SPARC_SYSCALL_H |
2 | #define __ASM_SPARC_SYSCALL_H | |
3 | ||
ce5d1128 | 4 | #include <uapi/linux/audit.h> |
badcbf0e | 5 | #include <linux/kernel.h> |
203f7907 | 6 | #include <linux/compat.h> |
badcbf0e DM |
7 | #include <linux/sched.h> |
8 | #include <asm/ptrace.h> | |
ce5d1128 | 9 | #include <asm/thread_info.h> |
badcbf0e | 10 | |
e7b8e675 MF |
11 | /* |
12 | * The syscall table always contains 32 bit pointers since we know that the | |
13 | * address of the function to be called is (way) below 4GB. So the "int" | |
14 | * type here is what we want [need] for both 32 bit and 64 bit systems. | |
15 | */ | |
16 | extern const unsigned int sys_call_table[]; | |
17 | ||
badcbf0e DM |
18 | /* The system call number is given by the user in %g1 */ |
19 | static inline long syscall_get_nr(struct task_struct *task, | |
20 | struct pt_regs *regs) | |
21 | { | |
22 | int syscall_p = pt_regs_is_syscall(regs); | |
23 | ||
24 | return (syscall_p ? regs->u_regs[UREG_G1] : -1L); | |
25 | } | |
26 | ||
27 | static inline void syscall_rollback(struct task_struct *task, | |
28 | struct pt_regs *regs) | |
29 | { | |
30 | /* XXX This needs some thought. On Sparc we don't | |
31 | * XXX save away the original %o0 value somewhere. | |
32 | * XXX Instead we hold it in register %l5 at the top | |
33 | * XXX level trap frame and pass this down to the signal | |
34 | * XXX dispatch code which is the only place that value | |
35 | * XXX ever was needed. | |
36 | */ | |
37 | } | |
38 | ||
39 | #ifdef CONFIG_SPARC32 | |
40 | static inline bool syscall_has_error(struct pt_regs *regs) | |
41 | { | |
42 | return (regs->psr & PSR_C) ? true : false; | |
43 | } | |
44 | static inline void syscall_set_error(struct pt_regs *regs) | |
45 | { | |
46 | regs->psr |= PSR_C; | |
47 | } | |
48 | static inline void syscall_clear_error(struct pt_regs *regs) | |
49 | { | |
50 | regs->psr &= ~PSR_C; | |
51 | } | |
52 | #else | |
53 | static inline bool syscall_has_error(struct pt_regs *regs) | |
54 | { | |
55 | return (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)) ? true : false; | |
56 | } | |
57 | static inline void syscall_set_error(struct pt_regs *regs) | |
58 | { | |
59 | regs->tstate |= (TSTATE_XCARRY | TSTATE_ICARRY); | |
60 | } | |
61 | static inline void syscall_clear_error(struct pt_regs *regs) | |
62 | { | |
63 | regs->tstate &= ~(TSTATE_XCARRY | TSTATE_ICARRY); | |
64 | } | |
65 | #endif | |
66 | ||
67 | static inline long syscall_get_error(struct task_struct *task, | |
68 | struct pt_regs *regs) | |
69 | { | |
70 | long val = regs->u_regs[UREG_I0]; | |
71 | ||
72 | return (syscall_has_error(regs) ? -val : 0); | |
73 | } | |
74 | ||
75 | static inline long syscall_get_return_value(struct task_struct *task, | |
76 | struct pt_regs *regs) | |
77 | { | |
78 | long val = regs->u_regs[UREG_I0]; | |
79 | ||
80 | return val; | |
81 | } | |
82 | ||
83 | static inline void syscall_set_return_value(struct task_struct *task, | |
84 | struct pt_regs *regs, | |
85 | int error, long val) | |
86 | { | |
87 | if (error) { | |
88 | syscall_set_error(regs); | |
89 | regs->u_regs[UREG_I0] = -error; | |
90 | } else { | |
91 | syscall_clear_error(regs); | |
92 | regs->u_regs[UREG_I0] = val; | |
93 | } | |
94 | } | |
95 | ||
96 | static inline void syscall_get_arguments(struct task_struct *task, | |
97 | struct pt_regs *regs, | |
98 | unsigned int i, unsigned int n, | |
99 | unsigned long *args) | |
100 | { | |
101 | int zero_extend = 0; | |
102 | unsigned int j; | |
103 | ||
104 | #ifdef CONFIG_SPARC64 | |
105 | if (test_tsk_thread_flag(task, TIF_32BIT)) | |
106 | zero_extend = 1; | |
107 | #endif | |
108 | ||
109 | for (j = 0; j < n; j++) { | |
110 | unsigned long val = regs->u_regs[UREG_I0 + i + j]; | |
111 | ||
112 | if (zero_extend) | |
113 | args[j] = (u32) val; | |
114 | else | |
115 | args[j] = val; | |
116 | } | |
117 | } | |
118 | ||
119 | static inline void syscall_set_arguments(struct task_struct *task, | |
120 | struct pt_regs *regs, | |
121 | unsigned int i, unsigned int n, | |
122 | const unsigned long *args) | |
123 | { | |
124 | unsigned int j; | |
125 | ||
126 | for (j = 0; j < n; j++) | |
127 | regs->u_regs[UREG_I0 + i + j] = args[j]; | |
128 | } | |
129 | ||
ce5d1128 EP |
130 | static inline int syscall_get_arch(void) |
131 | { | |
203f7907 AL |
132 | #if defined(CONFIG_SPARC64) && defined(CONFIG_COMPAT) |
133 | return in_compat_syscall() ? AUDIT_ARCH_SPARC : AUDIT_ARCH_SPARC64; | |
134 | #elif defined(CONFIG_SPARC64) | |
135 | return AUDIT_ARCH_SPARC64; | |
136 | #else | |
137 | return AUDIT_ARCH_SPARC; | |
138 | #endif | |
ce5d1128 EP |
139 | } |
140 | ||
badcbf0e | 141 | #endif /* __ASM_SPARC_SYSCALL_H */ |