diff options
Diffstat (limited to 'arch/blackfin/include/asm/syscall.h')
-rw-r--r-- | arch/blackfin/include/asm/syscall.h | 96 |
1 files changed, 96 insertions, 0 deletions
diff --git a/arch/blackfin/include/asm/syscall.h b/arch/blackfin/include/asm/syscall.h new file mode 100644 index 000000000000..4921a4815cce --- /dev/null +++ b/arch/blackfin/include/asm/syscall.h | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * Magic syscall break down functions | ||
3 | * | ||
4 | * Copyright 2010 Analog Devices Inc. | ||
5 | * | ||
6 | * Licensed under the GPL-2 or later. | ||
7 | */ | ||
8 | |||
9 | #ifndef __ASM_BLACKFIN_SYSCALL_H__ | ||
10 | #define __ASM_BLACKFIN_SYSCALL_H__ | ||
11 | |||
12 | /* | ||
13 | * Blackfin syscalls are simple: | ||
14 | * enter: | ||
15 | * p0: syscall number | ||
16 | * r{0,1,2,3,4,5}: syscall args 0,1,2,3,4,5 | ||
17 | * exit: | ||
18 | * r0: return/error value | ||
19 | */ | ||
20 | |||
21 | #include <linux/err.h> | ||
22 | #include <linux/sched.h> | ||
23 | #include <asm/ptrace.h> | ||
24 | |||
25 | static inline long | ||
26 | syscall_get_nr(struct task_struct *task, struct pt_regs *regs) | ||
27 | { | ||
28 | return regs->p0; | ||
29 | } | ||
30 | |||
31 | static inline void | ||
32 | syscall_rollback(struct task_struct *task, struct pt_regs *regs) | ||
33 | { | ||
34 | regs->p0 = regs->orig_p0; | ||
35 | } | ||
36 | |||
37 | static inline long | ||
38 | syscall_get_error(struct task_struct *task, struct pt_regs *regs) | ||
39 | { | ||
40 | return IS_ERR_VALUE(regs->r0) ? regs->r0 : 0; | ||
41 | } | ||
42 | |||
43 | static inline long | ||
44 | syscall_get_return_value(struct task_struct *task, struct pt_regs *regs) | ||
45 | { | ||
46 | return regs->r0; | ||
47 | } | ||
48 | |||
49 | static inline void | ||
50 | syscall_set_return_value(struct task_struct *task, struct pt_regs *regs, | ||
51 | int error, long val) | ||
52 | { | ||
53 | regs->r0 = error ? -error : val; | ||
54 | } | ||
55 | |||
56 | /** | ||
57 | * syscall_get_arguments() | ||
58 | * @task: unused | ||
59 | * @regs: the register layout to extract syscall arguments from | ||
60 | * @i: first syscall argument to extract | ||
61 | * @n: number of syscall arguments to extract | ||
62 | * @args: array to return the syscall arguments in | ||
63 | * | ||
64 | * args[0] gets i'th argument, args[n - 1] gets the i+n-1'th argument | ||
65 | */ | ||
66 | static inline void | ||
67 | syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, | ||
68 | unsigned int i, unsigned int n, unsigned long *args) | ||
69 | { | ||
70 | /* | ||
71 | * Assume the ptrace layout doesn't change -- r5 is first in memory, | ||
72 | * then r4, ..., then r0. So we simply reverse the ptrace register | ||
73 | * array in memory to store into the args array. | ||
74 | */ | ||
75 | long *aregs = ®s->r0 - i; | ||
76 | |||
77 | BUG_ON(i > 5 || i + n > 6); | ||
78 | |||
79 | while (n--) | ||
80 | *args++ = *aregs--; | ||
81 | } | ||
82 | |||
83 | /* See syscall_get_arguments() comments */ | ||
84 | static inline void | ||
85 | syscall_set_arguments(struct task_struct *task, struct pt_regs *regs, | ||
86 | unsigned int i, unsigned int n, const unsigned long *args) | ||
87 | { | ||
88 | long *aregs = ®s->r0 - i; | ||
89 | |||
90 | BUG_ON(i > 5 || i + n > 6); | ||
91 | |||
92 | while (n--) | ||
93 | *aregs-- = *args++; | ||
94 | } | ||
95 | |||
96 | #endif | ||