aboutsummaryrefslogtreecommitdiffstats
path: root/arch/um/os-Linux/skas/process.c
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2007-05-06 17:51:48 -0400
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-05-07 15:13:04 -0400
commit16dd07bc6404c8da0bdfeb7a5cde4e4a63991c00 (patch)
treede8401aeebfe1bbdaecaff3b81d92196c50c85d7 /arch/um/os-Linux/skas/process.c
parent3ec704e6660aa58505110a50102e57cdb9daa044 (diff)
uml: more page fault path trimming
More trimming of the page fault path. Permissions are passed around in a single int rather than one bit per int. The permission values are copied from libc so that they can be passed to mmap and mprotect without any further conversion. The register sets used by do_syscall_stub and copy_context_skas0 are initialized once, at boot time, rather than once per call. wait_stub_done checks whether it is getting the signals it expects by comparing the wait status to a mask containing bits for the signals of interest rather than comparing individually to the signal numbers. It also has one check for a wait failure instead of two. The caller is expected to do the initial continue of the stub. This gets rid of an argument and some logic. The fname argument is gone, as that can be had from a stack trace. user_signal() is collapsed into userspace() as it is basically one or two lines of code afterwards. The physical memory remapping stuff is gone, as it is unused. flush_tlb_page is inlined. Signed-off-by: Jeff Dike <jdike@linux.intel.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
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);