diff options
| -rw-r--r-- | arch/um/include/asm/thread_info.h | 3 | ||||
| -rw-r--r-- | arch/um/include/shared/os.h | 2 | ||||
| -rw-r--r-- | arch/um/kernel/process.c | 4 | ||||
| -rw-r--r-- | arch/um/os-Linux/skas/process.c | 17 | ||||
| -rw-r--r-- | arch/x86/um/os-Linux/registers.c | 18 | ||||
| -rw-r--r-- | arch/x86/um/user-offsets.c | 2 |
6 files changed, 27 insertions, 19 deletions
diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h index 053baff03674..9300f7630d2a 100644 --- a/arch/um/include/asm/thread_info.h +++ b/arch/um/include/asm/thread_info.h | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <asm/types.h> | 11 | #include <asm/types.h> |
| 12 | #include <asm/page.h> | 12 | #include <asm/page.h> |
| 13 | #include <asm/segment.h> | 13 | #include <asm/segment.h> |
| 14 | #include <sysdep/ptrace_user.h> | ||
| 14 | 15 | ||
| 15 | struct thread_info { | 16 | struct thread_info { |
| 16 | struct task_struct *task; /* main task structure */ | 17 | struct task_struct *task; /* main task structure */ |
| @@ -22,6 +23,8 @@ struct thread_info { | |||
| 22 | 0-0xBFFFFFFF for user | 23 | 0-0xBFFFFFFF for user |
| 23 | 0-0xFFFFFFFF for kernel */ | 24 | 0-0xFFFFFFFF for kernel */ |
| 24 | struct thread_info *real_thread; /* Points to non-IRQ stack */ | 25 | struct thread_info *real_thread; /* Points to non-IRQ stack */ |
| 26 | unsigned long aux_fp_regs[FP_SIZE]; /* auxiliary fp_regs to save/restore | ||
| 27 | them out-of-band */ | ||
| 25 | }; | 28 | }; |
| 26 | 29 | ||
| 27 | #define INIT_THREAD_INFO(tsk) \ | 30 | #define INIT_THREAD_INFO(tsk) \ |
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h index 574e03fc7ba2..d8ddaf9790d2 100644 --- a/arch/um/include/shared/os.h +++ b/arch/um/include/shared/os.h | |||
| @@ -278,7 +278,7 @@ extern int protect(struct mm_id * mm_idp, unsigned long addr, | |||
| 278 | extern int is_skas_winch(int pid, int fd, void *data); | 278 | extern int is_skas_winch(int pid, int fd, void *data); |
| 279 | extern int start_userspace(unsigned long stub_stack); | 279 | extern int start_userspace(unsigned long stub_stack); |
| 280 | extern int copy_context_skas0(unsigned long stack, int pid); | 280 | extern int copy_context_skas0(unsigned long stack, int pid); |
| 281 | extern void userspace(struct uml_pt_regs *regs); | 281 | extern void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs); |
| 282 | extern int map_stub_pages(int fd, unsigned long code, unsigned long data, | 282 | extern int map_stub_pages(int fd, unsigned long code, unsigned long data, |
| 283 | unsigned long stack); | 283 | unsigned long stack); |
| 284 | extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)); | 284 | extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)); |
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c index 2c7f721eccbc..691b83b10649 100644 --- a/arch/um/kernel/process.c +++ b/arch/um/kernel/process.c | |||
| @@ -131,7 +131,7 @@ void new_thread_handler(void) | |||
| 131 | * callback returns only if the kernel thread execs a process | 131 | * callback returns only if the kernel thread execs a process |
| 132 | */ | 132 | */ |
| 133 | n = fn(arg); | 133 | n = fn(arg); |
| 134 | userspace(¤t->thread.regs.regs); | 134 | userspace(¤t->thread.regs.regs, current_thread_info()->aux_fp_regs); |
| 135 | } | 135 | } |
| 136 | 136 | ||
| 137 | /* Called magically, see new_thread_handler above */ | 137 | /* Called magically, see new_thread_handler above */ |
| @@ -150,7 +150,7 @@ void fork_handler(void) | |||
| 150 | 150 | ||
| 151 | current->thread.prev_sched = NULL; | 151 | current->thread.prev_sched = NULL; |
| 152 | 152 | ||
| 153 | userspace(¤t->thread.regs.regs); | 153 | userspace(¤t->thread.regs.regs, current_thread_info()->aux_fp_regs); |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 156 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 819d68656673..c94c3bd70ccd 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c | |||
| @@ -88,12 +88,11 @@ bad_wait: | |||
| 88 | 88 | ||
| 89 | extern unsigned long current_stub_stack(void); | 89 | extern unsigned long current_stub_stack(void); |
| 90 | 90 | ||
| 91 | static void get_skas_faultinfo(int pid, struct faultinfo *fi) | 91 | static void get_skas_faultinfo(int pid, struct faultinfo *fi, unsigned long *aux_fp_regs) |
| 92 | { | 92 | { |
| 93 | int err; | 93 | int err; |
| 94 | unsigned long fpregs[FP_SIZE]; | ||
| 95 | 94 | ||
| 96 | err = get_fp_registers(pid, fpregs); | 95 | err = get_fp_registers(pid, aux_fp_regs); |
| 97 | if (err < 0) { | 96 | if (err < 0) { |
| 98 | printk(UM_KERN_ERR "save_fp_registers returned %d\n", | 97 | printk(UM_KERN_ERR "save_fp_registers returned %d\n", |
| 99 | err); | 98 | err); |
| @@ -113,7 +112,7 @@ static void get_skas_faultinfo(int pid, struct faultinfo *fi) | |||
| 113 | */ | 112 | */ |
| 114 | memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); | 113 | memcpy(fi, (void *)current_stub_stack(), sizeof(*fi)); |
| 115 | 114 | ||
| 116 | err = put_fp_registers(pid, fpregs); | 115 | err = put_fp_registers(pid, aux_fp_regs); |
| 117 | if (err < 0) { | 116 | if (err < 0) { |
| 118 | printk(UM_KERN_ERR "put_fp_registers returned %d\n", | 117 | printk(UM_KERN_ERR "put_fp_registers returned %d\n", |
| 119 | err); | 118 | err); |
| @@ -121,9 +120,9 @@ static void get_skas_faultinfo(int pid, struct faultinfo *fi) | |||
| 121 | } | 120 | } |
| 122 | } | 121 | } |
| 123 | 122 | ||
| 124 | static void handle_segv(int pid, struct uml_pt_regs * regs) | 123 | static void handle_segv(int pid, struct uml_pt_regs *regs, unsigned long *aux_fp_regs) |
| 125 | { | 124 | { |
| 126 | get_skas_faultinfo(pid, ®s->faultinfo); | 125 | get_skas_faultinfo(pid, ®s->faultinfo, aux_fp_regs); |
| 127 | segv(regs->faultinfo, 0, 1, NULL); | 126 | segv(regs->faultinfo, 0, 1, NULL); |
| 128 | } | 127 | } |
| 129 | 128 | ||
| @@ -332,7 +331,7 @@ int start_userspace(unsigned long stub_stack) | |||
| 332 | return err; | 331 | return err; |
| 333 | } | 332 | } |
| 334 | 333 | ||
| 335 | void userspace(struct uml_pt_regs *regs) | 334 | void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs) |
| 336 | { | 335 | { |
| 337 | int err, status, op, pid = userspace_pid[0]; | 336 | int err, status, op, pid = userspace_pid[0]; |
| 338 | /* To prevent races if using_sysemu changes under us.*/ | 337 | /* To prevent races if using_sysemu changes under us.*/ |
| @@ -407,11 +406,11 @@ void userspace(struct uml_pt_regs *regs) | |||
| 407 | case SIGSEGV: | 406 | case SIGSEGV: |
| 408 | if (PTRACE_FULL_FAULTINFO) { | 407 | if (PTRACE_FULL_FAULTINFO) { |
| 409 | get_skas_faultinfo(pid, | 408 | get_skas_faultinfo(pid, |
| 410 | ®s->faultinfo); | 409 | ®s->faultinfo, aux_fp_regs); |
| 411 | (*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si, | 410 | (*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si, |
| 412 | regs); | 411 | regs); |
| 413 | } | 412 | } |
| 414 | else handle_segv(pid, regs); | 413 | else handle_segv(pid, regs, aux_fp_regs); |
| 415 | break; | 414 | break; |
| 416 | case SIGTRAP + 0x80: | 415 | case SIGTRAP + 0x80: |
| 417 | handle_trap(pid, regs, local_using_sysemu); | 416 | handle_trap(pid, regs, local_using_sysemu); |
diff --git a/arch/x86/um/os-Linux/registers.c b/arch/x86/um/os-Linux/registers.c index 28775f55bde2..3c423dfcd78b 100644 --- a/arch/x86/um/os-Linux/registers.c +++ b/arch/x86/um/os-Linux/registers.c | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | */ | 5 | */ |
| 6 | 6 | ||
| 7 | #include <errno.h> | 7 | #include <errno.h> |
| 8 | #include <stdlib.h> | ||
| 8 | #include <sys/ptrace.h> | 9 | #include <sys/ptrace.h> |
| 9 | #ifdef __i386__ | 10 | #ifdef __i386__ |
| 10 | #include <sys/user.h> | 11 | #include <sys/user.h> |
| @@ -31,7 +32,7 @@ int save_fp_registers(int pid, unsigned long *fp_regs) | |||
| 31 | 32 | ||
| 32 | if (have_xstate_support) { | 33 | if (have_xstate_support) { |
| 33 | iov.iov_base = fp_regs; | 34 | iov.iov_base = fp_regs; |
| 34 | iov.iov_len = sizeof(struct _xstate); | 35 | iov.iov_len = FP_SIZE * sizeof(unsigned long); |
| 35 | if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) | 36 | if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0) |
| 36 | return -errno; | 37 | return -errno; |
| 37 | return 0; | 38 | return 0; |
| @@ -51,10 +52,9 @@ int restore_fp_registers(int pid, unsigned long *fp_regs) | |||
| 51 | { | 52 | { |
| 52 | #ifdef PTRACE_SETREGSET | 53 | #ifdef PTRACE_SETREGSET |
| 53 | struct iovec iov; | 54 | struct iovec iov; |
| 54 | |||
| 55 | if (have_xstate_support) { | 55 | if (have_xstate_support) { |
| 56 | iov.iov_base = fp_regs; | 56 | iov.iov_base = fp_regs; |
| 57 | iov.iov_len = sizeof(struct _xstate); | 57 | iov.iov_len = FP_SIZE * sizeof(unsigned long); |
| 58 | if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) | 58 | if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0) |
| 59 | return -errno; | 59 | return -errno; |
| 60 | return 0; | 60 | return 0; |
| @@ -125,13 +125,19 @@ int put_fp_registers(int pid, unsigned long *regs) | |||
| 125 | void arch_init_registers(int pid) | 125 | void arch_init_registers(int pid) |
| 126 | { | 126 | { |
| 127 | #ifdef PTRACE_GETREGSET | 127 | #ifdef PTRACE_GETREGSET |
| 128 | struct _xstate fp_regs; | 128 | void * fp_regs; |
| 129 | struct iovec iov; | 129 | struct iovec iov; |
| 130 | 130 | ||
| 131 | iov.iov_base = &fp_regs; | 131 | fp_regs = malloc(FP_SIZE * sizeof(unsigned long)); |
| 132 | iov.iov_len = sizeof(struct _xstate); | 132 | if(fp_regs == NULL) |
| 133 | return; | ||
| 134 | |||
| 135 | iov.iov_base = fp_regs; | ||
| 136 | iov.iov_len = FP_SIZE * sizeof(unsigned long); | ||
| 133 | if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0) | 137 | if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0) |
| 134 | have_xstate_support = 1; | 138 | have_xstate_support = 1; |
| 139 | |||
| 140 | free(fp_regs); | ||
| 135 | #endif | 141 | #endif |
| 136 | } | 142 | } |
| 137 | #endif | 143 | #endif |
diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c index 02250b2633b8..3099c209546f 100644 --- a/arch/x86/um/user-offsets.c +++ b/arch/x86/um/user-offsets.c | |||
| @@ -51,7 +51,7 @@ void foo(void) | |||
| 51 | DEFINE(HOST_ORIG_AX, ORIG_EAX); | 51 | DEFINE(HOST_ORIG_AX, ORIG_EAX); |
| 52 | #else | 52 | #else |
| 53 | #ifdef FP_XSTATE_MAGIC1 | 53 | #ifdef FP_XSTATE_MAGIC1 |
| 54 | DEFINE(HOST_FP_SIZE, sizeof(struct _xstate) / sizeof(unsigned long)); | 54 | DEFINE_LONGS(HOST_FP_SIZE, 2696); |
| 55 | #else | 55 | #else |
| 56 | DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long)); | 56 | DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long)); |
| 57 | #endif | 57 | #endif |
