diff options
Diffstat (limited to 'arch/um/os-Linux')
-rw-r--r-- | arch/um/os-Linux/process.c | 2 | ||||
-rw-r--r-- | arch/um/os-Linux/signal.c | 50 | ||||
-rw-r--r-- | arch/um/os-Linux/skas/mem.c | 2 | ||||
-rw-r--r-- | arch/um/os-Linux/skas/process.c | 15 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/signal.c | 8 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86_64/signal.c | 6 | ||||
-rw-r--r-- | arch/um/os-Linux/util.c | 23 |
7 files changed, 67 insertions, 39 deletions
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c index 92a7b59120d6..2d9d2ca39299 100644 --- a/arch/um/os-Linux/process.c +++ b/arch/um/os-Linux/process.c @@ -239,6 +239,7 @@ out: return ok; } +#ifdef UML_CONFIG_MODE_TT void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) { int flags = 0, pages; @@ -260,6 +261,7 @@ void init_new_thread_stack(void *sig_stack, void (*usr1_handler)(int)) "errno = %d\n", errno); } } +#endif void init_new_thread_signals(void) { diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c index 48d493415301..18e5c8b67eb8 100644 --- a/arch/um/os-Linux/signal.c +++ b/arch/um/os-Linux/signal.c @@ -61,15 +61,19 @@ void sig_handler(int sig, struct sigcontext *sc) static void real_alarm_handler(int sig, struct sigcontext *sc) { + union uml_pt_regs regs; + if(sig == SIGALRM) switch_timers(0); - CHOOSE_MODE_PROC(sig_handler_common_tt, sig_handler_common_skas, - sig, sc); + if(sc != NULL) + copy_sc(®s, sc); + regs.skas.is_user = 0; + unblock_signals(); + timer_handler(sig, ®s); if(sig == SIGALRM) switch_timers(1); - } void alarm_handler(int sig, struct sigcontext *sc) @@ -113,6 +117,46 @@ void remove_sigstack(void) void (*handlers[_NSIG])(int sig, struct sigcontext *sc); +void handle_signal(int sig, struct sigcontext *sc) +{ + unsigned long pending = 0; + + do { + int nested, bail; + + /* + * pending comes back with one bit set for each + * interrupt that arrived while setting up the stack, + * plus a bit for this interrupt, plus the zero bit is + * set if this is a nested interrupt. + * If bail is true, then we interrupted another + * handler setting up the stack. In this case, we + * have to return, and the upper handler will deal + * with this interrupt. + */ + bail = to_irq_stack(sig, &pending); + if(bail) + return; + + nested = pending & 1; + pending &= ~1; + + while((sig = ffs(pending)) != 0){ + sig--; + pending &= ~(1 << sig); + (*handlers[sig])(sig, sc); + } + + /* Again, pending comes back with a mask of signals + * that arrived while tearing down the stack. If this + * is non-zero, we just go back, set up the stack + * again, and handle the new interrupts. + */ + if(!nested) + pending = from_irq_stack(nested); + } while(pending); +} + extern void hard_handler(int sig); void set_handler(int sig, void (*handler)(int), int flags, ...) diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c index 8e490fff3d47..5c8946320799 100644 --- a/arch/um/os-Linux/skas/mem.c +++ b/arch/um/os-Linux/skas/mem.c @@ -68,7 +68,7 @@ static inline long do_syscall_stub(struct mm_id * mm_idp, void **addr) int err, pid = mm_idp->u.pid; if(proc_mm) -#warning Need to look up userspace_pid by cpu + /* FIXME: Need to look up userspace_pid by cpu */ pid = userspace_pid[0]; multi_count++; diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 5c088a55396c..f9d2f8545afe 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -288,7 +288,8 @@ int start_userspace(unsigned long stub_stack) void userspace(union uml_pt_regs *regs) { int err, status, op, pid = userspace_pid[0]; - int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/ + /* To prevent races if using_sysemu changes under us.*/ + int local_using_sysemu; while(1){ restore_registers(pid, regs); @@ -296,7 +297,8 @@ void userspace(union uml_pt_regs *regs) /* Now we set local_using_sysemu to be used for one loop */ local_using_sysemu = get_using_sysemu(); - op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL)); + op = SELECT_PTRACE_OPERATION(local_using_sysemu, + singlestepping(NULL)); err = ptrace(op, pid, 0, 0); if(err) @@ -490,8 +492,8 @@ void map_stub_pages(int fd, unsigned long code, void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)) { (*buf)[0].JB_IP = (unsigned long) handler; - (*buf)[0].JB_SP = (unsigned long) stack + - (PAGE_SIZE << UML_CONFIG_KERNEL_STACK_ORDER) - sizeof(void *); + (*buf)[0].JB_SP = (unsigned long) stack + UM_THREAD_SIZE - + sizeof(void *); } #define INIT_JMP_NEW_THREAD 0 @@ -533,8 +535,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf) case INIT_JMP_NEW_THREAD: (*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 *); + UM_THREAD_SIZE - sizeof(void *); break; case INIT_JMP_CALLBACK: (*cb_proc)(cb_arg); @@ -586,7 +587,7 @@ void switch_mm_skas(struct mm_id *mm_idp) { int err; -#warning need cpu pid in switch_mm_skas + /* FIXME: need cpu pid in switch_mm_skas */ if(proc_mm){ err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, mm_idp->u.mm_fd); diff --git a/arch/um/os-Linux/sys-i386/signal.c b/arch/um/os-Linux/sys-i386/signal.c index 0d3eae518352..f311609f93da 100644 --- a/arch/um/os-Linux/sys-i386/signal.c +++ b/arch/um/os-Linux/sys-i386/signal.c @@ -1,15 +1,13 @@ /* - * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include <signal.h> -extern void (*handlers[])(int sig, struct sigcontext *sc); +extern void handle_signal(int sig, struct sigcontext *sc); void hard_handler(int sig) { - struct sigcontext *sc = (struct sigcontext *) (&sig + 1); - - (*handlers[sig])(sig, sc); + handle_signal(sig, (struct sigcontext *) (&sig + 1)); } diff --git a/arch/um/os-Linux/sys-x86_64/signal.c b/arch/um/os-Linux/sys-x86_64/signal.c index 3f369e5f976b..82a388822cd3 100644 --- a/arch/um/os-Linux/sys-x86_64/signal.c +++ b/arch/um/os-Linux/sys-x86_64/signal.c @@ -1,16 +1,16 @@ /* - * Copyright (C) 2006 Jeff Dike (jdike@addtoit.com) + * Copyright (C) 2006 Jeff Dike (jdike@{addtoit,linux.intel}.com) * Licensed under the GPL */ #include <signal.h> -extern void (*handlers[])(int sig, struct sigcontext *sc); +extern void handle_signal(int sig, struct sigcontext *sc); void hard_handler(int sig) { struct ucontext *uc; asm("movq %%rdx, %0" : "=r" (uc)); - (*handlers[sig])(sig, (struct sigcontext *) &uc->uc_mcontext); + handle_signal(sig, (struct sigcontext *) &uc->uc_mcontext); } diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c index c307a89ed259..7cbcf484e13d 100644 --- a/arch/um/os-Linux/util.c +++ b/arch/um/os-Linux/util.c @@ -33,25 +33,8 @@ void stack_protections(unsigned long address) { - int prot = PROT_READ | PROT_WRITE | PROT_EXEC; - - if(mprotect((void *) address, UM_KERN_PAGE_SIZE, prot) < 0) - panic("protecting stack failed, errno = %d", errno); -} - -void task_protections(unsigned long address) -{ - unsigned long guard = address + UM_KERN_PAGE_SIZE; - unsigned long stack = guard + UM_KERN_PAGE_SIZE; - int prot = 0, pages; - -#ifdef notdef - if(mprotect((void *) stack, UM_KERN_PAGE_SIZE, prot) < 0) - panic("protecting guard page failed, errno = %d", errno); -#endif - pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2; - prot = PROT_READ | PROT_WRITE | PROT_EXEC; - if(mprotect((void *) stack, pages * UM_KERN_PAGE_SIZE, prot) < 0) + if(mprotect((void *) address, UM_THREAD_SIZE, + PROT_READ | PROT_WRITE | PROT_EXEC) < 0) panic("protecting stack failed, errno = %d", errno); } @@ -72,7 +55,7 @@ int raw(int fd) /* XXX tcsetattr could have applied only some changes * (and cfmakeraw() is a set of changes) */ - return(0); + return 0; } void setup_machinename(char *machine_out) |