summaryrefslogtreecommitdiffstats
path: root/sys/amd64
diff options
context:
space:
mode:
Diffstat (limited to 'sys/amd64')
-rw-r--r--sys/amd64/amd64/elf_machdep.c22
-rw-r--r--sys/amd64/amd64/fpu.c7
-rw-r--r--sys/amd64/amd64/ptrace_machdep.c58
3 files changed, 71 insertions, 16 deletions
diff --git a/sys/amd64/amd64/elf_machdep.c b/sys/amd64/amd64/elf_machdep.c
index fdc4d56..23fa39b 100644
--- a/sys/amd64/amd64/elf_machdep.c
+++ b/sys/amd64/amd64/elf_machdep.c
@@ -44,6 +44,7 @@ __FBSDID("$FreeBSD$");
#include <vm/vm_param.h>
#include <machine/elf.h>
+#include <machine/fpu.h>
#include <machine/md_var.h>
struct sysentvec elf64_freebsd_sysvec = {
@@ -133,12 +134,27 @@ SYSINIT(kelf64, SI_SUB_EXEC, SI_ORDER_ANY,
&kfreebsd_brand_info);
void
-elf64_dump_thread(struct thread *td __unused, void *dst __unused,
- size_t *off __unused)
+elf64_dump_thread(struct thread *td, void *dst, size_t *off)
{
+ void *buf;
+ size_t len;
+
+ len = 0;
+ if (use_xsave) {
+ if (dst != NULL) {
+ fpugetregs(td);
+ len += elf64_populate_note(NT_X86_XSTATE,
+ get_pcb_user_save_td(td), dst,
+ cpu_max_ext_state_size, &buf);
+ *(uint64_t *)((char *)buf + X86_XSTATE_XCR0_OFFSET) =
+ xsave_mask;
+ } else
+ len += elf64_populate_note(NT_X86_XSTATE, NULL, NULL,
+ cpu_max_ext_state_size, NULL);
+ }
+ *off = len;
}
-
/* Process one elf relocation with addend. */
static int
elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data,
diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c
index b0f25ba..f30c073 100644
--- a/sys/amd64/amd64/fpu.c
+++ b/sys/amd64/amd64/fpu.c
@@ -127,6 +127,13 @@ CTASSERT(sizeof(struct savefpu_ymm) == 832);
*/
CTASSERT(sizeof(struct pcb) % XSAVE_AREA_ALIGN == 0);
+/*
+ * Ensure the copy of XCR0 saved in a core is contained in the padding
+ * area.
+ */
+CTASSERT(X86_XSTATE_XCR0_OFFSET >= offsetof(struct savefpu, sv_pad) &&
+ X86_XSTATE_XCR0_OFFSET + sizeof(uint64_t) <= sizeof(struct savefpu));
+
static void fpu_clean_state(void);
SYSCTL_INT(_hw, HW_FLOATINGPT, floatingpoint, CTLFLAG_RD,
diff --git a/sys/amd64/amd64/ptrace_machdep.c b/sys/amd64/amd64/ptrace_machdep.c
index 9fa1917..c96fe26 100644
--- a/sys/amd64/amd64/ptrace_machdep.c
+++ b/sys/amd64/amd64/ptrace_machdep.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
static int
cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data)
{
+ struct ptrace_xstate_info info;
char *savefpu;
int error;
@@ -49,14 +50,14 @@ cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data)
return (EOPNOTSUPP);
switch (req) {
- case PT_GETXSTATE:
+ case PT_GETXSTATE_OLD:
fpugetregs(td);
savefpu = (char *)(get_pcb_user_save_td(td) + 1);
error = copyout(savefpu, addr,
cpu_max_ext_state_size - sizeof(struct savefpu));
break;
- case PT_SETXSTATE:
+ case PT_SETXSTATE_OLD:
if (data > cpu_max_ext_state_size - sizeof(struct savefpu)) {
error = EINVAL;
break;
@@ -70,6 +71,36 @@ cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data)
free(savefpu, M_TEMP);
break;
+ case PT_GETXSTATE_INFO:
+ if (data != sizeof(info)) {
+ error = EINVAL;
+ break;
+ }
+ info.xsave_len = cpu_max_ext_state_size;
+ info.xsave_mask = xsave_mask;
+ error = copyout(&info, addr, data);
+ break;
+
+ case PT_GETXSTATE:
+ fpugetregs(td);
+ savefpu = (char *)(get_pcb_user_save_td(td));
+ error = copyout(savefpu, addr, cpu_max_ext_state_size);
+ break;
+
+ case PT_SETXSTATE:
+ if (data > cpu_max_ext_state_size) {
+ error = EINVAL;
+ break;
+ }
+ savefpu = malloc(data, M_TEMP, M_WAITOK);
+ error = copyin(addr, savefpu, data);
+ if (error == 0)
+ error = fpusetregs(td, (struct savefpu *)savefpu,
+ savefpu + sizeof(struct savefpu), data -
+ sizeof(struct savefpu));
+ free(savefpu, M_TEMP);
+ break;
+
default:
error = EINVAL;
break;
@@ -81,8 +112,6 @@ cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data)
#ifdef COMPAT_FREEBSD32
#define PT_I386_GETXMMREGS (PT_FIRSTMACH + 0)
#define PT_I386_SETXMMREGS (PT_FIRSTMACH + 1)
-#define PT_I386_GETXSTATE (PT_FIRSTMACH + 2)
-#define PT_I386_SETXSTATE (PT_FIRSTMACH + 3)
static int
cpu32_ptrace(struct thread *td, int req, void *addr, int data)
@@ -104,12 +133,12 @@ cpu32_ptrace(struct thread *td, int req, void *addr, int data)
fpstate->sv_env.en_mxcsr &= cpu_mxcsr_mask;
break;
- case PT_I386_GETXSTATE:
- error = cpu_ptrace_xstate(td, PT_GETXSTATE, addr, data);
- break;
-
- case PT_I386_SETXSTATE:
- error = cpu_ptrace_xstate(td, PT_SETXSTATE, addr, data);
+ case PT_GETXSTATE_OLD:
+ case PT_SETXSTATE_OLD:
+ case PT_GETXSTATE_INFO:
+ case PT_GETXSTATE:
+ case PT_SETXSTATE:
+ error = cpu_ptrace_xstate(td, req, addr, data);
break;
default:
@@ -131,13 +160,16 @@ cpu_ptrace(struct thread *td, int req, void *addr, int data)
return (cpu32_ptrace(td, req, addr, data));
#endif
- /* Support old values of PT_GETXSTATE and PT_SETXSTATE. */
+ /* Support old values of PT_GETXSTATE_OLD and PT_SETXSTATE_OLD. */
if (req == PT_FIRSTMACH + 0)
- req = PT_GETXSTATE;
+ req = PT_GETXSTATE_OLD;
if (req == PT_FIRSTMACH + 1)
- req = PT_SETXSTATE;
+ req = PT_SETXSTATE_OLD;
switch (req) {
+ case PT_GETXSTATE_OLD:
+ case PT_SETXSTATE_OLD:
+ case PT_GETXSTATE_INFO:
case PT_GETXSTATE:
case PT_SETXSTATE:
error = cpu_ptrace_xstate(td, req, addr, data);
OpenPOWER on IntegriCloud