diff options
author | David S. Miller <davem@davemloft.net> | 2008-07-27 03:53:10 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-07-27 20:31:48 -0400 |
commit | badcbf0e8654c4a4ca51fe46c75a70376e83c1ef (patch) | |
tree | 630b9fc4e0bfc277703a9413c80af5e112667e76 /arch/sparc | |
parent | 73ccefab8a6590bb3d5b44c046010139108ab7ca (diff) |
sparc: Add asm/syscall.h
Based upon a patch by Roland McGrath.
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc')
-rw-r--r-- | arch/sparc/include/asm/syscall.h | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/arch/sparc/include/asm/syscall.h b/arch/sparc/include/asm/syscall.h new file mode 100644 index 000000000000..7486c605e23c --- /dev/null +++ b/arch/sparc/include/asm/syscall.h | |||
@@ -0,0 +1,120 @@ | |||
1 | #ifndef __ASM_SPARC_SYSCALL_H | ||
2 | #define __ASM_SPARC_SYSCALL_H | ||
3 | |||
4 | #include <linux/kernel.h> | ||
5 | #include <linux/sched.h> | ||
6 | #include <asm/ptrace.h> | ||
7 | |||
8 | /* The system call number is given by the user in %g1 */ | ||
9 | static inline long syscall_get_nr(struct task_struct *task, | ||
10 | struct pt_regs *regs) | ||
11 | { | ||
12 | int syscall_p = pt_regs_is_syscall(regs); | ||
13 | |||
14 | return (syscall_p ? regs->u_regs[UREG_G1] : -1L); | ||
15 | } | ||
16 | |||
17 | static inline void syscall_rollback(struct task_struct *task, | ||
18 | struct pt_regs *regs) | ||
19 | { | ||
20 | /* XXX This needs some thought. On Sparc we don't | ||
21 | * XXX save away the original %o0 value somewhere. | ||
22 | * XXX Instead we hold it in register %l5 at the top | ||
23 | * XXX level trap frame and pass this down to the signal | ||
24 | * XXX dispatch code which is the only place that value | ||
25 | * XXX ever was needed. | ||
26 | */ | ||
27 | } | ||
28 | |||
29 | #ifdef CONFIG_SPARC32 | ||
30 | static inline bool syscall_has_error(struct pt_regs *regs) | ||
31 | { | ||
32 | return (regs->psr & PSR_C) ? true : false; | ||
33 | } | ||
34 | static inline void syscall_set_error(struct pt_regs *regs) | ||
35 | { | ||
36 | regs->psr |= PSR_C; | ||
37 | } | ||
38 | static inline void syscall_clear_error(struct pt_regs *regs) | ||
39 | { | ||
40 | regs->psr &= ~PSR_C; | ||
41 | } | ||
42 | #else | ||
43 | static inline bool syscall_has_error(struct pt_regs *regs) | ||
44 | { | ||
45 | return (regs->tstate & (TSTATE_XCARRY | TSTATE_ICARRY)) ? true : false; | ||
46 | } | ||
47 | static inline void syscall_set_error(struct pt_regs *regs) | ||
48 | { | ||
49 | regs->tstate |= (TSTATE_XCARRY | TSTATE_ICARRY); | ||
50 | } | ||
51 | static inline void syscall_clear_error(struct pt_regs *regs) | ||
52 | { | ||
53 | regs->tstate &= ~(TSTATE_XCARRY | TSTATE_ICARRY); | ||
54 | } | ||
55 | #endif | ||
56 | |||
57 | static inline long syscall_get_error(struct task_struct *task, | ||
58 | struct pt_regs *regs) | ||
59 | { | ||
60 | long val = regs->u_regs[UREG_I0]; | ||
61 | |||
62 | return (syscall_has_error(regs) ? -val : 0); | ||
63 | } | ||
64 | |||
65 | static inline long syscall_get_return_value(struct task_struct *task, | ||
66 | struct pt_regs *regs) | ||
67 | { | ||
68 | long val = regs->u_regs[UREG_I0]; | ||
69 | |||
70 | return val; | ||
71 | } | ||
72 | |||
73 | static inline void syscall_set_return_value(struct task_struct *task, | ||
74 | struct pt_regs *regs, | ||
75 | int error, long val) | ||
76 | { | ||
77 | if (error) { | ||
78 | syscall_set_error(regs); | ||
79 | regs->u_regs[UREG_I0] = -error; | ||
80 | } else { | ||
81 | syscall_clear_error(regs); | ||
82 | regs->u_regs[UREG_I0] = val; | ||
83 | } | ||
84 | } | ||
85 | |||
86 | static inline void syscall_get_arguments(struct task_struct *task, | ||
87 | struct pt_regs *regs, | ||
88 | unsigned int i, unsigned int n, | ||
89 | unsigned long *args) | ||
90 | { | ||
91 | int zero_extend = 0; | ||
92 | unsigned int j; | ||
93 | |||
94 | #ifdef CONFIG_SPARC64 | ||
95 | if (test_tsk_thread_flag(task, TIF_32BIT)) | ||
96 | zero_extend = 1; | ||
97 | #endif | ||
98 | |||
99 | for (j = 0; j < n; j++) { | ||
100 | unsigned long val = regs->u_regs[UREG_I0 + i + j]; | ||
101 | |||
102 | if (zero_extend) | ||
103 | args[j] = (u32) val; | ||
104 | else | ||
105 | args[j] = val; | ||
106 | } | ||
107 | } | ||
108 | |||
109 | static inline void syscall_set_arguments(struct task_struct *task, | ||
110 | struct pt_regs *regs, | ||
111 | unsigned int i, unsigned int n, | ||
112 | const unsigned long *args) | ||
113 | { | ||
114 | unsigned int j; | ||
115 | |||
116 | for (j = 0; j < n; j++) | ||
117 | regs->u_regs[UREG_I0 + i + j] = args[j]; | ||
118 | } | ||
119 | |||
120 | #endif /* __ASM_SPARC_SYSCALL_H */ | ||