diff options
Diffstat (limited to 'arch/um/os-Linux/skas/mem.c')
-rw-r--r-- | arch/um/os-Linux/skas/mem.c | 75 |
1 files changed, 44 insertions, 31 deletions
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c index 9383e8751ae7..8e490fff3d47 100644 --- a/arch/um/os-Linux/skas/mem.c +++ b/arch/um/os-Linux/skas/mem.c | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <signal.h> | 6 | #include <signal.h> |
7 | #include <errno.h> | 7 | #include <errno.h> |
8 | #include <string.h> | 8 | #include <string.h> |
9 | #include <unistd.h> | ||
9 | #include <sys/mman.h> | 10 | #include <sys/mman.h> |
10 | #include <sys/wait.h> | 11 | #include <sys/wait.h> |
11 | #include <asm/page.h> | 12 | #include <asm/page.h> |
@@ -17,17 +18,17 @@ | |||
17 | #include "os.h" | 18 | #include "os.h" |
18 | #include "proc_mm.h" | 19 | #include "proc_mm.h" |
19 | #include "ptrace_user.h" | 20 | #include "ptrace_user.h" |
20 | #include "user_util.h" | ||
21 | #include "kern_util.h" | 21 | #include "kern_util.h" |
22 | #include "task.h" | 22 | #include "task.h" |
23 | #include "registers.h" | 23 | #include "registers.h" |
24 | #include "uml-config.h" | 24 | #include "uml-config.h" |
25 | #include "sysdep/ptrace.h" | 25 | #include "sysdep/ptrace.h" |
26 | #include "sysdep/stub.h" | 26 | #include "sysdep/stub.h" |
27 | #include "init.h" | ||
27 | 28 | ||
28 | extern unsigned long batch_syscall_stub, __syscall_stub_start; | 29 | extern unsigned long batch_syscall_stub, __syscall_stub_start; |
29 | 30 | ||
30 | extern void wait_stub_done(int pid, int sig, char * fname); | 31 | extern void wait_stub_done(int pid); |
31 | 32 | ||
32 | static inline unsigned long *check_init_stack(struct mm_id * mm_idp, | 33 | static inline unsigned long *check_init_stack(struct mm_id * mm_idp, |
33 | unsigned long *stack) | 34 | unsigned long *stack) |
@@ -39,6 +40,19 @@ static inline unsigned long *check_init_stack(struct mm_id * mm_idp, | |||
39 | return stack; | 40 | return stack; |
40 | } | 41 | } |
41 | 42 | ||
43 | static unsigned long syscall_regs[MAX_REG_NR]; | ||
44 | |||
45 | static int __init init_syscall_regs(void) | ||
46 | { | ||
47 | get_safe_registers(syscall_regs, NULL); | ||
48 | syscall_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + | ||
49 | ((unsigned long) &batch_syscall_stub - | ||
50 | (unsigned long) &__syscall_stub_start); | ||
51 | return 0; | ||
52 | } | ||
53 | |||
54 | __initcall(init_syscall_regs); | ||
55 | |||
42 | extern int proc_mm; | 56 | extern int proc_mm; |
43 | 57 | ||
44 | int single_count = 0; | 58 | int single_count = 0; |
@@ -47,12 +61,11 @@ int multi_op_count = 0; | |||
47 | 61 | ||
48 | static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) | 62 | static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) |
49 | { | 63 | { |
50 | unsigned long regs[MAX_REG_NR]; | ||
51 | int n, i; | 64 | int n, i; |
52 | long ret, offset; | 65 | long ret, offset; |
53 | unsigned long * data; | 66 | unsigned long * data; |
54 | unsigned long * syscall; | 67 | unsigned long * syscall; |
55 | int pid = mm_idp->u.pid; | 68 | int err, pid = mm_idp->u.pid; |
56 | 69 | ||
57 | if(proc_mm) | 70 | if(proc_mm) |
58 | #warning Need to look up userspace_pid by cpu | 71 | #warning Need to look up userspace_pid by cpu |
@@ -60,21 +73,21 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) | |||
60 | 73 | ||
61 | multi_count++; | 74 | multi_count++; |
62 | 75 | ||
63 | get_safe_registers(regs, NULL); | 76 | n = ptrace_setregs(pid, syscall_regs); |
64 | regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + | ||
65 | ((unsigned long) &batch_syscall_stub - | ||
66 | (unsigned long) &__syscall_stub_start); | ||
67 | |||
68 | n = ptrace_setregs(pid, regs); | ||
69 | if(n < 0){ | 77 | if(n < 0){ |
70 | printk("Registers - \n"); | 78 | printk("Registers - \n"); |
71 | for(i = 0; i < MAX_REG_NR; i++) | 79 | for(i = 0; i < MAX_REG_NR; i++) |
72 | printk("\t%d\t0x%lx\n", i, regs[i]); | 80 | printk("\t%d\t0x%lx\n", i, syscall_regs[i]); |
73 | panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", | 81 | panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", |
74 | -n); | 82 | -n); |
75 | } | 83 | } |
76 | 84 | ||
77 | wait_stub_done(pid, 0, "do_syscall_stub"); | 85 | err = ptrace(PTRACE_CONT, pid, 0, 0); |
86 | if(err) | ||
87 | panic("Failed to continue stub, pid = %d, errno = %d\n", pid, | ||
88 | errno); | ||
89 | |||
90 | wait_stub_done(pid); | ||
78 | 91 | ||
79 | /* When the stub stops, we find the following values on the | 92 | /* When the stub stops, we find the following values on the |
80 | * beginning of the stack: | 93 | * beginning of the stack: |
@@ -176,14 +189,10 @@ long syscall_stub_data(struct mm_id * mm_idp, | |||
176 | return 0; | 189 | return 0; |
177 | } | 190 | } |
178 | 191 | ||
179 | int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, | 192 | int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, int prot, |
180 | int r, int w, int x, int phys_fd, unsigned long long offset, | 193 | int phys_fd, unsigned long long offset, int done, void **data) |
181 | int done, void **data) | ||
182 | { | 194 | { |
183 | int prot, ret; | 195 | int ret; |
184 | |||
185 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | ||
186 | (x ? PROT_EXEC : 0); | ||
187 | 196 | ||
188 | if(proc_mm){ | 197 | if(proc_mm){ |
189 | struct proc_mm_op map; | 198 | struct proc_mm_op map; |
@@ -200,9 +209,11 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, | |||
200 | .fd = phys_fd, | 209 | .fd = phys_fd, |
201 | .offset= offset | 210 | .offset= offset |
202 | } } } ); | 211 | } } } ); |
203 | ret = os_write_file(fd, &map, sizeof(map)); | 212 | CATCH_EINTR(ret = write(fd, &map, sizeof(map))); |
204 | if(ret != sizeof(map)) | 213 | if(ret != sizeof(map)){ |
214 | ret = -errno; | ||
205 | printk("map : /proc/mm map failed, err = %d\n", -ret); | 215 | printk("map : /proc/mm map failed, err = %d\n", -ret); |
216 | } | ||
206 | else ret = 0; | 217 | else ret = 0; |
207 | } | 218 | } |
208 | else { | 219 | else { |
@@ -217,8 +228,8 @@ int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, | |||
217 | return ret; | 228 | return ret; |
218 | } | 229 | } |
219 | 230 | ||
220 | int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, | 231 | int unmap(struct mm_id * mm_idp, unsigned long addr, unsigned long len, |
221 | void **data) | 232 | int done, void **data) |
222 | { | 233 | { |
223 | int ret; | 234 | int ret; |
224 | 235 | ||
@@ -232,9 +243,11 @@ int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, | |||
232 | { .addr = | 243 | { .addr = |
233 | (unsigned long) addr, | 244 | (unsigned long) addr, |
234 | .len = len } } } ); | 245 | .len = len } } } ); |
235 | ret = os_write_file(fd, &unmap, sizeof(unmap)); | 246 | CATCH_EINTR(ret = write(fd, &unmap, sizeof(unmap))); |
236 | if(ret != sizeof(unmap)) | 247 | if(ret != sizeof(unmap)){ |
248 | ret = -errno; | ||
237 | printk("unmap - proc_mm write returned %d\n", ret); | 249 | printk("unmap - proc_mm write returned %d\n", ret); |
250 | } | ||
238 | else ret = 0; | 251 | else ret = 0; |
239 | } | 252 | } |
240 | else { | 253 | else { |
@@ -249,13 +262,11 @@ int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, | |||
249 | } | 262 | } |
250 | 263 | ||
251 | int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, | 264 | int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, |
252 | int r, int w, int x, int done, void **data) | 265 | unsigned int prot, int done, void **data) |
253 | { | 266 | { |
254 | struct proc_mm_op protect; | 267 | struct proc_mm_op protect; |
255 | int prot, ret; | 268 | int ret; |
256 | 269 | ||
257 | prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | | ||
258 | (x ? PROT_EXEC : 0); | ||
259 | if(proc_mm){ | 270 | if(proc_mm){ |
260 | int fd = mm_idp->u.mm_fd; | 271 | int fd = mm_idp->u.mm_fd; |
261 | 272 | ||
@@ -267,9 +278,11 @@ int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, | |||
267 | .len = len, | 278 | .len = len, |
268 | .prot = prot } } } ); | 279 | .prot = prot } } } ); |
269 | 280 | ||
270 | ret = os_write_file(fd, &protect, sizeof(protect)); | 281 | CATCH_EINTR(ret = write(fd, &protect, sizeof(protect))); |
271 | if(ret != sizeof(protect)) | 282 | if(ret != sizeof(protect)){ |
283 | ret = -errno; | ||
272 | printk("protect failed, err = %d", -ret); | 284 | printk("protect failed, err = %d", -ret); |
285 | } | ||
273 | else ret = 0; | 286 | else ret = 0; |
274 | } | 287 | } |
275 | else { | 288 | else { |