Commit | Line | Data |
---|---|---|
d8f8b844 MS |
1 | /* |
2 | * Access to user system call parameters and results | |
3 | * | |
4 | * See asm-generic/syscall.h for function descriptions. | |
5 | * | |
6 | * Copyright (C) 2015 Mickaël Salaün <mic@digikod.net> | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or modify | |
9 | * it under the terms of the GNU General Public License version 2 as | |
10 | * published by the Free Software Foundation. | |
11 | */ | |
12 | ||
13 | #ifndef __UM_SYSCALL_GENERIC_H | |
14 | #define __UM_SYSCALL_GENERIC_H | |
15 | ||
16 | #include <asm/ptrace.h> | |
17 | #include <linux/err.h> | |
18 | #include <linux/sched.h> | |
19 | #include <sysdep/ptrace.h> | |
20 | ||
21 | static inline int syscall_get_nr(struct task_struct *task, struct pt_regs *regs) | |
22 | { | |
23 | ||
24 | return PT_REGS_SYSCALL_NR(regs); | |
25 | } | |
26 | ||
27 | static inline void syscall_rollback(struct task_struct *task, | |
28 | struct pt_regs *regs) | |
29 | { | |
30 | /* do nothing */ | |
31 | } | |
32 | ||
33 | static inline long syscall_get_error(struct task_struct *task, | |
34 | struct pt_regs *regs) | |
35 | { | |
36 | const long error = regs_return_value(regs); | |
37 | ||
38 | return IS_ERR_VALUE(error) ? error : 0; | |
39 | } | |
40 | ||
41 | static inline long syscall_get_return_value(struct task_struct *task, | |
42 | struct pt_regs *regs) | |
43 | { | |
44 | return regs_return_value(regs); | |
45 | } | |
46 | ||
47 | static inline void syscall_set_return_value(struct task_struct *task, | |
48 | struct pt_regs *regs, | |
49 | int error, long val) | |
50 | { | |
51 | PT_REGS_SET_SYSCALL_RETURN(regs, (long) error ?: val); | |
52 | } | |
53 | ||
54 | static inline void syscall_get_arguments(struct task_struct *task, | |
55 | struct pt_regs *regs, | |
56 | unsigned int i, unsigned int n, | |
57 | unsigned long *args) | |
58 | { | |
59 | const struct uml_pt_regs *r = ®s->regs; | |
60 | ||
61 | switch (i) { | |
62 | case 0: | |
63 | if (!n--) | |
64 | break; | |
65 | *args++ = UPT_SYSCALL_ARG1(r); | |
66 | case 1: | |
67 | if (!n--) | |
68 | break; | |
69 | *args++ = UPT_SYSCALL_ARG2(r); | |
70 | case 2: | |
71 | if (!n--) | |
72 | break; | |
73 | *args++ = UPT_SYSCALL_ARG3(r); | |
74 | case 3: | |
75 | if (!n--) | |
76 | break; | |
77 | *args++ = UPT_SYSCALL_ARG4(r); | |
78 | case 4: | |
79 | if (!n--) | |
80 | break; | |
81 | *args++ = UPT_SYSCALL_ARG5(r); | |
82 | case 5: | |
83 | if (!n--) | |
84 | break; | |
85 | *args++ = UPT_SYSCALL_ARG6(r); | |
86 | case 6: | |
87 | if (!n--) | |
88 | break; | |
89 | default: | |
90 | BUG(); | |
91 | break; | |
92 | } | |
93 | } | |
94 | ||
95 | static inline void syscall_set_arguments(struct task_struct *task, | |
96 | struct pt_regs *regs, | |
97 | unsigned int i, unsigned int n, | |
98 | const unsigned long *args) | |
99 | { | |
100 | struct uml_pt_regs *r = ®s->regs; | |
101 | ||
102 | switch (i) { | |
103 | case 0: | |
104 | if (!n--) | |
105 | break; | |
106 | UPT_SYSCALL_ARG1(r) = *args++; | |
107 | case 1: | |
108 | if (!n--) | |
109 | break; | |
110 | UPT_SYSCALL_ARG2(r) = *args++; | |
111 | case 2: | |
112 | if (!n--) | |
113 | break; | |
114 | UPT_SYSCALL_ARG3(r) = *args++; | |
115 | case 3: | |
116 | if (!n--) | |
117 | break; | |
118 | UPT_SYSCALL_ARG4(r) = *args++; | |
119 | case 4: | |
120 | if (!n--) | |
121 | break; | |
122 | UPT_SYSCALL_ARG5(r) = *args++; | |
123 | case 5: | |
124 | if (!n--) | |
125 | break; | |
126 | UPT_SYSCALL_ARG6(r) = *args++; | |
127 | case 6: | |
128 | if (!n--) | |
129 | break; | |
130 | default: | |
131 | BUG(); | |
132 | break; | |
133 | } | |
134 | } | |
135 | ||
136 | /* See arch/x86/um/asm/syscall.h for syscall_get_arch() definition. */ | |
137 | ||
138 | #endif /* __UM_SYSCALL_GENERIC_H */ |