diff options
-rw-r--r-- | arch/um/include/registers.h | 2 | ||||
-rw-r--r-- | arch/um/include/sysdep-i386/ptrace_user.h | 3 | ||||
-rw-r--r-- | arch/um/include/sysdep-x86_64/ptrace_user.h | 3 | ||||
-rw-r--r-- | arch/um/os-Linux/skas/process.c | 15 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-i386/registers.c | 16 | ||||
-rw-r--r-- | arch/um/os-Linux/sys-x86_64/registers.c | 10 |
6 files changed, 49 insertions, 0 deletions
diff --git a/arch/um/include/registers.h b/arch/um/include/registers.h index 9ea1ae3c8f46..b0b4589e0ebc 100644 --- a/arch/um/include/registers.h +++ b/arch/um/include/registers.h @@ -18,5 +18,7 @@ extern int restore_registers(int pid, struct uml_pt_regs *regs); extern int init_registers(int pid); extern void get_safe_registers(unsigned long *regs); extern unsigned long get_thread_reg(int reg, jmp_buf *buf); +extern int get_fp_registers(int pid, unsigned long *regs); +extern int put_fp_registers(int pid, unsigned long *regs); #endif diff --git a/arch/um/include/sysdep-i386/ptrace_user.h b/arch/um/include/sysdep-i386/ptrace_user.h index 899aa4b2a78d..75650723c38f 100644 --- a/arch/um/include/sysdep-i386/ptrace_user.h +++ b/arch/um/include/sysdep-i386/ptrace_user.h @@ -9,6 +9,7 @@ #include <sys/ptrace.h> #include <linux/ptrace.h> #include <asm/ptrace.h> +#include "user_constants.h" #define PT_OFFSET(r) ((r) * sizeof(long)) @@ -40,6 +41,8 @@ #define PT_SP_OFFSET PT_OFFSET(UESP) #define PT_SP(regs) ((regs)[UESP]) +#define FP_SIZE ((HOST_XFP_SIZE > HOST_FP_SIZE) ? HOST_XFP_SIZE : HOST_FP_SIZE) + #ifndef FRAME_SIZE #define FRAME_SIZE (17) #endif diff --git a/arch/um/include/sysdep-x86_64/ptrace_user.h b/arch/um/include/sysdep-x86_64/ptrace_user.h index 4cd61a852fab..45c0bd881cb3 100644 --- a/arch/um/include/sysdep-x86_64/ptrace_user.h +++ b/arch/um/include/sysdep-x86_64/ptrace_user.h @@ -12,6 +12,7 @@ #include <linux/ptrace.h> #include <asm/ptrace.h> #undef __FRAME_OFFSETS +#include "user_constants.h" #define PT_INDEX(off) ((off) / sizeof(unsigned long)) @@ -69,6 +70,8 @@ #define REGS_IP_INDEX PT_INDEX(RIP) #define REGS_SP_INDEX PT_INDEX(RSP) +#define FP_SIZE (HOST_FP_SIZE) + #endif /* diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index b14829469fae..1e8cba6550a9 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -115,6 +115,14 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi) sizeof(struct ptrace_faultinfo)); } else { + unsigned long fpregs[FP_SIZE]; + + err = get_fp_registers(pid, fpregs); + if (err < 0) { + printk(UM_KERN_ERR "save_fp_registers returned %d\n", + err); + fatal_sigsegv(); + } err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV); if (err) { printk(UM_KERN_ERR "Failed to continue stub, pid = %d, " @@ -128,6 +136,13 @@ void get_skas_faultinfo(int pid, struct faultinfo * fi) * the stub stack page. We just have to copy it. */ memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); + + err = put_fp_registers(pid, fpregs); + if (err < 0) { + printk(UM_KERN_ERR "put_fp_registers returned %d\n", + err); + fatal_sigsegv(); + } } } diff --git a/arch/um/os-Linux/sys-i386/registers.c b/arch/um/os-Linux/sys-i386/registers.c index f74d853a0ee0..b613473b3ec1 100644 --- a/arch/um/os-Linux/sys-i386/registers.c +++ b/arch/um/os-Linux/sys-i386/registers.c @@ -56,6 +56,22 @@ unsigned long get_thread_reg(int reg, jmp_buf *buf) int have_fpx_regs = 1; +int get_fp_registers(int pid, unsigned long *regs) +{ + if (have_fpx_regs) + return save_fpx_registers(pid, regs); + else + return save_fp_registers(pid, regs); +} + +int put_fp_registers(int pid, unsigned long *regs) +{ + if (have_fpx_regs) + return restore_fpx_registers(pid, regs); + else + return restore_fp_registers(pid, regs); +} + void arch_init_registers(int pid) { unsigned long fpx_regs[HOST_XFP_SIZE]; diff --git a/arch/um/os-Linux/sys-x86_64/registers.c b/arch/um/os-Linux/sys-x86_64/registers.c index a375853337a7..594d97ad02b3 100644 --- a/arch/um/os-Linux/sys-x86_64/registers.c +++ b/arch/um/os-Linux/sys-x86_64/registers.c @@ -40,3 +40,13 @@ unsigned long get_thread_reg(int reg, jmp_buf *buf) return 0; } } + +int get_fp_registers(int pid, unsigned long *regs) +{ + return save_fp_registers(pid, regs); +} + +int put_fp_registers(int pid, unsigned long *regs) +{ + return restore_fp_registers(pid, regs); +} |