X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fum%2Fos-Linux%2Fskas%2Fprocess.c;fp=arch%2Fum%2Fos-Linux%2Fskas%2Fprocess.c;h=c4998cf588c037e429bc47fd2ee436117491ae44;hb=97bf2856c6014879bd04983a3e9dfcdac1e7fe85;hp=215ef68e62108646791c5c010454603ed47157fb;hpb=76828883507a47dae78837ab5dec5a5b4513c667;p=linux-2.6.git diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 215ef68e6..c4998cf58 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -8,16 +8,14 @@ #include #include #include -#include #include #include "ptrace_user.h" #include #include #include #include -#include +#include #include -#include #include "user.h" #include "sysdep/ptrace.h" #include "user_util.h" @@ -69,7 +67,7 @@ void wait_stub_done(int pid, int sig, char * fname) if((n < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ - unsigned long regs[HOST_FRAME_SIZE]; + unsigned long regs[MAX_REG_NR]; if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) printk("Failed to get registers from stub, " @@ -78,7 +76,7 @@ void wait_stub_done(int pid, int sig, char * fname) int i; printk("Stub registers -\n"); - for(i = 0; i < HOST_FRAME_SIZE; i++) + for(i = 0; i < ARRAY_SIZE(regs); i++) printk("\t%d - %lx\n", i, regs[i]); } panic("%s : failed to wait for SIGUSR1/SIGTRAP, " @@ -157,11 +155,15 @@ extern int __syscall_stub_start; static int userspace_tramp(void *stack) { void *addr; + int err; ptrace(PTRACE_TRACEME, 0, 0, 0); - init_new_thread_signals(1); - enable_timer(); + init_new_thread_signals(); + err = set_interval(1); + if(err) + panic("userspace_tramp - setting timer failed, errno = %d\n", + err); if(!proc_mm){ /* This has a pte, but it can't be mapped in with the usual @@ -191,14 +193,25 @@ static int userspace_tramp(void *stack) } } if(!ptrace_faultinfo && (stack != NULL)){ + struct sigaction sa; + unsigned long v = UML_CONFIG_STUB_CODE + (unsigned long) stub_segv_handler - (unsigned long) &__syscall_stub_start; set_sigstack((void *) UML_CONFIG_STUB_DATA, page_size()); - set_handler(SIGSEGV, (void *) v, SA_ONSTACK, - SIGIO, SIGWINCH, SIGALRM, SIGVTALRM, - SIGUSR1, -1); + sigemptyset(&sa.sa_mask); + sigaddset(&sa.sa_mask, SIGIO); + sigaddset(&sa.sa_mask, SIGWINCH); + sigaddset(&sa.sa_mask, SIGALRM); + sigaddset(&sa.sa_mask, SIGVTALRM); + sigaddset(&sa.sa_mask, SIGUSR1); + sa.sa_flags = SA_ONSTACK; + sa.sa_handler = (void *) v; + sa.sa_restorer = NULL; + if(sigaction(SIGSEGV, &sa, NULL) < 0) + panic("userspace_tramp - setting SIGSEGV handler " + "failed - errno = %d\n", errno); } os_stop_process(os_getpid()); @@ -266,7 +279,7 @@ void userspace(union uml_pt_regs *regs) if(err) panic("userspace - could not resume userspace process, " "pid=%d, ptrace operation = %d, errno = %d\n", - op, errno); + pid, op, errno); CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED)); if(err < 0) @@ -315,7 +328,7 @@ void userspace(union uml_pt_regs *regs) int copy_context_skas0(unsigned long new_stack, int pid) { int err; - unsigned long regs[HOST_FRAME_SIZE]; + unsigned long regs[MAX_REG_NR]; unsigned long fp_regs[HOST_FP_SIZE]; unsigned long current_stack = current_stub_stack(); struct stub_data *data = (struct stub_data *) current_stack; @@ -345,12 +358,12 @@ int copy_context_skas0(unsigned long new_stack, int pid) err = ptrace_setregs(pid, regs); if(err < 0) panic("copy_context_skas0 : PTRACE_SETREGS failed, " - "pid = %d, errno = %d\n", pid, errno); + "pid = %d, errno = %d\n", pid, -err); err = ptrace_setfpregs(pid, fp_regs); if(err < 0) panic("copy_context_skas0 : PTRACE_SETFPREGS failed, " - "pid = %d, errno = %d\n", pid, errno); + "pid = %d, errno = %d\n", pid, -err); /* set a well known return code for detection of child write failure */ child_data->err = 12345678; @@ -363,14 +376,14 @@ int copy_context_skas0(unsigned long new_stack, int pid) pid = data->err; if(pid < 0) panic("copy_context_skas0 - stub-parent reports error %d\n", - pid); + -pid); /* Wait, until child has finished too: read child's result from * child's stack and check it. */ wait_stub_done(pid, -1, "copy_context_skas0"); if (child_data->err != UML_CONFIG_STUB_DATA) - panic("copy_context_skas0 - stub-child reports error %d\n", + panic("copy_context_skas0 - stub-child reports error %ld\n", child_data->err); if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, @@ -431,89 +444,50 @@ void map_stub_pages(int fd, unsigned long code, } } -void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, - void (*handler)(int)) +void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) { - unsigned long flags; - sigjmp_buf switch_buf, fork_buf; - int enable; - - *switch_buf_ptr = &switch_buf; - *fork_buf_ptr = &fork_buf; - - /* Somewhat subtle - siglongjmp restores the signal mask before doing - * the longjmp. This means that when jumping from one stack to another - * when the target stack has interrupts enabled, an interrupt may occur - * on the source stack. This is bad when starting up a process because - * it's not supposed to get timer ticks until it has been scheduled. - * So, we disable interrupts around the sigsetjmp to ensure that - * they can't happen until we get back here where they are safe. - */ - flags = get_signals(); - block_signals(); - if(UML_SIGSETJMP(&fork_buf, enable) == 0) - new_thread_proc(stack, handler); - - remove_sigstack(); - - set_signals(flags); + (*buf)[0].JB_IP = (unsigned long) handler; + (*buf)[0].JB_SP = (unsigned long) stack + + (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *); } #define INIT_JMP_NEW_THREAD 0 -#define INIT_JMP_REMOVE_SIGSTACK 1 -#define INIT_JMP_CALLBACK 2 -#define INIT_JMP_HALT 3 -#define INIT_JMP_REBOOT 4 +#define INIT_JMP_CALLBACK 1 +#define INIT_JMP_HALT 2 +#define INIT_JMP_REBOOT 3 -void thread_wait(void *sw, void *fb) +void switch_threads(jmp_buf *me, jmp_buf *you) { - sigjmp_buf buf, **switch_buf = sw, *fork_buf; - int enable; - - *switch_buf = &buf; - fork_buf = fb; - if(UML_SIGSETJMP(&buf, enable) == 0) - siglongjmp(*fork_buf, INIT_JMP_REMOVE_SIGSTACK); + if(UML_SETJMP(me) == 0) + UML_LONGJMP(you, 1); } -void switch_threads(void *me, void *next) -{ - sigjmp_buf my_buf, **me_ptr = me, *next_buf = next; - int enable; - - *me_ptr = &my_buf; - if(UML_SIGSETJMP(&my_buf, enable) == 0) - UML_SIGLONGJMP(next_buf, 1); -} - -static sigjmp_buf initial_jmpbuf; +static jmp_buf initial_jmpbuf; /* XXX Make these percpu */ static void (*cb_proc)(void *arg); static void *cb_arg; -static sigjmp_buf *cb_back; +static jmp_buf *cb_back; -int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) +int start_idle_thread(void *stack, jmp_buf *switch_buf) { - sigjmp_buf **switch_buf = switch_buf_ptr; - int n, enable; + int n; set_handler(SIGWINCH, (__sighandler_t) sig_handler, SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGALRM, SIGVTALRM, -1); - *fork_buf_ptr = &initial_jmpbuf; - n = UML_SIGSETJMP(&initial_jmpbuf, enable); + n = UML_SETJMP(&initial_jmpbuf); switch(n){ case INIT_JMP_NEW_THREAD: - new_thread_proc((void *) stack, new_thread_handler); - break; - case INIT_JMP_REMOVE_SIGSTACK: - remove_sigstack(); + (*switch_buf)[0].JB_IP = (unsigned long) new_thread_handler; + (*switch_buf)[0].JB_SP = (unsigned long) stack + + (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - + sizeof(void *); break; case INIT_JMP_CALLBACK: (*cb_proc)(cb_arg); - UML_SIGLONGJMP(cb_back, 1); + UML_LONGJMP(cb_back, 1); break; case INIT_JMP_HALT: kmalloc_ok = 0; @@ -524,21 +498,20 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) default: panic("Bad sigsetjmp return in start_idle_thread - %d\n", n); } - UML_SIGLONGJMP(*switch_buf, 1); + UML_LONGJMP(switch_buf, 1); } void initial_thread_cb_skas(void (*proc)(void *), void *arg) { - sigjmp_buf here; - int enable; + jmp_buf here; cb_proc = proc; cb_arg = arg; cb_back = &here; block_signals(); - if(UML_SIGSETJMP(&here, enable) == 0) - UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); + if(UML_SETJMP(&here) == 0) + UML_LONGJMP(&initial_jmpbuf, INIT_JMP_CALLBACK); unblock_signals(); cb_proc = NULL; @@ -549,13 +522,13 @@ void initial_thread_cb_skas(void (*proc)(void *), void *arg) void halt_skas(void) { block_signals(); - UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_HALT); + UML_LONGJMP(&initial_jmpbuf, INIT_JMP_HALT); } void reboot_skas(void) { block_signals(); - UML_SIGLONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT); + UML_LONGJMP(&initial_jmpbuf, INIT_JMP_REBOOT); } void switch_mm_skas(struct mm_id *mm_idp)