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.c190
1 files changed, 119 insertions, 71 deletions
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index 0564422c155f..5c088a55396c 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -18,7 +18,6 @@
18#include <asm/types.h> 18#include <asm/types.h>
19#include "user.h" 19#include "user.h"
20#include "sysdep/ptrace.h" 20#include "sysdep/ptrace.h"
21#include "user_util.h"
22#include "kern_util.h" 21#include "kern_util.h"
23#include "skas.h" 22#include "skas.h"
24#include "stub-data.h" 23#include "stub-data.h"
@@ -34,6 +33,8 @@
34#include "uml-config.h" 33#include "uml-config.h"
35#include "process.h" 34#include "process.h"
36#include "longjmp.h" 35#include "longjmp.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{
@@ -44,45 +45,58 @@ int is_skas_winch(int pid, int fd, void *data)
44 return(1); 45 return(1);
45} 46}
46 47
47void wait_stub_done(int pid, int sig, char * fname) 48static int ptrace_dump_regs(int pid)
48{ 49{
49 int n, status, err; 50 unsigned long regs[MAX_REG_NR];
51 int i;
52
53 if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
54 return -errno;
55 else {
56 printk("Stub registers -\n");
57 for(i = 0; i < ARRAY_SIZE(regs); i++)
58 printk("\t%d - %lx\n", i, regs[i]);
59 }
60
61 return 0;
62}
50 63
51 do { 64/*
52 if ( sig != -1 ) { 65 * Signals that are OK to receive in the stub - we'll just continue it.
53 err = ptrace(PTRACE_CONT, pid, 0, sig); 66 * SIGWINCH will happen when UML is inside a detached screen.
54 if(err) 67 */
55 panic("%s : continue failed, errno = %d\n", 68#define STUB_SIG_MASK ((1 << SIGVTALRM) | (1 << SIGWINCH))
56 fname, errno); 69
57 } 70/* Signals that the stub will finish with - anything else is an error */
58 sig = 0; 71#define STUB_DONE_MASK ((1 << SIGUSR1) | (1 << SIGTRAP))
72
73void wait_stub_done(int pid)
74{
75 int n, status, err;
59 76
77 while(1){
60 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); 78 CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED));
61 } while((n >= 0) && WIFSTOPPED(status) && 79 if((n < 0) || !WIFSTOPPED(status))
62 ((WSTOPSIG(status) == SIGVTALRM) || 80 goto bad_wait;
63 /* running UML inside a detached screen can cause 81
64 * SIGWINCHes 82 if(((1 << WSTOPSIG(status)) & STUB_SIG_MASK) == 0)
65 */ 83 break;
66 (WSTOPSIG(status) == SIGWINCH))); 84
67 85 err = ptrace(PTRACE_CONT, pid, 0, 0);
68 if((n < 0) || !WIFSTOPPED(status) || 86 if(err)
69 (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ 87 panic("wait_stub_done : continue failed, errno = %d\n",
70 unsigned long regs[MAX_REG_NR]; 88 errno);
71
72 if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0)
73 printk("Failed to get registers from stub, "
74 "errno = %d\n", errno);
75 else {
76 int i;
77
78 printk("Stub registers -\n");
79 for(i = 0; i < ARRAY_SIZE(regs); i++)
80 printk("\t%d - %lx\n", i, regs[i]);
81 }
82 panic("%s : failed to wait for SIGUSR1/SIGTRAP, "
83 "pid = %d, n = %d, errno = %d, status = 0x%x\n",
84 fname, pid, n, errno, status);
85 } 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);
86} 100}
87 101
88extern unsigned long current_stub_stack(void); 102extern unsigned long current_stub_stack(void);
@@ -104,7 +118,11 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi)
104 sizeof(struct ptrace_faultinfo)); 118 sizeof(struct ptrace_faultinfo));
105 } 119 }
106 else { 120 else {
107 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);
108 126
109 /* faultinfo is prepared by the stub-segv-handler at start of 127 /* faultinfo is prepared by the stub-segv-handler at start of
110 * the stub stack page. We just have to copy it. 128 * the stub stack page. We just have to copy it.
@@ -142,9 +160,14 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu
142 160
143 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); 161 CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
144 if((err < 0) || !WIFSTOPPED(status) || 162 if((err < 0) || !WIFSTOPPED(status) ||
145 (WSTOPSIG(status) != SIGTRAP + 0x80)) 163 (WSTOPSIG(status) != SIGTRAP + 0x80)){
164 err = ptrace_dump_regs(pid);
165 if(err)
166 printk("Failed to get registers from process, "
167 "errno = %d\n", -err);
146 panic("handle_trap - failed to wait at end of syscall, " 168 panic("handle_trap - failed to wait at end of syscall, "
147 "errno = %d, status = %d\n", errno, status); 169 "errno = %d, status = %d\n", errno, status);
170 }
148 } 171 }
149 172
150 handle_syscall(regs); 173 handle_syscall(regs);
@@ -172,7 +195,7 @@ static int userspace_tramp(void *stack)
172 int fd; 195 int fd;
173 __u64 offset; 196 __u64 offset;
174 fd = phys_mapping(to_phys(&__syscall_stub_start), &offset); 197 fd = phys_mapping(to_phys(&__syscall_stub_start), &offset);
175 addr = mmap64((void *) UML_CONFIG_STUB_CODE, page_size(), 198 addr = mmap64((void *) UML_CONFIG_STUB_CODE, UM_KERN_PAGE_SIZE,
176 PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset); 199 PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
177 if(addr == MAP_FAILED){ 200 if(addr == MAP_FAILED){
178 printk("mapping mmap stub failed, errno = %d\n", 201 printk("mapping mmap stub failed, errno = %d\n",
@@ -182,8 +205,8 @@ static int userspace_tramp(void *stack)
182 205
183 if(stack != NULL){ 206 if(stack != NULL){
184 fd = phys_mapping(to_phys(stack), &offset); 207 fd = phys_mapping(to_phys(stack), &offset);
185 addr = mmap((void *) UML_CONFIG_STUB_DATA, page_size(), 208 addr = mmap((void *) UML_CONFIG_STUB_DATA,
186 PROT_READ | PROT_WRITE, 209 UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
187 MAP_FIXED | MAP_SHARED, fd, offset); 210 MAP_FIXED | MAP_SHARED, fd, offset);
188 if(addr == MAP_FAILED){ 211 if(addr == MAP_FAILED){
189 printk("mapping segfault stack failed, " 212 printk("mapping segfault stack failed, "
@@ -199,7 +222,7 @@ static int userspace_tramp(void *stack)
199 (unsigned long) stub_segv_handler - 222 (unsigned long) stub_segv_handler -
200 (unsigned long) &__syscall_stub_start; 223 (unsigned long) &__syscall_stub_start;
201 224
202 set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size()); 225 set_sigstack((void *) UML_CONFIG_STUB_DATA, UM_KERN_PAGE_SIZE);
203 sigemptyset(&sa.sa_mask); 226 sigemptyset(&sa.sa_mask);
204 sigaddset(&sa.sa_mask, SIGIO); 227 sigaddset(&sa.sa_mask, SIGIO);
205 sigaddset(&sa.sa_mask, SIGWINCH); 228 sigaddset(&sa.sa_mask, SIGWINCH);
@@ -291,10 +314,13 @@ void userspace(union uml_pt_regs *regs)
291 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */ 314 UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
292 315
293 if(WIFSTOPPED(status)){ 316 if(WIFSTOPPED(status)){
294 switch(WSTOPSIG(status)){ 317 int sig = WSTOPSIG(status);
318 switch(sig){
295 case SIGSEGV: 319 case SIGSEGV:
296 if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo) 320 if(PTRACE_FULL_FAULTINFO || !ptrace_faultinfo){
297 user_signal(SIGSEGV, regs, pid); 321 get_skas_faultinfo(pid, &regs->skas.faultinfo);
322 (*sig_info[SIGSEGV])(SIGSEGV, regs);
323 }
298 else handle_segv(pid, regs); 324 else handle_segv(pid, regs);
299 break; 325 break;
300 case SIGTRAP + 0x80: 326 case SIGTRAP + 0x80:
@@ -309,11 +335,13 @@ void userspace(union uml_pt_regs *regs)
309 case SIGBUS: 335 case SIGBUS:
310 case SIGFPE: 336 case SIGFPE:
311 case SIGWINCH: 337 case SIGWINCH:
312 user_signal(WSTOPSIG(status), regs, pid); 338 block_signals();
339 (*sig_info[sig])(sig, regs);
340 unblock_signals();
313 break; 341 break;
314 default: 342 default:
315 printk("userspace - child stopped with signal " 343 printk("userspace - child stopped with signal "
316 "%d\n", WSTOPSIG(status)); 344 "%d\n", sig);
317 } 345 }
318 pid = userspace_pid[0]; 346 pid = userspace_pid[0];
319 interrupt_end(); 347 interrupt_end();
@@ -325,11 +353,29 @@ void userspace(union uml_pt_regs *regs)
325 } 353 }
326} 354}
327 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
328int copy_context_skas0(unsigned long new_stack, int pid) 376int copy_context_skas0(unsigned long new_stack, int pid)
329{ 377{
330 int err; 378 int err;
331 unsigned long regs[MAX_REG_NR];
332 unsigned long fp_regs[HOST_FP_SIZE];
333 unsigned long current_stack = current_stub_stack(); 379 unsigned long current_stack = current_stub_stack();
334 struct stub_data *data = (struct stub_data *) current_stack; 380 struct stub_data *data = (struct stub_data *) current_stack;
335 struct stub_data *child_data = (struct stub_data *) new_stack; 381 struct stub_data *child_data = (struct stub_data *) new_stack;
@@ -344,23 +390,12 @@ int copy_context_skas0(unsigned long new_stack, int pid)
344 .timer = ((struct itimerval) 390 .timer = ((struct itimerval)
345 { { 0, 1000000 / hz() }, 391 { { 0, 1000000 / hz() },
346 { 0, 1000000 / hz() }})}); 392 { 0, 1000000 / hz() }})});
347 get_safe_registers(regs, fp_regs); 393 err = ptrace_setregs(pid, thread_regs);
348
349 /* Set parent's instruction pointer to start of clone-stub */
350 regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE +
351 (unsigned long) stub_clone_handler -
352 (unsigned long) &__syscall_stub_start;
353 regs[REGS_SP_INDEX] = UML_CONFIG_STUB_DATA + PAGE_SIZE -
354 sizeof(void *);
355#ifdef __SIGNAL_FRAMESIZE
356 regs[REGS_SP_INDEX] -= __SIGNAL_FRAMESIZE;
357#endif
358 err = ptrace_setregs(pid, regs);
359 if(err < 0) 394 if(err < 0)
360 panic("copy_context_skas0 : PTRACE_SETREGS failed, " 395 panic("copy_context_skas0 : PTRACE_SETREGS failed, "
361 "pid = %d, errno = %d\n", pid, -err); 396 "pid = %d, errno = %d\n", pid, -err);
362 397
363 err = ptrace_setfpregs(pid, fp_regs); 398 err = ptrace_setfpregs(pid, thread_fp_regs);
364 if(err < 0) 399 if(err < 0)
365 panic("copy_context_skas0 : PTRACE_SETFPREGS failed, " 400 panic("copy_context_skas0 : PTRACE_SETFPREGS failed, "
366 "pid = %d, errno = %d\n", pid, -err); 401 "pid = %d, errno = %d\n", pid, -err);
@@ -371,7 +406,11 @@ int copy_context_skas0(unsigned long new_stack, int pid)
371 /* 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
372 * parent's stack, and check, if bad result. 407 * parent's stack, and check, if bad result.
373 */ 408 */
374 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);
375 414
376 pid = data->err; 415 pid = data->err;
377 if(pid < 0) 416 if(pid < 0)
@@ -381,7 +420,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
381 /* Wait, until child has finished too: read child's result from 420 /* Wait, until child has finished too: read child's result from
382 * child's stack and check it. 421 * child's stack and check it.
383 */ 422 */
384 wait_stub_done(pid, -1, "copy_context_skas0"); 423 wait_stub_done(pid);
385 if (child_data->err != UML_CONFIG_STUB_DATA) 424 if (child_data->err != UML_CONFIG_STUB_DATA)
386 panic("copy_context_skas0 - stub-child reports error %ld\n", 425 panic("copy_context_skas0 - stub-child reports error %ld\n",
387 child_data->err); 426 child_data->err);
@@ -396,7 +435,7 @@ int copy_context_skas0(unsigned long new_stack, int pid)
396 435
397/* 436/*
398 * This is used only, if stub pages are needed, while proc_mm is 437 * This is used only, if stub pages are needed, while proc_mm is
399 * availabl. Opening /proc/mm creates a new mm_context, which lacks 438 * available. Opening /proc/mm creates a new mm_context, which lacks
400 * the stub-pages. Thus, we map them using /proc/mm-fd 439 * the stub-pages. Thus, we map them using /proc/mm-fd
401 */ 440 */
402void map_stub_pages(int fd, unsigned long code, 441void map_stub_pages(int fd, unsigned long code,
@@ -418,12 +457,13 @@ void map_stub_pages(int fd, unsigned long code,
418 .fd = code_fd, 457 .fd = code_fd,
419 .offset = code_offset 458 .offset = code_offset
420 } } }); 459 } } });
421 n = os_write_file(fd, &mmop, sizeof(mmop)); 460 CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
422 if(n != sizeof(mmop)){ 461 if(n != sizeof(mmop)){
462 n = errno;
423 printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n", 463 printk("mmap args - addr = 0x%lx, fd = %d, offset = %llx\n",
424 code, code_fd, (unsigned long long) code_offset); 464 code, code_fd, (unsigned long long) code_offset);
425 panic("map_stub_pages : /proc/mm map for code failed, " 465 panic("map_stub_pages : /proc/mm map for code failed, "
426 "err = %d\n", -n); 466 "err = %d\n", n);
427 } 467 }
428 468
429 if ( stack ) { 469 if ( stack ) {
@@ -440,10 +480,10 @@ void map_stub_pages(int fd, unsigned long code,
440 .fd = map_fd, 480 .fd = map_fd,
441 .offset = map_offset 481 .offset = map_offset
442 } } }); 482 } } });
443 n = os_write_file(fd, &mmop, sizeof(mmop)); 483 CATCH_EINTR(n = write(fd, &mmop, sizeof(mmop)));
444 if(n != sizeof(mmop)) 484 if(n != sizeof(mmop))
445 panic("map_stub_pages : /proc/mm map for data failed, " 485 panic("map_stub_pages : /proc/mm map for data failed, "
446 "err = %d\n", -n); 486 "err = %d\n", errno);
447 } 487 }
448} 488}
449 489
@@ -480,7 +520,15 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
480 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, 520 SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM,
481 SIGVTALRM, -1); 521 SIGVTALRM, -1);
482 522
483 n = UML_SETJMP(&initial_jmpbuf); 523 /*
524 * Can't use UML_SETJMP or UML_LONGJMP here because they save
525 * and restore signals, with the possible side-effect of
526 * trying to handle any signals which came when they were
527 * blocked, which can't be done on this stack.
528 * Signals must be blocked when jumping back here and restored
529 * after returning to the jumper.
530 */
531 n = setjmp(initial_jmpbuf);
484 switch(n){ 532 switch(n){
485 case INIT_JMP_NEW_THREAD: 533 case INIT_JMP_NEW_THREAD:
486 (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; 534 (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler;
@@ -490,7 +538,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
490 break; 538 break;
491 case INIT_JMP_CALLBACK: 539 case INIT_JMP_CALLBACK:
492 (*cb_proc)(cb_arg); 540 (*cb_proc)(cb_arg);
493 UML_LONGJMP(cb_back, 1); 541 longjmp(*cb_back, 1);
494 break; 542 break;
495 case INIT_JMP_HALT: 543 case INIT_JMP_HALT:
496 kmalloc_ok = 0; 544 kmalloc_ok = 0;
@@ -501,7 +549,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)
501 default: 549 default:
502 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); 550 panic("Bad sigsetjmp return in start_idle_thread - %d\n", n);
503 } 551 }
504 UML_LONGJMP(switch_buf, 1); 552 longjmp(*switch_buf, 1);
505} 553}
506 554
507void initial_thread_cb_skas(void (*proc)(void *), void *arg) 555void initial_thread_cb_skas(void (*proc)(void *), void *arg)