aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/um/os-Linux
diff options
context:
space:
mode:
authorEli Cooper <elicooper@gmx.com>2016-03-19 12:58:41 -0400
committerRichard Weinberger <richard@nod.at>2016-05-21 17:38:06 -0400
commita78ff1112263fdd871d3506dbcff44f6f12e8423 (patch)
treee57ced8c83977e3686b8a69343cc5541565b8b94 /arch/x86/um/os-Linux
parentb6024b21fec8367ef961a771cc9dde31f1831965 (diff)
um: add extended processor state save/restore support
This patch extends save_fp_registers() and restore_fp_registers() to use PTRACE_GETREGSET and PTRACE_SETREGSET with the XSTATE note type, adding support for new processor state extensions between context switches. When the new ptrace requests are unavailable, it falls back to the old PTRACE_GETFPREGS and PTRACE_SETFPREGS methods, which have been renamed to save_i387_registers() and restore_i387_registers(). Now these functions expect *fp_regs to have the space of an _xstate struct. Thus, this also makes ptrace in UML responde to PTRACE_GETFPREGS/_SETFPREG requests with a user_i387_struct (thus independent from HOST_FP_SIZE), and by calling save_i387_registers() and restore_i387_registers() instead of the extended save_fp_registers() and restore_fp_registers() functions. Signed-off-by: Eli Cooper <elicooper@gmx.com>
Diffstat (limited to 'arch/x86/um/os-Linux')
-rw-r--r--arch/x86/um/os-Linux/registers.c49
1 files changed, 47 insertions, 2 deletions
diff --git a/arch/x86/um/os-Linux/registers.c b/arch/x86/um/os-Linux/registers.c
index 41bfe84e11ab..00f54a91bb4b 100644
--- a/arch/x86/um/os-Linux/registers.c
+++ b/arch/x86/um/os-Linux/registers.c
@@ -11,21 +11,56 @@
11#endif 11#endif
12#include <longjmp.h> 12#include <longjmp.h>
13#include <sysdep/ptrace_user.h> 13#include <sysdep/ptrace_user.h>
14#include <sys/uio.h>
15#include <asm/sigcontext.h>
16#include <linux/elf.h>
14 17
15int save_fp_registers(int pid, unsigned long *fp_regs) 18int have_xstate_support;
19
20int save_i387_registers(int pid, unsigned long *fp_regs)
16{ 21{
17 if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0) 22 if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
18 return -errno; 23 return -errno;
19 return 0; 24 return 0;
20} 25}
21 26
22int restore_fp_registers(int pid, unsigned long *fp_regs) 27int save_fp_registers(int pid, unsigned long *fp_regs)
28{
29 struct iovec iov;
30
31 if (have_xstate_support) {
32 iov.iov_base = fp_regs;
33 iov.iov_len = sizeof(struct _xstate);
34 if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
35 return -errno;
36 return 0;
37 } else {
38 return save_i387_registers(pid, fp_regs);
39 }
40}
41
42int restore_i387_registers(int pid, unsigned long *fp_regs)
23{ 43{
24 if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0) 44 if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
25 return -errno; 45 return -errno;
26 return 0; 46 return 0;
27} 47}
28 48
49int restore_fp_registers(int pid, unsigned long *fp_regs)
50{
51 struct iovec iov;
52
53 if (have_xstate_support) {
54 iov.iov_base = fp_regs;
55 iov.iov_len = sizeof(struct _xstate);
56 if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
57 return -errno;
58 return 0;
59 } else {
60 return restore_i387_registers(pid, fp_regs);
61 }
62}
63
29#ifdef __i386__ 64#ifdef __i386__
30int have_fpx_regs = 1; 65int have_fpx_regs = 1;
31int save_fpx_registers(int pid, unsigned long *fp_regs) 66int save_fpx_registers(int pid, unsigned long *fp_regs)
@@ -85,6 +120,16 @@ int put_fp_registers(int pid, unsigned long *regs)
85 return restore_fp_registers(pid, regs); 120 return restore_fp_registers(pid, regs);
86} 121}
87 122
123void arch_init_registers(int pid)
124{
125 struct _xstate fp_regs;
126 struct iovec iov;
127
128 iov.iov_base = &fp_regs;
129 iov.iov_len = sizeof(struct _xstate);
130 if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0)
131 have_xstate_support = 1;
132}
88#endif 133#endif
89 134
90unsigned long get_thread_reg(int reg, jmp_buf *buf) 135unsigned long get_thread_reg(int reg, jmp_buf *buf)