diff options
Diffstat (limited to 'arch/um/os-Linux/skas/process.c')
| -rw-r--r-- | arch/um/os-Linux/skas/process.c | 76 | 
1 files changed, 46 insertions, 30 deletions
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index d6e0a2234b8..908579f2b0a 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -9,31 +9,23 @@  #include <errno.h>  #include <string.h>  #include <sys/mman.h> -#include <sys/ptrace.h>  #include <sys/wait.h>  #include <asm/unistd.h> -#include "as-layout.h" -#include "chan_user.h" -#include "kern_constants.h" -#include "kern_util.h" -#include "mem.h" -#include "os.h" -#include "process.h" -#include "proc_mm.h" -#include "ptrace_user.h" -#include "registers.h" -#include "skas.h" -#include "skas_ptrace.h" -#include "user.h" -#include "sysdep/stub.h" +#include <as-layout.h> +#include <init.h> +#include <kern_util.h> +#include <mem.h> +#include <os.h> +#include <proc_mm.h> +#include <ptrace_user.h> +#include <registers.h> +#include <skas.h> +#include <skas_ptrace.h> +#include <sysdep/stub.h>  int is_skas_winch(int pid, int fd, void *data)  { -	if (pid != getpgrp()) -		return 0; - -	register_winch_irq(-1, fd, -1, data, 0); -	return 1; +	return pid == getpgrp();  }  static int ptrace_dump_regs(int pid) @@ -169,7 +161,7 @@ static void handle_trap(int pid, struct uml_pt_regs *regs,  	if (!local_using_sysemu)  	{ -		err = ptrace(PTRACE_POKEUSR, pid, PT_SYSCALL_NR_OFFSET, +		err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET,  			     __NR_getpid);  		if (err < 0) {  			printk(UM_KERN_ERR "handle_trap - nullifying syscall " @@ -257,8 +249,8 @@ static int userspace_tramp(void *stack)  		set_sigstack((void *) STUB_DATA, UM_KERN_PAGE_SIZE);  		sigemptyset(&sa.sa_mask); -		sa.sa_flags = SA_ONSTACK | SA_NODEFER; -		sa.sa_handler = (void *) v; +		sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO; +		sa.sa_sigaction = (void *) v;  		sa.sa_restorer = NULL;  		if (sigaction(SIGSEGV, &sa, NULL) < 0) {  			printk(UM_KERN_ERR "userspace_tramp - setting SIGSEGV " @@ -354,6 +346,10 @@ void userspace(struct uml_pt_regs *regs)  	int err, status, op, pid = userspace_pid[0];  	/* To prevent races if using_sysemu changes under us.*/  	int local_using_sysemu; +	siginfo_t si; + +	/* Handle any immediate reschedules or signals */ +	interrupt_end();  	if (getitimer(ITIMER_VIRTUAL, &timer))  		printk(UM_KERN_ERR "Failed to get itimer, errno = %d\n", errno); @@ -373,6 +369,9 @@ void userspace(struct uml_pt_regs *regs)  		if (ptrace(PTRACE_SETREGS, pid, 0, regs->gp))  			fatal_sigsegv(); +		if (put_fp_registers(pid, regs->fp)) +			fatal_sigsegv(); +  		/* Now we set local_using_sysemu to be used for one loop */  		local_using_sysemu = get_using_sysemu(); @@ -399,17 +398,27 @@ void userspace(struct uml_pt_regs *regs)  			fatal_sigsegv();  		} +		if (get_fp_registers(pid, regs->fp)) { +			printk(UM_KERN_ERR "userspace -  get_fp_registers failed, " +			       "errno = %d\n", errno); +			fatal_sigsegv(); +		} +  		UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */  		if (WIFSTOPPED(status)) {  			int sig = WSTOPSIG(status); + +			ptrace(PTRACE_GETSIGINFO, pid, 0, (struct siginfo *)&si); +  			switch (sig) {  			case SIGSEGV:  				if (PTRACE_FULL_FAULTINFO ||  				    !ptrace_faultinfo) {  					get_skas_faultinfo(pid,  							   ®s->faultinfo); -					(*sig_info[SIGSEGV])(SIGSEGV, regs); +					(*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si, +							     regs);  				}  				else handle_segv(pid, regs);  				break; @@ -417,14 +426,14 @@ void userspace(struct uml_pt_regs *regs)  			        handle_trap(pid, regs, local_using_sysemu);  				break;  			case SIGTRAP: -				relay_signal(SIGTRAP, regs); +				relay_signal(SIGTRAP, (struct siginfo *)&si, regs);  				break;  			case SIGVTALRM:  				now = os_nsecs();  				if (now < nsecs)  					break;  				block_signals(); -				(*sig_info[sig])(sig, regs); +				(*sig_info[sig])(sig, (struct siginfo *)&si, regs);  				unblock_signals();  				nsecs = timer.it_value.tv_sec *  					UM_NSEC_PER_SEC + @@ -438,7 +447,7 @@ void userspace(struct uml_pt_regs *regs)  			case SIGFPE:  			case SIGWINCH:  				block_signals(); -				(*sig_info[sig])(sig, regs); +				(*sig_info[sig])(sig, (struct siginfo *)&si, regs);  				unblock_signals();  				break;  			default: @@ -457,10 +466,11 @@ void userspace(struct uml_pt_regs *regs)  }  static unsigned long thread_regs[MAX_REG_NR]; +static unsigned long thread_fp_regs[FP_SIZE];  static int __init init_thread_regs(void)  { -	get_safe_registers(thread_regs); +	get_safe_registers(thread_regs, thread_fp_regs);  	/* Set parent's instruction pointer to start of clone-stub */  	thread_regs[REGS_IP_INDEX] = STUB_CODE +  				(unsigned long) stub_clone_handler - @@ -503,6 +513,13 @@ int copy_context_skas0(unsigned long new_stack, int pid)  		return err;  	} +	err = put_fp_registers(pid, thread_fp_regs); +	if (err < 0) { +		printk(UM_KERN_ERR "copy_context_skas0 : put_fp_registers " +		       "failed, pid = %d, err = %d\n", pid, err); +		return err; +	} +  	/* set a well known return code for detection of child write failure */  	child_data->err = 12345678; @@ -644,8 +661,7 @@ int start_idle_thread(void *stack, jmp_buf *switch_buf)  {  	int n; -	set_handler(SIGWINCH, (__sighandler_t) sig_handler, -		    SA_ONSTACK | SA_RESTART, SIGUSR1, SIGIO, SIGVTALRM, -1); +	set_handler(SIGWINCH);  	/*  	 * Can't use UML_SETJMP or UML_LONGJMP here because they save  | 
