diff options
Diffstat (limited to 'arch/um/kernel/skas/process.c')
-rw-r--r-- | arch/um/kernel/skas/process.c | 153 |
1 files changed, 120 insertions, 33 deletions
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 773cd2b525fc..1647abb0d1aa 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) | 2 | * Copyright (C) 2002- 2004 Jeff Dike (jdike@addtoit.com) |
3 | * Licensed under the GPL | 3 | * Licensed under the GPL |
4 | */ | 4 | */ |
5 | 5 | ||
@@ -14,6 +14,7 @@ | |||
14 | #include <sys/mman.h> | 14 | #include <sys/mman.h> |
15 | #include <sys/user.h> | 15 | #include <sys/user.h> |
16 | #include <asm/unistd.h> | 16 | #include <asm/unistd.h> |
17 | #include <asm/types.h> | ||
17 | #include "user.h" | 18 | #include "user.h" |
18 | #include "ptrace_user.h" | 19 | #include "ptrace_user.h" |
19 | #include "time_user.h" | 20 | #include "time_user.h" |
@@ -21,13 +22,17 @@ | |||
21 | #include "user_util.h" | 22 | #include "user_util.h" |
22 | #include "kern_util.h" | 23 | #include "kern_util.h" |
23 | #include "skas.h" | 24 | #include "skas.h" |
25 | #include "mm_id.h" | ||
24 | #include "sysdep/sigcontext.h" | 26 | #include "sysdep/sigcontext.h" |
27 | #include "sysdep/stub.h" | ||
25 | #include "os.h" | 28 | #include "os.h" |
26 | #include "proc_mm.h" | 29 | #include "proc_mm.h" |
27 | #include "skas_ptrace.h" | 30 | #include "skas_ptrace.h" |
28 | #include "chan_user.h" | 31 | #include "chan_user.h" |
29 | #include "signal_user.h" | 32 | #include "signal_user.h" |
30 | #include "registers.h" | 33 | #include "registers.h" |
34 | #include "mem.h" | ||
35 | #include "uml-config.h" | ||
31 | #include "process.h" | 36 | #include "process.h" |
32 | 37 | ||
33 | int is_skas_winch(int pid, int fd, void *data) | 38 | int is_skas_winch(int pid, int fd, void *data) |
@@ -39,20 +44,55 @@ int is_skas_winch(int pid, int fd, void *data) | |||
39 | return(1); | 44 | return(1); |
40 | } | 45 | } |
41 | 46 | ||
42 | void get_skas_faultinfo(int pid, struct faultinfo * fi) | 47 | void wait_stub_done(int pid, int sig, char * fname) |
43 | { | 48 | { |
44 | int err; | 49 | int n, status, err; |
45 | 50 | ||
46 | err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); | 51 | do { |
47 | if(err) | 52 | if ( sig != -1 ) { |
48 | panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " | 53 | err = ptrace(PTRACE_CONT, pid, 0, sig); |
49 | "errno = %d\n", errno); | 54 | if(err) |
55 | panic("%s : continue failed, errno = %d\n", | ||
56 | fname, errno); | ||
57 | } | ||
58 | sig = 0; | ||
59 | |||
60 | CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); | ||
61 | } while((n >= 0) && WIFSTOPPED(status) && | ||
62 | (WSTOPSIG(status) == SIGVTALRM)); | ||
63 | |||
64 | if((n < 0) || !WIFSTOPPED(status) || | ||
65 | (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status != SIGTRAP))){ | ||
66 | panic("%s : failed to wait for SIGUSR1/SIGTRAP, " | ||
67 | "pid = %d, n = %d, errno = %d, status = 0x%x\n", | ||
68 | fname, pid, n, errno, status); | ||
69 | } | ||
70 | } | ||
50 | 71 | ||
51 | /* Special handling for i386, which has different structs */ | 72 | void get_skas_faultinfo(int pid, struct faultinfo * fi) |
52 | if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) | 73 | { |
53 | memset((char *)fi + sizeof(struct ptrace_faultinfo), 0, | 74 | int err; |
54 | sizeof(struct faultinfo) - | 75 | |
55 | sizeof(struct ptrace_faultinfo)); | 76 | if(ptrace_faultinfo){ |
77 | err = ptrace(PTRACE_FAULTINFO, pid, 0, fi); | ||
78 | if(err) | ||
79 | panic("get_skas_faultinfo - PTRACE_FAULTINFO failed, " | ||
80 | "errno = %d\n", errno); | ||
81 | |||
82 | /* Special handling for i386, which has different structs */ | ||
83 | if (sizeof(struct ptrace_faultinfo) < sizeof(struct faultinfo)) | ||
84 | memset((char *)fi + sizeof(struct ptrace_faultinfo), 0, | ||
85 | sizeof(struct faultinfo) - | ||
86 | sizeof(struct ptrace_faultinfo)); | ||
87 | } | ||
88 | else { | ||
89 | wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo"); | ||
90 | |||
91 | /* faultinfo is prepared by the stub-segv-handler at start of | ||
92 | * the stub stack page. We just have to copy it. | ||
93 | */ | ||
94 | memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); | ||
95 | } | ||
56 | } | 96 | } |
57 | 97 | ||
58 | static void handle_segv(int pid, union uml_pt_regs * regs) | 98 | static void handle_segv(int pid, union uml_pt_regs * regs) |
@@ -91,11 +131,56 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu | |||
91 | handle_syscall(regs); | 131 | handle_syscall(regs); |
92 | } | 132 | } |
93 | 133 | ||
94 | static int userspace_tramp(void *arg) | 134 | extern int __syscall_stub_start; |
135 | |||
136 | static int userspace_tramp(void *stack) | ||
95 | { | 137 | { |
96 | init_new_thread_signals(0); | 138 | void *addr; |
97 | enable_timer(); | 139 | |
98 | ptrace(PTRACE_TRACEME, 0, 0, 0); | 140 | ptrace(PTRACE_TRACEME, 0, 0, 0); |
141 | |||
142 | init_new_thread_signals(1); | ||
143 | enable_timer(); | ||
144 | |||
145 | if(!proc_mm){ | ||
146 | /* This has a pte, but it can't be mapped in with the usual | ||
147 | * tlb_flush mechanism because this is part of that mechanism | ||
148 | */ | ||
149 | int fd; | ||
150 | __u64 offset; | ||
151 | |||
152 | fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); | ||
153 | addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(), | ||
154 | PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); | ||
155 | if(addr == MAP_FAILED){ | ||
156 | printk("mapping mmap stub failed, errno = %d\n", | ||
157 | errno); | ||
158 | exit(1); | ||
159 | } | ||
160 | |||
161 | if(stack != NULL){ | ||
162 | fd = phys_mapping(to_phys(stack), &offset); | ||
163 | addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(), | ||
164 | PROT_READ | PROT_WRITE, | ||
165 | MAP_FIXED | MAP_SHARED, fd, offset); | ||
166 | if(addr == MAP_FAILED){ | ||
167 | printk("mapping segfault stack failed, " | ||
168 | "errno = %d\n", errno); | ||
169 | exit(1); | ||
170 | } | ||
171 | } | ||
172 | } | ||
173 | if(!ptrace_faultinfo && (stack != NULL)){ | ||
174 | unsigned long v = UML_CONFIG_STUB_CODE + | ||
175 | (unsigned long) stub_segv_handler - | ||
176 | (unsigned long) &__syscall_stub_start; | ||
177 | |||
178 | set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size()); | ||
179 | set_handler(SIGSEGV, (void *) v, SA_ONSTACK, | ||
180 | SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, | ||
181 | SIGUSR1, -1); | ||
182 | } | ||
183 | |||
99 | os_stop_process(os_getpid()); | 184 | os_stop_process(os_getpid()); |
100 | return(0); | 185 | return(0); |
101 | } | 186 | } |
@@ -105,11 +190,11 @@ static int userspace_tramp(void *arg) | |||
105 | #define NR_CPUS 1 | 190 | #define NR_CPUS 1 |
106 | int userspace_pid[NR_CPUS]; | 191 | int userspace_pid[NR_CPUS]; |
107 | 192 | ||
108 | void start_userspace(int cpu) | 193 | int start_userspace(unsigned long stub_stack) |
109 | { | 194 | { |
110 | void *stack; | 195 | void *stack; |
111 | unsigned long sp; | 196 | unsigned long sp; |
112 | int pid, status, n; | 197 | int pid, status, n, flags; |
113 | 198 | ||
114 | stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, | 199 | stack = mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, |
115 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); | 200 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
@@ -117,8 +202,9 @@ void start_userspace(int cpu) | |||
117 | panic("start_userspace : mmap failed, errno = %d", errno); | 202 | panic("start_userspace : mmap failed, errno = %d", errno); |
118 | sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); | 203 | sp = (unsigned long) stack + PAGE_SIZE - sizeof(void *); |
119 | 204 | ||
120 | pid = clone(userspace_tramp, (void *) sp, | 205 | flags = CLONE_FILES | SIGCHLD; |
121 | CLONE_FILES | CLONE_VM | SIGCHLD, NULL); | 206 | if(proc_mm) flags |= CLONE_VM; |
207 | pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack); | ||
122 | if(pid < 0) | 208 | if(pid < 0) |
123 | panic("start_userspace : clone failed, errno = %d", errno); | 209 | panic("start_userspace : clone failed, errno = %d", errno); |
124 | 210 | ||
@@ -140,7 +226,7 @@ void start_userspace(int cpu) | |||
140 | if(munmap(stack, PAGE_SIZE) < 0) | 226 | if(munmap(stack, PAGE_SIZE) < 0) |
141 | panic("start_userspace : munmap failed, errno = %d\n", errno); | 227 | panic("start_userspace : munmap failed, errno = %d\n", errno); |
142 | 228 | ||
143 | userspace_pid[cpu] = pid; | 229 | return(pid); |
144 | } | 230 | } |
145 | 231 | ||
146 | void userspace(union uml_pt_regs *regs) | 232 | void userspace(union uml_pt_regs *regs) |
@@ -174,7 +260,9 @@ void userspace(union uml_pt_regs *regs) | |||
174 | if(WIFSTOPPED(status)){ | 260 | if(WIFSTOPPED(status)){ |
175 | switch(WSTOPSIG(status)){ | 261 | switch(WSTOPSIG(status)){ |
176 | case SIGSEGV: | 262 | case SIGSEGV: |
177 | handle_segv(pid, regs); | 263 | if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) |
264 | user_signal(SIGSEGV, regs, pid); | ||
265 | else handle_segv(pid, regs); | ||
178 | break; | 266 | break; |
179 | case SIGTRAP + 0x80: | 267 | case SIGTRAP + 0x80: |
180 | handle_trap(pid, regs, local_using_sysemu); | 268 | handle_trap(pid, regs, local_using_sysemu); |
@@ -194,6 +282,7 @@ void userspace(union uml_pt_regs *regs) | |||
194 | printk("userspace - child stopped with signal " | 282 | printk("userspace - child stopped with signal " |
195 | "%d\n", WSTOPSIG(status)); | 283 | "%d\n", WSTOPSIG(status)); |
196 | } | 284 | } |
285 | pid = userspace_pid[0]; | ||
197 | interrupt_end(); | 286 | interrupt_end(); |
198 | 287 | ||
199 | /* Avoid -ERESTARTSYS handling in host */ | 288 | /* Avoid -ERESTARTSYS handling in host */ |
@@ -334,21 +423,19 @@ void reboot_skas(void) | |||
334 | siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT); | 423 | siglongjmp(initial_jmpbuf, INIT_JMP_REBOOT); |
335 | } | 424 | } |
336 | 425 | ||
337 | void switch_mm_skas(int mm_fd) | 426 | void switch_mm_skas(struct mm_id *mm_idp) |
338 | { | 427 | { |
339 | int err; | 428 | int err; |
340 | 429 | ||
341 | #warning need cpu pid in switch_mm_skas | 430 | #warning need cpu pid in switch_mm_skas |
342 | err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_fd); | 431 | if(proc_mm){ |
343 | if(err) | 432 | err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, |
344 | panic("switch_mm_skas - PTRACE_SWITCH_MM failed, errno = %d\n", | 433 | mm_idp->u.mm_fd); |
345 | errno); | 434 | if(err) |
346 | } | 435 | panic("switch_mm_skas - PTRACE_SWITCH_MM failed, " |
347 | 436 | "errno = %d\n", errno); | |
348 | void kill_off_processes_skas(void) | 437 | } |
349 | { | 438 | else userspace_pid[0] = mm_idp->u.pid; |
350 | #warning need to loop over userspace_pids in kill_off_processes_skas | ||
351 | os_kill_ptraced_process(userspace_pid[0], 1); | ||
352 | } | 439 | } |
353 | 440 | ||
354 | /* | 441 | /* |