aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/um/include/asm/thread_info.h3
-rw-r--r--arch/um/include/shared/os.h2
-rw-r--r--arch/um/kernel/process.c4
-rw-r--r--arch/um/os-Linux/skas/process.c17
-rw-r--r--arch/x86/um/os-Linux/registers.c18
-rw-r--r--arch/x86/um/user-offsets.c2
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
15struct thread_info { 16struct 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,
278extern int is_skas_winch(int pid, int fd, void *data); 278extern int is_skas_winch(int pid, int fd, void *data);
279extern int start_userspace(unsigned long stub_stack); 279extern int start_userspace(unsigned long stub_stack);
280extern int copy_context_skas0(unsigned long stack, int pid); 280extern int copy_context_skas0(unsigned long stack, int pid);
281extern void userspace(struct uml_pt_regs *regs); 281extern void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs);
282extern int map_stub_pages(int fd, unsigned long code, unsigned long data, 282extern int map_stub_pages(int fd, unsigned long code, unsigned long data,
283 unsigned long stack); 283 unsigned long stack);
284extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void)); 284extern 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(&current->thread.regs.regs); 134 userspace(&current->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(&current->thread.regs.regs); 153 userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs);
154} 154}
155 155
156int copy_thread(unsigned long clone_flags, unsigned long sp, 156int 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
89extern unsigned long current_stub_stack(void); 89extern unsigned long current_stub_stack(void);
90 90
91static void get_skas_faultinfo(int pid, struct faultinfo *fi) 91static 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
124static void handle_segv(int pid, struct uml_pt_regs * regs) 123static void handle_segv(int pid, struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
125{ 124{
126 get_skas_faultinfo(pid, &regs->faultinfo); 125 get_skas_faultinfo(pid, &regs->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
335void userspace(struct uml_pt_regs *regs) 334void 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 &regs->faultinfo); 409 &regs->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)
125void arch_init_registers(int pid) 125void 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