aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux/skas/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/um/os-Linux/skas/process.c')
-rw-r--r--arch/um/os-Linux/skas/process.c122
1 files changed, 74 insertions, 48 deletions
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 1f39f2bf7ce9..5c088a55396c 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -34,6 +34,7 @@
34#include "process.h" 34#include "process.h"
35#include "longjmp.h" 35#include "longjmp.h"
36#include "kern_constants.h" 36#include "kern_constants.h"
37#include "as-layout.h"
37 38
38int is_skas_winch(int pid, int fd, void *data) 39int is_skas_winch(int pid, int fd, void *data)
39{ 40{
@@ -60,37 +61,42 @@ static int ptrace_dump_regs(int pid)
60 return 0; 61 return 0;
61} 62}
62 63
63void wait_stub_done(int pid, int sig, char * fname) 64/*
65 * Signals that are OK to receive in the stub - we'll just continue it.
66 * SIGWINCH will happen when UML is inside a detached screen.
67 */
68#define STUB_SIG_MASK ((1 << SIGVTALRM) | (1 << SIGWINCH))
69
70/* Signals that the stub will finish with - anything else is an error */
71#define STUB_DONE_MASK ((1 << SIGUSR1) | (1 << SIGTRAP))
72
73void wait_stub_done(int pid)
64{ 74{
65 int n, status, err; 75 int n, status, err;
66 76
67 do { 77 while(1){
68 if ( sig != -1 ) {
69 err = ptrace(PTRACE_CONT, pid, 0, sig);
70 if(err)
71 panic("%s : continue failed, errno = %d\n",
72 fname, errno);
73 }
74 sig = 0;
75
76 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 78 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
77 } while((n >= 0) && WIFSTOPPED(status) && 79 if((n < 0) || !WIFSTOPPED(status))
78 ((WSTOPSIG(status) == SIGVTALRM) || 80 goto bad_wait;
79 /* running UML inside a detached screen can cause 81
80 * SIGWINCHes 82 if(((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0)
81 */ 83 break;
82 (WSTOPSIG(status) == SIGWINCH))); 84
83 85 err = ptrace(PTRACE_CONT, pid, 0, 0);
84 if((n < 0) || !WIFSTOPPED(status) ||
85 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){
86 err = ptrace_dump_regs(pid);
87 if(err) 86 if(err)
88 printk("Failed to get registers from stub, " 87 panic("wait_stub_done : continue failed, errno = %d\n",
89 "errno = %d\n", -err); 88 errno);
90 panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
91 "pid = %d, n = %d, errno = %d, status = 0x%x\n",
92 fname, pid, n, errno, status);
93 } 89 }
90
91 if(((1 << WSTOPSIG(status)) & STUB_DONE_MASK) != 0)
92 return;
93
94bad_wait:
95 err = ptrace_dump_regs(pid);
96 if(err)
97 printk("Failed to get registers from stub, errno = %d\n", -err);
98 panic("wait_stub_done : failed to wait for SIGUSR1/SIGTRAP, pid = %d, "
99 "n = %d, errno = %d, status = 0x%x\n", pid, n, errno, status);
94} 100}
95 101
96extern unsigned long current_stub_stack(void); 102extern unsigned long current_stub_stack(void);
@@ -112,7 +118,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
112 sizeof(struct ptrace_faultinfo)); 118 sizeof(struct ptrace_faultinfo));
113 } 119 }
114 else { 120 else {
115 wait_stub_done(pid, SIGSEGV, "get_skas_faultinfo"); 121 err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
122 if(err)
123 panic("Failed to continue stub, pid = %d, errno = %d\n",
124 pid, errno);
125 wait_stub_done(pid);
116 126
117 /* faultinfo is prepared by the stub-segv-handler at start of 127 /* faultinfo is prepared by the stub-segv-handler at start of
118 * the stub stack page. We just have to copy it. 128 * the stub stack page. We just have to copy it.
@@ -304,10 +314,13 @@ void userspace(union uml_pt_regs *regs)
304 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ 314 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
305 315
306 if(WIFSTOPPED(status)){ 316 if(WIFSTOPPED(status)){
307 switch(WSTOPSIG(status)){ 317 int sig = WSTOPSIG(status);
318 switch(sig){
308 case SIGSEGV: 319 case SIGSEGV:
309 if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) 320 if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo){
310 user_signal(SIGSEGV, regs, pid); 321 get_skas_faultinfo(pid, &regs->skas.faultinfo);
322 (*sig_info[SIGSEGV])(SIGSEGV, regs);
323 }
311 else handle_segv(pid, regs); 324 else handle_segv(pid, regs);
312 break; 325 break;
313 case SIGTRAP + 0x80: 326 case SIGTRAP + 0x80:
@@ -322,11 +335,13 @@ void userspace(union uml_pt_regs *regs)
322 case SIGBUS: 335 case SIGBUS:
323 case SIGFPE: 336 case SIGFPE:
324 case SIGWINCH: 337 case SIGWINCH:
325 user_signal(WSTOPSIG(status), regs, pid); 338 block_signals();
339 (*sig_info[sig])(sig, regs);
340 unblock_signals();
326 break; 341 break;
327 default: 342 default:
328 printk("userspace - child stopped with signal " 343 printk("userspace - child stopped with signal "
329 "%d\n", WSTOPSIG(status)); 344 "%d\n", sig);
330 } 345 }
331 pid = userspace_pid[0]; 346 pid = userspace_pid[0];
332 interrupt_end(); 347 interrupt_end();
@@ -338,11 +353,29 @@ void userspace(union uml_pt_regs *regs)
338 } 353 }
339} 354}
340 355
356static unsigned long thread_regs[MAX_REG_NR];
357static unsigned long thread_fp_regs[HOST_FP_SIZE];
358
359static int __init init_thread_regs(void)
360{
361 get_safe_registers(thread_regs, thread_fp_regs);
362 /* Set parent's instruction pointer to start of clone-stub */
363 thread_regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
364 (unsigned long) stub_clone_handler -
365 (unsigned long) &__syscall_stub_start;
366 thread_regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
367 sizeof(void *);
368#ifdef __SIGNAL_FRAMESIZE
369 thread_regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
370#endif
371 return 0;
372}
373
374__initcall(init_thread_regs);
375
341int copy_context_skas0(unsigned long new_stack, int pid) 376int copy_context_skas0(unsigned long new_stack, int pid)
342{ 377{
343 int err; 378 int err;
344 unsigned long regs[MAX_REG_NR];
345 unsigned long fp_regs[HOST_FP_SIZE];
346 unsigned long current_stack = current_stub_stack(); 379 unsigned long current_stack = current_stub_stack();
347 struct stub_data *data = (struct stub_data *) current_stack; 380 struct stub_data *data = (struct stub_data *) current_stack;
348 struct stub_data *child_data = (struct stub_data *) new_stack; 381 struct stub_data *child_data = (struct stub_data *) new_stack;
@@ -357,23 +390,12 @@ int copy_context_skas0(unsigned long new_stack, int pid)
357 .timer = ((struct itimerval) 390 .timer = ((struct itimerval)
358 { { 0, 1000000 / hz() }, 391 { { 0, 1000000 / hz() },
359 { 0, 1000000 / hz() }})}); 392 { 0, 1000000 / hz() }})});
360 get_safe_registers(regs, fp_regs); 393 err = ptrace_setregs(pid, thread_regs);
361
362 /* Set parent's instruction pointer to start of clone-stub */
363 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
364 (unsigned long) stub_clone_handler -
365 (unsigned long) &__syscall_stub_start;
366 regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
367 sizeof(void *);
368#ifdef __SIGNAL_FRAMESIZE
369 regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
370#endif
371 err = ptrace_setregs(pid, regs);
372 if(err < 0) 394 if(err < 0)
373 panic("copy_context_skas0 : PTRACE_SETREGS failed, " 395 panic("copy_context_skas0 : PTRACE_SETREGS failed, "
374 "pid = %d, errno = %d\n", pid, -err); 396 "pid = %d, errno = %d\n", pid, -err);
375 397
376 err = ptrace_setfpregs(pid, fp_regs); 398 err = ptrace_setfpregs(pid, thread_fp_regs);
377 if(err < 0) 399 if(err < 0)
378 panic("copy_context_skas0 : PTRACE_SETFPREGS failed, " 400 panic("copy_context_skas0 : PTRACE_SETFPREGS failed, "
379 "pid = %d, errno = %d\n", pid, -err); 401 "pid = %d, errno = %d\n", pid, -err);
@@ -384,7 +406,11 @@ int copy_context_skas0(unsigned long new_stack, int pid)
384 /* Wait, until parent has finished its work: read child's pid from 406 /* Wait, until parent has finished its work: read child's pid from
385 * parent's stack, and check, if bad result. 407 * parent's stack, and check, if bad result.
386 */ 408 */
387 wait_stub_done(pid, 0, "copy_context_skas0"); 409 err = ptrace(PTRACE_CONT, pid, 0, 0);
410 if(err)
411 panic("Failed to continue new process, pid = %d, "
412 "errno = %d\n", pid, errno);
413 wait_stub_done(pid);
388 414
389 pid = data->err; 415 pid = data->err;
390 if(pid < 0) 416 if(pid < 0)
@@ -394,7 +420,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
394 /* Wait, until child has finished too: read child's result from 420 /* Wait, until child has finished too: read child's result from
395 * child's stack and check it. 421 * child's stack and check it.
396 */ 422 */
397 wait_stub_done(pid, -1, "copy_context_skas0"); 423 wait_stub_done(pid);
398 if (child_data->err != UML_CONFIG_STUB_DATA) 424 if (child_data->err != UML_CONFIG_STUB_DATA)
399 panic("copy_context_skas0 - stub-child reports error %ld\n", 425 panic("copy_context_skas0 - stub-child reports error %ld\n",
400 child_data->err); 426 child_data->err);