[Zrouter-src-freebsd] ZRouter.org: push to FreeBSD HEAD tree
zrouter-src-freebsd at zrouter.org
zrouter-src-freebsd at zrouter.org
Wed Feb 1 10:56:51 UTC 2012
details: http://zrouter.org/hg/FreeBSD/head//rev/09f923a839c9
changeset: 319:09f923a839c9
user: ray at terran.dlink.ua
date: Wed Feb 01 11:53:18 2012 +0200
description:
Update sys/amd64
diffstat:
head/sys/amd64/acpica/acpi_switch.S | 25 ++-
head/sys/amd64/acpica/acpi_wakecode.S | 8 +-
head/sys/amd64/acpica/acpi_wakeup.c | 16 +-
head/sys/amd64/amd64/cpu_switch.S | 32 ++-
head/sys/amd64/amd64/fpu.c | 315 ++++++++++++++++++++++++++++---
head/sys/amd64/amd64/genassym.c | 4 +-
head/sys/amd64/amd64/initcpu.c | 3 +-
head/sys/amd64/amd64/machdep.c | 142 +++++++++++--
head/sys/amd64/amd64/minidump_machdep.c | 6 +-
head/sys/amd64/amd64/mp_machdep.c | 6 +-
head/sys/amd64/amd64/ptrace_machdep.c | 141 ++++++++++++++
head/sys/amd64/amd64/sys_machdep.c | 28 ++-
head/sys/amd64/amd64/trap.c | 4 +-
head/sys/amd64/amd64/uma_machdep.c | 5 +-
head/sys/amd64/amd64/vm_machdep.c | 72 ++++++-
head/sys/amd64/conf/GENERIC | 3 +-
head/sys/amd64/conf/NOTES | 7 +-
head/sys/amd64/ia32/ia32_reg.c | 8 +-
head/sys/amd64/ia32/ia32_signal.c | 119 +++++++++--
head/sys/amd64/include/cpufunc.h | 2 +-
head/sys/amd64/include/float.h | 18 +-
head/sys/amd64/include/fpu.h | 77 +++++--
head/sys/amd64/include/frame.h | 5 +-
head/sys/amd64/include/md_var.h | 12 +-
head/sys/amd64/include/pcb.h | 6 +-
head/sys/amd64/include/pcpu.h | 4 +-
head/sys/amd64/include/ptrace.h | 7 +-
head/sys/amd64/include/signal.h | 7 +-
head/sys/amd64/include/specialreg.h | 15 +-
head/sys/amd64/include/sysarch.h | 14 +-
head/sys/amd64/include/ucontext.h | 10 +-
31 files changed, 958 insertions(+), 163 deletions(-)
diffs (2297 lines):
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/acpica/acpi_switch.S
--- a/head/sys/amd64/acpica/acpi_switch.S Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/acpica/acpi_switch.S Wed Feb 01 11:53:18 2012 +0200
@@ -1,7 +1,7 @@
/*-
* Copyright (c) 2001 Takanori Watanabe <takawata at jp.freebsd.org>
* Copyright (c) 2001 Mitsuru IWASAKI <iwasaki at jp.freebsd.org>
- * Copyright (c) 2008-2010 Jung-uk Kim <jkim at FreeBSD.org>
+ * Copyright (c) 2008-2012 Jung-uk Kim <jkim at FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,7 +25,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/amd64/acpica/acpi_switch.S 230830 2012-01-31 17:51:30Z jkim $
*/
#include <machine/asmacros.h>
@@ -95,7 +95,6 @@
/* Restore CR0 except for FPU mode. */
movq PCB_CR0(%rdi), %rax
- movq %rax, %rcx
andq $~(CR0_EM | CR0_TS), %rax
movq %rax, %cr0
@@ -146,10 +145,26 @@
/* Restore FPU state. */
fninit
- fxrstor PCB_USERFPU(%rdi)
+ movq WAKEUP_CTX(xsmask), %rax
+ testq %rax, %rax
+ jz 1f
+ movq %rax, %rdx
+ shrq $32, %rdx
+ movl $XCR0, %ecx
+/* xsetbv */
+ .byte 0x0f, 0x01, 0xd1
+ movq WAKEUP_CTX(fpusave), %rcx
+/* xrstor (%rcx) */
+ .byte 0x0f, 0xae, 0x29
+ jmp 2f
+1:
+ movq WAKEUP_CTX(fpusave), %rcx
+ fxrstor (%rcx)
+2:
/* Reload CR0. */
- movq %rcx, %cr0
+ movq PCB_CR0(%rdi), %rax
+ movq %rax, %cr0
/* Restore return address. */
movq PCB_RIP(%rdi), %rax
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/acpica/acpi_wakecode.S
--- a/head/sys/amd64/acpica/acpi_wakecode.S Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/acpica/acpi_wakecode.S Wed Feb 01 11:53:18 2012 +0200
@@ -2,7 +2,7 @@
* Copyright (c) 2001 Takanori Watanabe <takawata at jp.freebsd.org>
* Copyright (c) 2001 Mitsuru IWASAKI <iwasaki at jp.freebsd.org>
* Copyright (c) 2003 Peter Wemm
- * Copyright (c) 2008-2010 Jung-uk Kim <jkim at FreeBSD.org>
+ * Copyright (c) 2008-2012 Jung-uk Kim <jkim at FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/amd64/acpica/acpi_wakecode.S 230830 2012-01-31 17:51:30Z jkim $
*/
#include <machine/asmacros.h>
@@ -267,6 +267,8 @@
.quad 0
wakeup_pcb:
.quad 0
+wakeup_fpusave:
+ .quad 0
wakeup_gdt:
.word 0
.quad 0
@@ -282,6 +284,8 @@
.quad 0
wakeup_sfmask:
.quad 0
+wakeup_xsmask:
+ .quad 0
wakeup_cpu:
.long 0
dummy:
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/acpica/acpi_wakeup.c
--- a/head/sys/amd64/acpica/acpi_wakeup.c Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/acpica/acpi_wakeup.c Wed Feb 01 11:53:18 2012 +0200
@@ -2,7 +2,7 @@
* Copyright (c) 2001 Takanori Watanabe <takawata at jp.freebsd.org>
* Copyright (c) 2001 Mitsuru IWASAKI <iwasaki at jp.freebsd.org>
* Copyright (c) 2003 Peter Wemm
- * Copyright (c) 2008-2010 Jung-uk Kim <jkim at FreeBSD.org>
+ * Copyright (c) 2008-2012 Jung-uk Kim <jkim at FreeBSD.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/acpica/acpi_wakeup.c 223758 2011-07-04 12:04:52Z attilio $");
+__FBSDID("$FreeBSD: head/sys/amd64/acpica/acpi_wakeup.c 230830 2012-01-31 17:51:30Z jkim $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -45,6 +45,7 @@
#include <machine/pcb.h>
#include <machine/pmap.h>
#include <machine/specialreg.h>
+#include <machine/md_var.h>
#ifdef SMP
#include <x86/apicreg.h>
@@ -67,8 +68,10 @@
#ifdef SMP
extern struct pcb **susppcbs;
+extern void **suspfpusave;
#else
static struct pcb **susppcbs;
+static void **suspfpusave;
#endif
int acpi_restorecpu(vm_offset_t, struct pcb *);
@@ -105,6 +108,7 @@
int ms;
WAKECODE_FIXUP(wakeup_pcb, struct pcb *, susppcbs[cpu]);
+ WAKECODE_FIXUP(wakeup_fpusave, void *, suspfpusave[cpu]);
WAKECODE_FIXUP(wakeup_gdt, uint16_t, susppcbs[cpu]->pcb_gdt.rd_limit);
WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t,
susppcbs[cpu]->pcb_gdt.rd_base);
@@ -244,6 +248,7 @@
load_cr3(KPML4phys);
if (savectx(susppcbs[0])) {
+ ctx_fpusave(suspfpusave[0]);
#ifdef SMP
if (!CPU_EMPTY(&wakeup_cpus) &&
suspend_cpus(wakeup_cpus) == 0) {
@@ -256,6 +261,7 @@
WAKECODE_FIXUP(reset_video, uint8_t, (acpi_reset_video != 0));
WAKECODE_FIXUP(wakeup_pcb, struct pcb *, susppcbs[0]);
+ WAKECODE_FIXUP(wakeup_fpusave, void *, suspfpusave[0]);
WAKECODE_FIXUP(wakeup_gdt, uint16_t,
susppcbs[0]->pcb_gdt.rd_limit);
WAKECODE_FIXUP(wakeup_gdt + 2, uint64_t,
@@ -333,8 +339,11 @@
return (NULL);
}
susppcbs = malloc(mp_ncpus * sizeof(*susppcbs), M_DEVBUF, M_WAITOK);
- for (i = 0; i < mp_ncpus; i++)
+ suspfpusave = malloc(mp_ncpus * sizeof(void *), M_DEVBUF, M_WAITOK);
+ for (i = 0; i < mp_ncpus; i++) {
susppcbs[i] = malloc(sizeof(**susppcbs), M_DEVBUF, M_WAITOK);
+ suspfpusave[i] = alloc_fpusave(M_WAITOK);
+ }
return (wakeaddr);
}
@@ -377,6 +386,7 @@
WAKECODE_FIXUP(wakeup_lstar, uint64_t, rdmsr(MSR_LSTAR));
WAKECODE_FIXUP(wakeup_cstar, uint64_t, rdmsr(MSR_CSTAR));
WAKECODE_FIXUP(wakeup_sfmask, uint64_t, rdmsr(MSR_SF_MASK));
+ WAKECODE_FIXUP(wakeup_xsmask, uint64_t, xsave_mask);
/* Build temporary page tables below realmode code. */
pt4 = wakeaddr;
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/amd64/cpu_switch.S
--- a/head/sys/amd64/amd64/cpu_switch.S Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/amd64/cpu_switch.S Wed Feb 01 11:53:18 2012 +0200
@@ -30,7 +30,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/amd64/amd64/cpu_switch.S 230426 2012-01-21 17:45:27Z kib $
*/
#include <machine/asmacros.h>
@@ -112,16 +112,25 @@
/* have we used fp, and need a save? */
cmpq %rdi,PCPU(FPCURTHREAD)
- jne 1f
+ jne 3f
movq PCB_SAVEFPU(%r8),%r8
clts
+ cmpl $0,use_xsave
+ jne 1f
fxsave (%r8)
- smsw %ax
+ jmp 2f
+1: movq %rdx,%rcx
+ movl xsave_mask,%eax
+ movl xsave_mask+4,%edx
+/* xsave (%r8) */
+ .byte 0x41,0x0f,0xae,0x20
+ movq %rcx,%rdx
+2: smsw %ax
orb $CR0_TS,%al
lmsw %ax
xorl %eax,%eax
movq %rax,PCPU(FPCURTHREAD)
-1:
+3:
/* Save is done. Now fire up new thread. Leave old vmspace. */
movq TD_PCB(%rsi),%r8
@@ -354,10 +363,19 @@
sldt PCB_LDT(%rdi)
str PCB_TR(%rdi)
- clts
- fxsave PCB_USERFPU(%rdi)
- movq %rsi,%cr0 /* The previous %cr0 is saved in %rsi. */
+2: movq %rsi,%cr0 /* The previous %cr0 is saved in %rsi. */
movl $1,%eax
ret
END(savectx)
+
+/*
+ * Wrapper around fpusave to care about TS0_CR.
+ */
+ENTRY(ctx_fpusave)
+ movq %cr0,%rsi
+ clts
+ call fpusave
+ movq %rsi,%cr0
+ ret
+END(ctx_fpusave)
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/amd64/fpu.c
--- a/head/sys/amd64/amd64/fpu.c Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/amd64/fpu.c Wed Feb 01 11:53:18 2012 +0200
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/fpu.c 230766 2012-01-30 07:53:33Z kib $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -78,6 +78,41 @@
: : "n" (CR0_TS) : "ax")
#define stop_emulating() __asm __volatile("clts")
+static __inline void
+xrstor(char *addr, uint64_t mask)
+{
+ uint32_t low, hi;
+
+ low = mask;
+ hi = mask >> 32;
+ /* xrstor (%rdi) */
+ __asm __volatile(".byte 0x0f,0xae,0x2f" : :
+ "a" (low), "d" (hi), "D" (addr));
+}
+
+static __inline void
+xsave(char *addr, uint64_t mask)
+{
+ uint32_t low, hi;
+
+ low = mask;
+ hi = mask >> 32;
+ /* xsave (%rdi) */
+ __asm __volatile(".byte 0x0f,0xae,0x27" : :
+ "a" (low), "d" (hi), "D" (addr) : "memory");
+}
+
+static __inline void
+xsetbv(uint32_t reg, uint64_t val)
+{
+ uint32_t low, hi;
+
+ low = val;
+ hi = val >> 32;
+ __asm __volatile(".byte 0x0f,0x01,0xd1" : :
+ "c" (reg), "a" (low), "d" (hi));
+}
+
#else /* !(__GNUCLIKE_ASM && !lint) */
void fldcw(u_short cw);
@@ -90,25 +125,106 @@
void ldmxcsr(u_int csr);
void start_emulating(void);
void stop_emulating(void);
+void xrstor(char *addr, uint64_t mask);
+void xsave(char *addr, uint64_t mask);
+void xsetbv(uint32_t reg, uint64_t val);
#endif /* __GNUCLIKE_ASM && !lint */
#define GET_FPU_CW(thread) ((thread)->td_pcb->pcb_save->sv_env.en_cw)
#define GET_FPU_SW(thread) ((thread)->td_pcb->pcb_save->sv_env.en_sw)
-typedef u_char bool_t;
+CTASSERT(sizeof(struct savefpu) == 512);
+CTASSERT(sizeof(struct xstate_hdr) == 64);
+CTASSERT(sizeof(struct savefpu_ymm) == 832);
+
+/*
+ * This requirement is to make it easier for asm code to calculate
+ * offset of the fpu save area from the pcb address. FPU save area
+ * must by 64-bytes aligned.
+ */
+CTASSERT(sizeof(struct pcb) % XSAVE_AREA_ALIGN == 0);
static void fpu_clean_state(void);
SYSCTL_INT(_hw, HW_FLOATINGPT, floatingpoint, CTLFLAG_RD,
NULL, 1, "Floating point instructions executed in hardware");
-static struct savefpu fpu_initialstate;
+int use_xsave; /* non-static for cpu_switch.S */
+uint64_t xsave_mask; /* the same */
+static struct savefpu *fpu_initialstate;
+
+void
+fpusave(void *addr)
+{
+
+ if (use_xsave)
+ xsave((char *)addr, xsave_mask);
+ else
+ fxsave((char *)addr);
+}
+
+static void
+fpurestore(void *addr)
+{
+
+ if (use_xsave)
+ xrstor((char *)addr, xsave_mask);
+ else
+ fxrstor((char *)addr);
+}
/*
- * Initialize the floating point unit. On the boot CPU we generate a
- * clean state that is used to initialize the floating point unit when
- * it is first used by a process.
+ * Enable XSAVE if supported and allowed by user.
+ * Calculate the xsave_mask.
+ */
+static void
+fpuinit_bsp1(void)
+{
+ u_int cp[4];
+ uint64_t xsave_mask_user;
+
+ if ((cpu_feature2 & CPUID2_XSAVE) != 0) {
+ use_xsave = 1;
+ TUNABLE_INT_FETCH("hw.use_xsave", &use_xsave);
+ }
+ if (!use_xsave)
+ return;
+
+ cpuid_count(0xd, 0x0, cp);
+ xsave_mask = XFEATURE_ENABLED_X87 | XFEATURE_ENABLED_SSE;
+ if ((cp[0] & xsave_mask) != xsave_mask)
+ panic("CPU0 does not support X87 or SSE: %x", cp[0]);
+ xsave_mask = ((uint64_t)cp[3] << 32) | cp[0];
+ xsave_mask_user = xsave_mask;
+ TUNABLE_ULONG_FETCH("hw.xsave_mask", &xsave_mask_user);
+ xsave_mask_user |= XFEATURE_ENABLED_X87 | XFEATURE_ENABLED_SSE;
+ xsave_mask &= xsave_mask_user;
+}
+
+/*
+ * Calculate the fpu save area size.
+ */
+static void
+fpuinit_bsp2(void)
+{
+ u_int cp[4];
+
+ if (use_xsave) {
+ cpuid_count(0xd, 0x0, cp);
+ cpu_max_ext_state_size = cp[1];
+
+ /*
+ * Reload the cpu_feature2, since we enabled OSXSAVE.
+ */
+ do_cpuid(1, cp);
+ cpu_feature2 = cp[2];
+ } else
+ cpu_max_ext_state_size = sizeof(struct savefpu);
+}
+
+/*
+ * Initialize the floating point unit.
*/
void
fpuinit(void)
@@ -117,6 +233,20 @@
u_int mxcsr;
u_short control;
+ if (IS_BSP())
+ fpuinit_bsp1();
+
+ if (use_xsave) {
+ load_cr4(rcr4() | CR4_XSAVE);
+ xsetbv(XCR0, xsave_mask);
+ }
+
+ /*
+ * XCR0 shall be set up before CPU can report the save area size.
+ */
+ if (IS_BSP())
+ fpuinit_bsp2();
+
/*
* It is too early for critical_enter() to work on AP.
*/
@@ -127,20 +257,46 @@
fldcw(control);
mxcsr = __INITIAL_MXCSR__;
ldmxcsr(mxcsr);
- if (PCPU_GET(cpuid) == 0) {
- fxsave(&fpu_initialstate);
- if (fpu_initialstate.sv_env.en_mxcsr_mask)
- cpu_mxcsr_mask = fpu_initialstate.sv_env.en_mxcsr_mask;
- else
- cpu_mxcsr_mask = 0xFFBF;
- bzero(fpu_initialstate.sv_fp, sizeof(fpu_initialstate.sv_fp));
- bzero(fpu_initialstate.sv_xmm, sizeof(fpu_initialstate.sv_xmm));
- }
start_emulating();
intr_restore(saveintr);
}
/*
+ * On the boot CPU we generate a clean state that is used to
+ * initialize the floating point unit when it is first used by a
+ * process.
+ */
+static void
+fpuinitstate(void *arg __unused)
+{
+ register_t saveintr;
+
+ fpu_initialstate = malloc(cpu_max_ext_state_size, M_DEVBUF,
+ M_WAITOK | M_ZERO);
+ saveintr = intr_disable();
+ stop_emulating();
+
+ fpusave(fpu_initialstate);
+ if (fpu_initialstate->sv_env.en_mxcsr_mask)
+ cpu_mxcsr_mask = fpu_initialstate->sv_env.en_mxcsr_mask;
+ else
+ cpu_mxcsr_mask = 0xFFBF;
+
+ /*
+ * The fninit instruction does not modify XMM registers. The
+ * fpusave call dumped the garbage contained in the registers
+ * after reset to the initial state saved. Clear XMM
+ * registers file image to make the startup program state and
+ * signal handler XMM register content predictable.
+ */
+ bzero(&fpu_initialstate->sv_xmm[0], sizeof(struct xmmacc));
+
+ start_emulating();
+ intr_restore(saveintr);
+}
+SYSINIT(fpuinitstate, SI_SUB_DRIVERS, SI_ORDER_ANY, fpuinitstate, NULL);
+
+/*
* Free coprocessor (if we have it).
*/
void
@@ -150,7 +306,7 @@
critical_enter();
if (curthread == PCPU_GET(fpcurthread)) {
stop_emulating();
- fxsave(PCPU_GET(curpcb)->pcb_save);
+ fpusave(PCPU_GET(curpcb)->pcb_save);
start_emulating();
PCPU_SET(fpcurthread, 0);
}
@@ -423,7 +579,7 @@
* the PCB doesn't contain a clean FPU state. Explicitly
* load an initial state.
*/
- fxrstor(&fpu_initialstate);
+ fpurestore(fpu_initialstate);
if (pcb->pcb_initial_fpucw != __INITIAL_FPUCW__)
fldcw(pcb->pcb_initial_fpucw);
if (PCB_USER_FPU(pcb))
@@ -432,7 +588,7 @@
else
set_pcb_flags(pcb, PCB_FPUINITDONE);
} else
- fxrstor(pcb->pcb_save);
+ fpurestore(pcb->pcb_save);
critical_exit();
}
@@ -461,15 +617,16 @@
pcb = td->td_pcb;
if ((pcb->pcb_flags & PCB_USERFPUINITDONE) == 0) {
- bcopy(&fpu_initialstate, &pcb->pcb_user_save,
- sizeof(fpu_initialstate));
- pcb->pcb_user_save.sv_env.en_cw = pcb->pcb_initial_fpucw;
+ bcopy(fpu_initialstate, get_pcb_user_save_pcb(pcb),
+ cpu_max_ext_state_size);
+ get_pcb_user_save_pcb(pcb)->sv_env.en_cw =
+ pcb->pcb_initial_fpucw;
fpuuserinited(td);
return (_MC_FPOWNED_PCB);
}
critical_enter();
if (td == PCPU_GET(fpcurthread) && PCB_USER_FPU(pcb)) {
- fxsave(&pcb->pcb_user_save);
+ fpusave(get_pcb_user_save_pcb(pcb));
critical_exit();
return (_MC_FPOWNED_FPU);
} else {
@@ -491,25 +648,78 @@
set_pcb_flags(pcb, PCB_FPUINITDONE);
}
+int
+fpusetxstate(struct thread *td, char *xfpustate, size_t xfpustate_size)
+{
+ struct xstate_hdr *hdr, *ehdr;
+ size_t len, max_len;
+ uint64_t bv;
+
+ /* XXXKIB should we clear all extended state in xstate_bv instead ? */
+ if (xfpustate == NULL)
+ return (0);
+ if (!use_xsave)
+ return (EOPNOTSUPP);
+
+ len = xfpustate_size;
+ if (len < sizeof(struct xstate_hdr))
+ return (EINVAL);
+ max_len = cpu_max_ext_state_size - sizeof(struct savefpu);
+ if (len > max_len)
+ return (EINVAL);
+
+ ehdr = (struct xstate_hdr *)xfpustate;
+ bv = ehdr->xstate_bv;
+
+ /*
+ * Avoid #gp.
+ */
+ if (bv & ~xsave_mask)
+ return (EINVAL);
+ if ((bv & (XFEATURE_ENABLED_X87 | XFEATURE_ENABLED_SSE)) !=
+ (XFEATURE_ENABLED_X87 | XFEATURE_ENABLED_SSE))
+ return (EINVAL);
+
+ hdr = (struct xstate_hdr *)(get_pcb_user_save_td(td) + 1);
+
+ hdr->xstate_bv = bv;
+ bcopy(xfpustate + sizeof(struct xstate_hdr),
+ (char *)(hdr + 1), len - sizeof(struct xstate_hdr));
+
+ return (0);
+}
+
/*
* Set the state of the FPU.
*/
-void
-fpusetregs(struct thread *td, struct savefpu *addr)
+int
+fpusetregs(struct thread *td, struct savefpu *addr, char *xfpustate,
+ size_t xfpustate_size)
{
struct pcb *pcb;
+ int error;
pcb = td->td_pcb;
critical_enter();
if (td == PCPU_GET(fpcurthread) && PCB_USER_FPU(pcb)) {
- fxrstor(addr);
+ error = fpusetxstate(td, xfpustate, xfpustate_size);
+ if (error != 0) {
+ critical_exit();
+ return (error);
+ }
+ bcopy(addr, get_pcb_user_save_td(td), sizeof(*addr));
+ fpurestore(get_pcb_user_save_td(td));
critical_exit();
set_pcb_flags(pcb, PCB_FPUINITDONE | PCB_USERFPUINITDONE);
} else {
critical_exit();
- bcopy(addr, &td->td_pcb->pcb_user_save, sizeof(*addr));
+ error = fpusetxstate(td, xfpustate, xfpustate_size);
+ if (error != 0)
+ return (error);
+ bcopy(addr, get_pcb_user_save_td(td), sizeof(*addr));
fpuuserinited(td);
}
+ return (0);
}
/*
@@ -599,20 +809,62 @@
DRIVER_MODULE(fpupnp, acpi, fpupnp_driver, fpupnp_devclass, 0, 0);
#endif /* DEV_ISA */
+static MALLOC_DEFINE(M_FPUKERN_CTX, "fpukern_ctx",
+ "Kernel contexts for FPU state");
+
+#define FPU_KERN_CTX_FPUINITDONE 0x01
+
+struct fpu_kern_ctx {
+ struct savefpu *prev;
+ uint32_t flags;
+ char hwstate1[];
+};
+
+struct fpu_kern_ctx *
+fpu_kern_alloc_ctx(u_int flags)
+{
+ struct fpu_kern_ctx *res;
+ size_t sz;
+
+ sz = sizeof(struct fpu_kern_ctx) + XSAVE_AREA_ALIGN +
+ cpu_max_ext_state_size;
+ res = malloc(sz, M_FPUKERN_CTX, ((flags & FPU_KERN_NOWAIT) ?
+ M_NOWAIT : M_WAITOK) | M_ZERO);
+ return (res);
+}
+
+void
+fpu_kern_free_ctx(struct fpu_kern_ctx *ctx)
+{
+
+ /* XXXKIB clear the memory ? */
+ free(ctx, M_FPUKERN_CTX);
+}
+
+static struct savefpu *
+fpu_kern_ctx_savefpu(struct fpu_kern_ctx *ctx)
+{
+ vm_offset_t p;
+
+ p = (vm_offset_t)&ctx->hwstate1;
+ p = roundup2(p, XSAVE_AREA_ALIGN);
+ return ((struct savefpu *)p);
+}
+
int
fpu_kern_enter(struct thread *td, struct fpu_kern_ctx *ctx, u_int flags)
{
struct pcb *pcb;
pcb = td->td_pcb;
- KASSERT(!PCB_USER_FPU(pcb) || pcb->pcb_save == &pcb->pcb_user_save,
- ("mangled pcb_save"));
+ KASSERT(!PCB_USER_FPU(pcb) || pcb->pcb_save ==
+ get_pcb_user_save_pcb(pcb), ("mangled pcb_save"));
ctx->flags = 0;
if ((pcb->pcb_flags & PCB_FPUINITDONE) != 0)
ctx->flags |= FPU_KERN_CTX_FPUINITDONE;
fpuexit(td);
ctx->prev = pcb->pcb_save;
- pcb->pcb_save = &ctx->hwstate;
+ pcb->pcb_save = fpu_kern_ctx_savefpu(ctx);
set_pcb_flags(pcb, PCB_KERNFPU);
clear_pcb_flags(pcb, PCB_FPUINITDONE);
return (0);
@@ -629,7 +881,7 @@
fpudrop();
critical_exit();
pcb->pcb_save = ctx->prev;
- if (pcb->pcb_save == &pcb->pcb_user_save) {
+ if (pcb->pcb_save == get_pcb_user_save_pcb(pcb)) {
if ((pcb->pcb_flags & PCB_USERFPUINITDONE) != 0) {
set_pcb_flags(pcb, PCB_FPUINITDONE);
clear_pcb_flags(pcb, PCB_KERNFPU);
@@ -653,7 +905,8 @@
pcb = PCPU_GET(curpcb);
KASSERT((curthread->td_pflags & TDP_KTHREAD) != 0,
("Only kthread may use fpu_kern_thread"));
- KASSERT(pcb->pcb_save == &pcb->pcb_user_save, ("mangled pcb_save"));
+ KASSERT(pcb->pcb_save == get_pcb_user_save_pcb(pcb),
+ ("mangled pcb_save"));
KASSERT(PCB_USER_FPU(pcb), ("recursive call"));
set_pcb_flags(pcb, PCB_KERNFPU);
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/amd64/genassym.c
--- a/head/sys/amd64/amd64/genassym.c Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/amd64/genassym.c Wed Feb 01 11:53:18 2012 +0200
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/amd64/genassym.c 225475 2011-09-11 16:08:10Z kib $");
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/genassym.c 230426 2012-01-21 17:45:27Z kib $");
#include "opt_compat.h"
#include "opt_hwpmc_hooks.h"
@@ -156,7 +156,7 @@
ASSYM(PCB_TSSP, offsetof(struct pcb, pcb_tssp));
ASSYM(PCB_SAVEFPU, offsetof(struct pcb, pcb_save));
ASSYM(PCB_SAVEFPU_SIZE, sizeof(struct savefpu));
-ASSYM(PCB_USERFPU, offsetof(struct pcb, pcb_user_save));
+ASSYM(PCB_USERFPU, sizeof(struct pcb));
ASSYM(PCB_SIZE, sizeof(struct pcb));
ASSYM(PCB_FULL_IRET, PCB_FULL_IRET);
ASSYM(PCB_DBREGS, PCB_DBREGS);
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/amd64/initcpu.c
--- a/head/sys/amd64/amd64/initcpu.c Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/amd64/initcpu.c Wed Feb 01 11:53:18 2012 +0200
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/initcpu.c 230426 2012-01-21 17:45:27Z kib $");
#include "opt_cpu.h"
@@ -72,6 +72,7 @@
u_int cpu_fxsr; /* SSE enabled */
u_int cpu_mxcsr_mask; /* Valid bits in mxcsr */
u_int cpu_clflush_line_size = 32;
+u_int cpu_max_ext_state_size;
SYSCTL_UINT(_hw, OID_AUTO, via_feature_rng, CTLFLAG_RD,
&via_feature_rng, 0, "VIA RNG feature available in CPU");
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/amd64/machdep.c
--- a/head/sys/amd64/amd64/machdep.c Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/amd64/machdep.c Wed Feb 01 11:53:18 2012 +0200
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/amd64/machdep.c 229085 2011-12-31 13:24:53Z gavin $");
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/machdep.c 230426 2012-01-21 17:45:27Z kib $");
#include "opt_atalk.h"
#include "opt_atpic.h"
@@ -154,8 +154,10 @@
#define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
static void cpu_startup(void *);
-static void get_fpcontext(struct thread *td, mcontext_t *mcp);
-static int set_fpcontext(struct thread *td, const mcontext_t *mcp);
+static void get_fpcontext(struct thread *td, mcontext_t *mcp,
+ char *xfpusave, size_t xfpusave_len);
+static int set_fpcontext(struct thread *td, const mcontext_t *mcp,
+ char *xfpustate, size_t xfpustate_len);
SYSINIT(cpu, SI_SUB_CPU, SI_ORDER_FIRST, cpu_startup, NULL);
/*
@@ -315,6 +317,8 @@
struct sigacts *psp;
char *sp;
struct trapframe *regs;
+ char *xfpusave;
+ size_t xfpusave_len;
int sig;
int oonstack;
@@ -328,6 +332,14 @@
regs = td->td_frame;
oonstack = sigonstack(regs->tf_rsp);
+ if (cpu_max_ext_state_size > sizeof(struct savefpu) && use_xsave) {
+ xfpusave_len = cpu_max_ext_state_size - sizeof(struct savefpu);
+ xfpusave = __builtin_alloca(xfpusave_len);
+ } else {
+ xfpusave_len = 0;
+ xfpusave = NULL;
+ }
+
/* Save user context. */
bzero(&sf, sizeof(sf));
sf.sf_uc.uc_sigmask = *mask;
@@ -337,7 +349,7 @@
sf.sf_uc.uc_mcontext.mc_onstack = (oonstack) ? 1 : 0;
bcopy(regs, &sf.sf_uc.uc_mcontext.mc_rdi, sizeof(*regs));
sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
- get_fpcontext(td, &sf.sf_uc.uc_mcontext);
+ get_fpcontext(td, &sf.sf_uc.uc_mcontext, xfpusave, xfpusave_len);
fpstate_drop(td);
sf.sf_uc.uc_mcontext.mc_fsbase = pcb->pcb_fsbase;
sf.sf_uc.uc_mcontext.mc_gsbase = pcb->pcb_gsbase;
@@ -348,13 +360,18 @@
/* Allocate space for the signal handler context. */
if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
SIGISMEMBER(psp->ps_sigonstack, sig)) {
- sp = td->td_sigstk.ss_sp +
- td->td_sigstk.ss_size - sizeof(struct sigframe);
+ sp = td->td_sigstk.ss_sp + td->td_sigstk.ss_size;
#if defined(COMPAT_43)
td->td_sigstk.ss_flags |= SS_ONSTACK;
#endif
} else
- sp = (char *)regs->tf_rsp - sizeof(struct sigframe) - 128;
+ sp = (char *)regs->tf_rsp - 128;
+ if (xfpusave != NULL) {
+ sp -= xfpusave_len;
+ sp = (char *)((unsigned long)sp & ~0x3Ful);
+ sf.sf_uc.uc_mcontext.mc_xfpustate = (register_t)sp;
+ }
+ sp -= sizeof(struct sigframe);
/* Align to 16 bytes. */
sfp = (struct sigframe *)((unsigned long)sp & ~0xFul);
@@ -387,7 +404,10 @@
/*
* Copy the sigframe out to the user's stack.
*/
- if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
+ if (copyout(&sf, sfp, sizeof(*sfp)) != 0 ||
+ (xfpusave != NULL && copyout(xfpusave,
+ (void *)sf.sf_uc.uc_mcontext.mc_xfpustate, xfpusave_len)
+ != 0)) {
#ifdef DEBUG
printf("process %ld has trashed its stack\n", (long)p->p_pid);
#endif
@@ -432,6 +452,8 @@
struct proc *p;
struct trapframe *regs;
ucontext_t *ucp;
+ char *xfpustate;
+ size_t xfpustate_len;
long rflags;
int cs, error, ret;
ksiginfo_t ksi;
@@ -490,7 +512,28 @@
return (EINVAL);
}
- ret = set_fpcontext(td, &ucp->uc_mcontext);
+ if ((uc.uc_mcontext.mc_flags & _MC_HASFPXSTATE) != 0) {
+ xfpustate_len = uc.uc_mcontext.mc_xfpustate_len;
+ if (xfpustate_len > cpu_max_ext_state_size -
+ sizeof(struct savefpu)) {
+ uprintf("pid %d (%s): sigreturn xfpusave_len = 0x%zx\n",
+ p->p_pid, td->td_name, xfpustate_len);
+ return (EINVAL);
+ }
+ xfpustate = __builtin_alloca(xfpustate_len);
+ error = copyin((const void *)uc.uc_mcontext.mc_xfpustate,
+ xfpustate, xfpustate_len);
+ if (error != 0) {
+ uprintf(
+ "pid %d (%s): sigreturn copying xfpustate failed\n",
+ p->p_pid, td->td_name);
+ return (error);
+ }
+ } else {
+ xfpustate = NULL;
+ xfpustate_len = 0;
+ }
+ ret = set_fpcontext(td, &ucp->uc_mcontext, xfpustate, xfpustate_len);
if (ret != 0) {
uprintf("pid %d (%s): sigreturn set_fpcontext err %d\n",
p->p_pid, td->td_name, ret);
@@ -1592,6 +1635,7 @@
int gsel_tss, x;
struct pcpu *pc;
struct nmi_pcpu *np;
+ struct xstate_hdr *xhdr;
u_int64_t msr;
char *env;
size_t kstack0_sz;
@@ -1601,7 +1645,6 @@
kstack0_sz = thread0.td_kstack_pages * PAGE_SIZE;
bzero((void *)thread0.td_kstack, kstack0_sz);
physfree += kstack0_sz;
- thread0.td_pcb = (struct pcb *)(thread0.td_kstack + kstack0_sz) - 1;
/*
* This may be done better later if it gets more high level
@@ -1650,7 +1693,6 @@
physfree += DPCPU_SIZE;
PCPU_SET(prvspace, pc);
PCPU_SET(curthread, &thread0);
- PCPU_SET(curpcb, thread0.td_pcb);
PCPU_SET(tssp, &common_tss[0]);
PCPU_SET(commontssp, &common_tss[0]);
PCPU_SET(tss, (struct system_segment_descriptor *)&gdt[GPROC0_SEL]);
@@ -1742,13 +1784,6 @@
initializecpu(); /* Initialize CPU registers */
initializecpucache();
- /* make an initial tss so cpu can get interrupt stack on syscall! */
- common_tss[0].tss_rsp0 = thread0.td_kstack +
- kstack0_sz - sizeof(struct pcb);
- /* Ensure the stack is aligned to 16 bytes */
- common_tss[0].tss_rsp0 &= ~0xFul;
- PCPU_SET(rsp0, common_tss[0].tss_rsp0);
-
/* doublefault stack space, runs on ist1 */
common_tss[0].tss_ist1 = (long)&dblfault_stack[sizeof(dblfault_stack)];
@@ -1785,6 +1820,25 @@
msgbufinit(msgbufp, msgbufsize);
fpuinit();
+ /*
+ * Set up thread0 pcb after fpuinit calculated pcb + fpu save
+ * area size. Zero out the extended state header in fpu save
+ * area.
+ */
+ thread0.td_pcb = get_pcb_td(&thread0);
+ bzero(get_pcb_user_save_td(&thread0), cpu_max_ext_state_size);
+ if (use_xsave) {
+ xhdr = (struct xstate_hdr *)(get_pcb_user_save_td(&thread0) +
+ 1);
+ xhdr->xstate_bv = xsave_mask;
+ }
+ /* make an initial tss so cpu can get interrupt stack on syscall! */
+ common_tss[0].tss_rsp0 = (vm_offset_t)thread0.td_pcb;
+ /* Ensure the stack is aligned to 16 bytes */
+ common_tss[0].tss_rsp0 &= ~0xFul;
+ PCPU_SET(rsp0, common_tss[0].tss_rsp0);
+ PCPU_SET(curpcb, thread0.td_pcb);
+
/* transfer to user mode */
_ucodesel = GSEL(GUCODE_SEL, SEL_UPL);
@@ -2054,7 +2108,7 @@
P_SHOULDSTOP(td->td_proc),
("not suspended thread %p", td));
fpugetregs(td);
- fill_fpregs_xmm(&td->td_pcb->pcb_user_save, fpregs);
+ fill_fpregs_xmm(get_pcb_user_save_td(td), fpregs);
return (0);
}
@@ -2063,7 +2117,7 @@
set_fpregs(struct thread *td, struct fpreg *fpregs)
{
- set_fpregs_xmm(fpregs, &td->td_pcb->pcb_user_save);
+ set_fpregs_xmm(fpregs, get_pcb_user_save_td(td));
fpuuserinited(td);
return (0);
}
@@ -2114,9 +2168,11 @@
mcp->mc_gs = tp->tf_gs;
mcp->mc_flags = tp->tf_flags;
mcp->mc_len = sizeof(*mcp);
- get_fpcontext(td, mcp);
+ get_fpcontext(td, mcp, NULL, 0);
mcp->mc_fsbase = pcb->pcb_fsbase;
mcp->mc_gsbase = pcb->pcb_gsbase;
+ mcp->mc_xfpustate = 0;
+ mcp->mc_xfpustate_len = 0;
bzero(mcp->mc_spare, sizeof(mcp->mc_spare));
return (0);
}
@@ -2132,6 +2188,7 @@
{
struct pcb *pcb;
struct trapframe *tp;
+ char *xfpustate;
long rflags;
int ret;
@@ -2142,7 +2199,18 @@
return (EINVAL);
rflags = (mcp->mc_rflags & PSL_USERCHANGE) |
(tp->tf_rflags & ~PSL_USERCHANGE);
- ret = set_fpcontext(td, mcp);
+ if (mcp->mc_flags & _MC_HASFPXSTATE) {
+ if (mcp->mc_xfpustate_len > cpu_max_ext_state_size -
+ sizeof(struct savefpu))
+ return (EINVAL);
+ xfpustate = __builtin_alloca(mcp->mc_xfpustate_len);
+ ret = copyin((void *)mcp->mc_xfpustate, xfpustate,
+ mcp->mc_xfpustate_len);
+ if (ret != 0)
+ return (ret);
+ } else
+ xfpustate = NULL;
+ ret = set_fpcontext(td, mcp, xfpustate, mcp->mc_xfpustate_len);
if (ret != 0)
return (ret);
tp->tf_r15 = mcp->mc_r15;
@@ -2180,35 +2248,51 @@
}
static void
-get_fpcontext(struct thread *td, mcontext_t *mcp)
+get_fpcontext(struct thread *td, mcontext_t *mcp, char *xfpusave,
+ size_t xfpusave_len)
{
+ size_t max_len, len;
mcp->mc_ownedfp = fpugetregs(td);
- bcopy(&td->td_pcb->pcb_user_save, &mcp->mc_fpstate,
+ bcopy(get_pcb_user_save_td(td), &mcp->mc_fpstate,
sizeof(mcp->mc_fpstate));
mcp->mc_fpformat = fpuformat();
+ if (!use_xsave || xfpusave_len == 0)
+ return;
+ max_len = cpu_max_ext_state_size - sizeof(struct savefpu);
+ len = xfpusave_len;
+ if (len > max_len) {
+ len = max_len;
+ bzero(xfpusave + max_len, len - max_len);
+ }
+ mcp->mc_flags |= _MC_HASFPXSTATE;
+ mcp->mc_xfpustate_len = len;
+ bcopy(get_pcb_user_save_td(td) + 1, xfpusave, len);
}
static int
-set_fpcontext(struct thread *td, const mcontext_t *mcp)
+set_fpcontext(struct thread *td, const mcontext_t *mcp, char *xfpustate,
+ size_t xfpustate_len)
{
struct savefpu *fpstate;
+ int error;
if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
return (0);
else if (mcp->mc_fpformat != _MC_FPFMT_XMM)
return (EINVAL);
- else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE)
+ else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) {
/* We don't care what state is left in the FPU or PCB. */
fpstate_drop(td);
- else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
+ error = 0;
+ } else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
fpstate = (struct savefpu *)&mcp->mc_fpstate;
fpstate->sv_env.en_mxcsr &= cpu_mxcsr_mask;
- fpusetregs(td, fpstate);
+ error = fpusetregs(td, fpstate, xfpustate, xfpustate_len);
} else
return (EINVAL);
- return (0);
+ return (error);
}
void
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/amd64/minidump_machdep.c
--- a/head/sys/amd64/amd64/minidump_machdep.c Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/amd64/minidump_machdep.c Wed Feb 01 11:53:18 2012 +0200
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/amd64/minidump_machdep.c 225194 2011-08-26 17:08:22Z jhb $");
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/minidump_machdep.c 230623 2012-01-27 20:18:31Z kmacy $");
#include "opt_pmap.h"
#include "opt_watchdog.h"
@@ -41,6 +41,7 @@
#include <sys/watchdog.h>
#endif
#include <vm/vm.h>
+#include <vm/vm_page.h>
#include <vm/pmap.h>
#include <machine/atomic.h>
#include <machine/elf.h>
@@ -75,8 +76,11 @@
static int
is_dumpable(vm_paddr_t pa)
{
+ vm_page_t m;
int i;
+ if ((m = vm_phys_paddr_to_vm_page(pa)) != NULL)
+ return ((m->flags & PG_NODUMP) == 0);
for (i = 0; dump_avail[i] != 0 || dump_avail[i + 1] != 0; i += 2) {
if (pa >= dump_avail[i] && pa < dump_avail[i + 1])
return (1);
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/amd64/mp_machdep.c
--- a/head/sys/amd64/amd64/mp_machdep.c Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/amd64/mp_machdep.c Wed Feb 01 11:53:18 2012 +0200
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/amd64/mp_machdep.c 227309 2011-11-07 15:43:11Z ed $");
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/mp_machdep.c 230426 2012-01-21 17:45:27Z kib $");
#include "opt_cpu.h"
#include "opt_kstack_pages.h"
@@ -99,7 +99,8 @@
void *dpcpu;
struct pcb stoppcbs[MAXCPU];
-struct pcb **susppcbs = NULL;
+struct pcb **susppcbs;
+void **suspfpusave;
/* Variables needed for SMP tlb shootdown. */
vm_offset_t smp_tlb_addr1;
@@ -1422,6 +1423,7 @@
cr3 = rcr3();
if (savectx(susppcbs[cpu])) {
+ ctx_fpusave(suspfpusave[cpu]);
wbinvd();
CPU_SET_ATOMIC(cpu, &stopped_cpus);
} else {
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/amd64/ptrace_machdep.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/head/sys/amd64/amd64/ptrace_machdep.c Wed Feb 01 11:53:18 2012 +0200
@@ -0,0 +1,141 @@
+/*-
+ * Copyright (c) 2011 Konstantin Belousov <kib at FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/ptrace_machdep.c 230426 2012-01-21 17:45:27Z kib $");
+
+#include "opt_compat.h"
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/proc.h>
+#include <sys/ptrace.h>
+#include <sys/sysent.h>
+#include <machine/md_var.h>
+#include <machine/pcb.h>
+
+static int
+cpu_ptrace_xstate(struct thread *td, int req, void *addr, int data)
+{
+ char *savefpu;
+ int error;
+
+ if (!use_xsave)
+ return (EOPNOTSUPP);
+
+ switch (req) {
+ case PT_GETXSTATE:
+ 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:
+ if (data > cpu_max_ext_state_size - sizeof(struct savefpu)) {
+ error = EINVAL;
+ break;
+ }
+ savefpu = malloc(data, M_TEMP, M_WAITOK);
+ error = copyin(addr, savefpu, data);
+ if (error == 0)
+ error = fpusetxstate(td, savefpu, data);
+ free(savefpu, M_TEMP);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
+}
+
+#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)
+{
+ struct savefpu *fpstate;
+ int error;
+
+ switch (req) {
+ case PT_I386_GETXMMREGS:
+ error = copyout(get_pcb_user_save_td(td), addr,
+ sizeof(*fpstate));
+ break;
+
+ case PT_I386_SETXMMREGS:
+ fpstate = get_pcb_user_save_td(td);
+ error = copyin(addr, fpstate, sizeof(*fpstate));
+ 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);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
+}
+#endif
+
+int
+cpu_ptrace(struct thread *td, int req, void *addr, int data)
+{
+ int error;
+
+#ifdef COMPAT_FREEBSD32
+ if (SV_CURPROC_FLAG(SV_ILP32))
+ return (cpu32_ptrace(td, req, addr, data));
+#endif
+
+ switch (req) {
+ case PT_GETXSTATE:
+ case PT_SETXSTATE:
+ error = cpu_ptrace_xstate(td, req, addr, data);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ return (error);
+}
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/amd64/sys_machdep.c
--- a/head/sys/amd64/amd64/sys_machdep.c Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/amd64/sys_machdep.c Wed Feb 01 11:53:18 2012 +0200
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/amd64/sys_machdep.c 226498 2011-10-18 07:39:27Z des $");
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/sys_machdep.c 230426 2012-01-21 17:45:27Z kib $");
#include "opt_capsicum.h"
@@ -179,6 +179,8 @@
uint32_t i386base;
uint64_t a64base;
struct i386_ioperm_args iargs;
+ struct i386_get_xfpustate i386xfpu;
+ struct amd64_get_xfpustate a64xfpu;
#ifdef CAPABILITY_MODE
/*
@@ -195,10 +197,12 @@
case I386_SET_FSBASE:
case I386_GET_GSBASE:
case I386_SET_GSBASE:
+ case I386_GET_XFPUSTATE:
case AMD64_GET_FSBASE:
case AMD64_SET_FSBASE:
case AMD64_GET_GSBASE:
case AMD64_SET_GSBASE:
+ case AMD64_GET_XFPUSTATE:
break;
case I386_SET_IOPERM:
@@ -226,6 +230,18 @@
sizeof(struct i386_ioperm_args))) != 0)
return (error);
break;
+ case I386_GET_XFPUSTATE:
+ if ((error = copyin(uap->parms, &i386xfpu,
+ sizeof(struct i386_get_xfpustate))) != 0)
+ return (error);
+ a64xfpu.addr = (void *)(uintptr_t)i386xfpu.addr;
+ a64xfpu.len = i386xfpu.len;
+ break;
+ case AMD64_GET_XFPUSTATE:
+ if ((error = copyin(uap->parms, &a64xfpu,
+ sizeof(struct amd64_get_xfpustate))) != 0)
+ return (error);
+ break;
default:
break;
}
@@ -296,6 +312,16 @@
}
break;
+ case I386_GET_XFPUSTATE:
+ case AMD64_GET_XFPUSTATE:
+ if (a64xfpu.len > cpu_max_ext_state_size -
+ sizeof(struct savefpu))
+ return (EINVAL);
+ fpugetregs(td);
+ error = copyout((char *)(get_pcb_user_save_td(td) + 1),
+ a64xfpu.addr, a64xfpu.len);
+ return (error);
+
default:
error = EINVAL;
break;
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/amd64/trap.c
--- a/head/sys/amd64/amd64/trap.c Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/amd64/trap.c Wed Feb 01 11:53:18 2012 +0200
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/amd64/trap.c 227399 2011-11-09 18:25:50Z kib $");
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/trap.c 230426 2012-01-21 17:45:27Z kib $");
/*
* AMD64 Trap and System call handling
@@ -934,7 +934,7 @@
KASSERT(PCB_USER_FPU(td->td_pcb),
("System call %s returing with kernel FPU ctx leaked",
syscallname(td->td_proc, sa.code)));
- KASSERT(td->td_pcb->pcb_save == &td->td_pcb->pcb_user_save,
+ KASSERT(td->td_pcb->pcb_save == get_pcb_user_save_td(td),
("System call %s returning with mangled pcb_save",
syscallname(td->td_proc, sa.code)));
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/amd64/uma_machdep.c
--- a/head/sys/amd64/amd64/uma_machdep.c Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/amd64/uma_machdep.c Wed Feb 01 11:53:18 2012 +0200
@@ -25,7 +25,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/amd64/uma_machdep.c 226843 2011-10-27 16:39:17Z alc $");
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/uma_machdep.c 230623 2012-01-27 20:18:31Z kmacy $");
#include <sys/param.h>
#include <sys/lock.h>
@@ -65,7 +65,8 @@
break;
}
pa = m->phys_addr;
- dump_add_page(pa);
+ if ((wait & M_NODUMP) == 0)
+ dump_add_page(pa);
va = (void *)PHYS_TO_DMAP(pa);
if ((wait & M_ZERO) && (m->flags & PG_ZERO) == 0)
pagezero(va);
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/amd64/vm_machdep.c
--- a/head/sys/amd64/amd64/vm_machdep.c Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/amd64/vm_machdep.c Wed Feb 01 11:53:18 2012 +0200
@@ -41,7 +41,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/amd64/vm_machdep.c 223758 2011-07-04 12:04:52Z attilio $");
+__FBSDID("$FreeBSD: head/sys/amd64/amd64/vm_machdep.c 230426 2012-01-21 17:45:27Z kib $");
#include "opt_isa.h"
#include "opt_cpu.h"
@@ -90,6 +90,51 @@
static volatile u_int cpu_reset_proxy_active;
#endif
+struct savefpu *
+get_pcb_user_save_td(struct thread *td)
+{
+ vm_offset_t p;
+
+ p = td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
+ cpu_max_ext_state_size;
+ KASSERT((p % 64) == 0, ("Unaligned pcb_user_save area"));
+ return ((struct savefpu *)p);
+}
+
+struct savefpu *
+get_pcb_user_save_pcb(struct pcb *pcb)
+{
+ vm_offset_t p;
+
+ p = (vm_offset_t)(pcb + 1);
+ return ((struct savefpu *)p);
+}
+
+struct pcb *
+get_pcb_td(struct thread *td)
+{
+ vm_offset_t p;
+
+ p = td->td_kstack + td->td_kstack_pages * PAGE_SIZE -
+ cpu_max_ext_state_size - sizeof(struct pcb);
+ return ((struct pcb *)p);
+}
+
+void *
+alloc_fpusave(int flags)
+{
+ struct pcb *res;
+ struct savefpu_ymm *sf;
+
+ res = malloc(cpu_max_ext_state_size, M_DEVBUF, flags);
+ if (use_xsave) {
+ sf = (struct savefpu_ymm *)res;
+ bzero(&sf->sv_xstate.sx_hd, sizeof(sf->sv_xstate.sx_hd));
+ sf->sv_xstate.sx_hd.xstate_bv = xsave_mask;
+ }
+ return (res);
+}
+
/*
* Finish a fork operation, with process p2 nearly set up.
* Copy and update the pcb, set up the stack so that the child
@@ -127,15 +172,16 @@
fpuexit(td1);
/* Point the pcb to the top of the stack */
- pcb2 = (struct pcb *)(td2->td_kstack +
- td2->td_kstack_pages * PAGE_SIZE) - 1;
+ pcb2 = get_pcb_td(td2);
td2->td_pcb = pcb2;
/* Copy td1's pcb */
bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
/* Properly initialize pcb_save */
- pcb2->pcb_save = &pcb2->pcb_user_save;
+ pcb2->pcb_save = get_pcb_user_save_pcb(pcb2);
+ bcopy(get_pcb_user_save_td(td1), get_pcb_user_save_pcb(pcb2),
+ cpu_max_ext_state_size);
/* Point mdproc and then copy over td1's contents */
mdp2 = &p2->p_md;
@@ -310,11 +356,17 @@
void
cpu_thread_alloc(struct thread *td)
{
+ struct pcb *pcb;
+ struct xstate_hdr *xhdr;
- td->td_pcb = (struct pcb *)(td->td_kstack +
- td->td_kstack_pages * PAGE_SIZE) - 1;
- td->td_frame = (struct trapframe *)td->td_pcb - 1;
- td->td_pcb->pcb_save = &td->td_pcb->pcb_user_save;
+ td->td_pcb = pcb = get_pcb_td(td);
+ td->td_frame = (struct trapframe *)pcb - 1;
+ pcb->pcb_save = get_pcb_user_save_pcb(pcb);
+ if (use_xsave) {
+ xhdr = (struct xstate_hdr *)(pcb->pcb_save + 1);
+ bzero(xhdr, sizeof(*xhdr));
+ xhdr->xstate_bv = xsave_mask;
+ }
}
void
@@ -387,7 +439,9 @@
*/
bcopy(td0->td_pcb, pcb2, sizeof(*pcb2));
clear_pcb_flags(pcb2, PCB_FPUINITDONE | PCB_USERFPUINITDONE);
- pcb2->pcb_save = &pcb2->pcb_user_save;
+ pcb2->pcb_save = get_pcb_user_save_pcb(pcb2);
+ bcopy(get_pcb_user_save_td(td0), pcb2->pcb_save,
+ cpu_max_ext_state_size);
set_pcb_flags(pcb2, PCB_FULL_IRET);
/*
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/conf/GENERIC
--- a/head/sys/amd64/conf/GENERIC Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/conf/GENERIC Wed Feb 01 11:53:18 2012 +0200
@@ -16,7 +16,7 @@
# If you are in doubt as to the purpose or necessity of a line, check first
# in NOTES.
#
-# $FreeBSD: head/sys/amd64/conf/GENERIC 229997 2012-01-12 00:34:33Z ken $
+# $FreeBSD: head/sys/amd64/conf/GENERIC 230843 2012-01-31 19:38:18Z jimharris $
cpu HAMMER
ident GENERIC
@@ -123,6 +123,7 @@
device adw # Advansys wide SCSI adapters
device aic # Adaptec 15[012]x SCSI adapters, AIC-6[23]60.
device bt # Buslogic/Mylex MultiMaster SCSI adapters
+device isci # Intel C600 SAS controller
# ATA/SCSI peripherals
device scbus # SCSI bus (required for ATA/SCSI)
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/conf/NOTES
--- a/head/sys/amd64/conf/NOTES Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/conf/NOTES Wed Feb 01 11:53:18 2012 +0200
@@ -4,7 +4,7 @@
# This file contains machine dependent kernel configuration notes. For
# machine independent notes, look in /sys/conf/NOTES.
#
-# $FreeBSD: head/sys/amd64/conf/NOTES 228940 2011-12-28 23:26:58Z delphij $
+# $FreeBSD: head/sys/amd64/conf/NOTES 230843 2012-01-31 19:38:18Z jimharris $
#
#
@@ -409,6 +409,11 @@
device ips
#
+# Intel C600 (Patsburg) integrated SAS controller
+device isci
+options ISCI_LOGGING # enable debugging in isci HAL
+
+#
# SafeNet crypto driver: can be moved to the MI NOTES as soon as
# it's tested on a big-endian machine
#
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/ia32/ia32_reg.c
--- a/head/sys/amd64/ia32/ia32_reg.c Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/ia32/ia32_reg.c Wed Feb 01 11:53:18 2012 +0200
@@ -23,11 +23,11 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/amd64/ia32/ia32_reg.c 230426 2012-01-21 17:45:27Z kib $
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/amd64/ia32/ia32_reg.c 230426 2012-01-21 17:45:27Z kib $");
#include "opt_compat.h"
@@ -155,7 +155,7 @@
sv_87 = (struct save87 *)regs;
penv_87 = &sv_87->sv_env;
fpugetregs(td);
- sv_fpu = &td->td_pcb->pcb_user_save;
+ sv_fpu = get_pcb_user_save_td(td);
penv_xmm = &sv_fpu->sv_env;
/* FPU control/status */
@@ -187,7 +187,7 @@
{
struct save87 *sv_87 = (struct save87 *)regs;
struct env87 *penv_87 = &sv_87->sv_env;
- struct savefpu *sv_fpu = &td->td_pcb->pcb_user_save;
+ struct savefpu *sv_fpu = get_pcb_user_save_td(td);
struct envxmm *penv_xmm = &sv_fpu->sv_env;
int i;
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/ia32/ia32_signal.c
--- a/head/sys/amd64/ia32/ia32_signal.c Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/ia32/ia32_signal.c Wed Feb 01 11:53:18 2012 +0200
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD: head/sys/amd64/ia32/ia32_signal.c 220238 2011-04-01 11:16:29Z kib $");
+__FBSDID("$FreeBSD: head/sys/amd64/ia32/ia32_signal.c 230426 2012-01-21 17:45:27Z kib $");
#include "opt_compat.h"
@@ -71,6 +71,7 @@
#include <compat/freebsd32/freebsd32_signal.h>
#include <compat/freebsd32/freebsd32_util.h>
#include <compat/freebsd32/freebsd32_proto.h>
+#include <compat/freebsd32/freebsd32.h>
#include <compat/ia32/ia32_signal.h>
#include <machine/psl.h>
#include <machine/segments.h>
@@ -83,15 +84,15 @@
#ifdef COMPAT_FREEBSD4
static void freebsd4_ia32_sendsig(sig_t, ksiginfo_t *, sigset_t *);
#endif
-static void ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp);
-static int ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp);
#define CS_SECURE(cs) (ISPL(cs) == SEL_UPL)
#define EFL_SECURE(ef, oef) ((((ef) ^ (oef)) & ~PSL_USERCHANGE) == 0)
static void
-ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp)
+ia32_get_fpcontext(struct thread *td, struct ia32_mcontext *mcp,
+ char *xfpusave, size_t xfpusave_len)
{
+ size_t max_len, len;
/*
* XXX Format of 64bit and 32bit FXSAVE areas differs. FXSAVE
@@ -100,28 +101,43 @@
* for now, it should be irrelevant for most applications.
*/
mcp->mc_ownedfp = fpugetregs(td);
- bcopy(&td->td_pcb->pcb_user_save, &mcp->mc_fpstate,
+ bcopy(get_pcb_user_save_td(td), &mcp->mc_fpstate,
sizeof(mcp->mc_fpstate));
mcp->mc_fpformat = fpuformat();
+ if (!use_xsave || xfpusave_len == 0)
+ return;
+ max_len = cpu_max_ext_state_size - sizeof(struct savefpu);
+ len = xfpusave_len;
+ if (len > max_len) {
+ len = max_len;
+ bzero(xfpusave + max_len, len - max_len);
+ }
+ mcp->mc_flags |= _MC_HASFPXSTATE;
+ mcp->mc_xfpustate_len = len;
+ bcopy(get_pcb_user_save_td(td) + 1, xfpusave, len);
}
static int
-ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp)
+ia32_set_fpcontext(struct thread *td, const struct ia32_mcontext *mcp,
+ char *xfpustate, size_t xfpustate_len)
{
+ int error;
if (mcp->mc_fpformat == _MC_FPFMT_NODEV)
return (0);
else if (mcp->mc_fpformat != _MC_FPFMT_XMM)
return (EINVAL);
- else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE)
+ else if (mcp->mc_ownedfp == _MC_FPOWNED_NONE) {
/* We don't care what state is left in the FPU or PCB. */
fpstate_drop(td);
- else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
+ error = 0;
+ } else if (mcp->mc_ownedfp == _MC_FPOWNED_FPU ||
mcp->mc_ownedfp == _MC_FPOWNED_PCB) {
- fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate);
+ error = fpusetregs(td, (struct savefpu *)&mcp->mc_fpstate,
+ xfpustate, xfpustate_len);
} else
return (EINVAL);
- return (0);
+ return (error);
}
/*
@@ -164,10 +180,12 @@
mcp->mc_esp = tp->tf_rsp;
mcp->mc_ss = tp->tf_ss;
mcp->mc_len = sizeof(*mcp);
- ia32_get_fpcontext(td, mcp);
+ mcp->mc_flags = tp->tf_flags;
+ ia32_get_fpcontext(td, mcp, NULL, 0);
mcp->mc_fsbase = pcb->pcb_fsbase;
mcp->mc_gsbase = pcb->pcb_gsbase;
- bzero(mcp->mc_spare1, sizeof(mcp->mc_spare1));
+ mcp->mc_xfpustate = 0;
+ mcp->mc_xfpustate_len = 0;
bzero(mcp->mc_spare2, sizeof(mcp->mc_spare2));
set_pcb_flags(pcb, PCB_FULL_IRET);
return (0);
@@ -183,6 +201,7 @@
ia32_set_mcontext(struct thread *td, const struct ia32_mcontext *mcp)
{
struct trapframe *tp;
+ char *xfpustate;
long rflags;
int ret;
@@ -191,7 +210,18 @@
return (EINVAL);
rflags = (mcp->mc_eflags & PSL_USERCHANGE) |
(tp->tf_rflags & ~PSL_USERCHANGE);
- ret = ia32_set_fpcontext(td, mcp);
+ if (mcp->mc_flags & _MC_IA32_HASFPXSTATE) {
+ if (mcp->mc_xfpustate_len > cpu_max_ext_state_size -
+ sizeof(struct savefpu))
+ return (EINVAL);
+ xfpustate = __builtin_alloca(mcp->mc_xfpustate_len);
+ ret = copyin(PTRIN(mcp->mc_xfpustate), xfpustate,
+ mcp->mc_xfpustate_len);
+ if (ret != 0)
+ return (ret);
+ } else
+ xfpustate = NULL;
+ ret = ia32_set_fpcontext(td, mcp, xfpustate, mcp->mc_xfpustate_len);
if (ret != 0)
return (ret);
tp->tf_gs = mcp->mc_gs;
@@ -529,6 +559,8 @@
struct sigacts *psp;
char *sp;
struct trapframe *regs;
+ char *xfpusave;
+ size_t xfpusave_len;
int oonstack;
int sig;
@@ -554,6 +586,14 @@
regs = td->td_frame;
oonstack = sigonstack(regs->tf_rsp);
+ if (cpu_max_ext_state_size > sizeof(struct savefpu) && use_xsave) {
+ xfpusave_len = cpu_max_ext_state_size - sizeof(struct savefpu);
+ xfpusave = __builtin_alloca(xfpusave_len);
+ } else {
+ xfpusave_len = 0;
+ xfpusave = NULL;
+ }
+
/* Save user context. */
bzero(&sf, sizeof(sf));
sf.sf_uc.uc_sigmask = *mask;
@@ -582,7 +622,7 @@
sf.sf_uc.uc_mcontext.mc_fs = regs->tf_fs;
sf.sf_uc.uc_mcontext.mc_gs = regs->tf_gs;
sf.sf_uc.uc_mcontext.mc_len = sizeof(sf.sf_uc.uc_mcontext); /* magic */
- ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext);
+ ia32_get_fpcontext(td, &sf.sf_uc.uc_mcontext, xfpusave, xfpusave_len);
fpstate_drop(td);
sf.sf_uc.uc_mcontext.mc_fsbase = td->td_pcb->pcb_fsbase;
sf.sf_uc.uc_mcontext.mc_gsbase = td->td_pcb->pcb_gsbase;
@@ -590,11 +630,16 @@
/* Allocate space for the signal handler context. */
if ((td->td_pflags & TDP_ALTSTACK) != 0 && !oonstack &&
- SIGISMEMBER(psp->ps_sigonstack, sig)) {
- sp = td->td_sigstk.ss_sp +
- td->td_sigstk.ss_size - sizeof(sf);
- } else
- sp = (char *)regs->tf_rsp - sizeof(sf);
+ SIGISMEMBER(psp->ps_sigonstack, sig))
+ sp = td->td_sigstk.ss_sp + td->td_sigstk.ss_size;
+ else
+ sp = (char *)regs->tf_rsp;
+ if (xfpusave != NULL) {
+ sp -= xfpusave_len;
+ sp = (char *)((unsigned long)sp & ~0x3Ful);
+ sf.sf_uc.uc_mcontext.mc_xfpustate = (register_t)sp;
+ }
+ sp -= sizeof(sf);
/* Align to 16 bytes. */
sfp = (struct ia32_sigframe *)((uintptr_t)sp & ~0xF);
PROC_UNLOCK(p);
@@ -626,7 +671,10 @@
/*
* Copy the sigframe out to the user's stack.
*/
- if (copyout(&sf, sfp, sizeof(*sfp)) != 0) {
+ if (copyout(&sf, sfp, sizeof(*sfp)) != 0 ||
+ (xfpusave != NULL && copyout(xfpusave,
+ PTRIN(sf.sf_uc.uc_mcontext.mc_xfpustate), xfpusave_len)
+ != 0)) {
#ifdef DEBUG
printf("process %ld has trashed its stack\n", (long)p->p_pid);
#endif
@@ -812,6 +860,8 @@
struct ia32_ucontext uc;
struct trapframe *regs;
struct ia32_ucontext *ucp;
+ char *xfpustate;
+ size_t xfpustate_len;
int cs, eflags, error, ret;
ksiginfo_t ksi;
@@ -858,9 +908,34 @@
return (EINVAL);
}
- ret = ia32_set_fpcontext(td, &ucp->uc_mcontext);
- if (ret != 0)
+ if ((ucp->uc_mcontext.mc_flags & _MC_HASFPXSTATE) != 0) {
+ xfpustate_len = uc.uc_mcontext.mc_xfpustate_len;
+ if (xfpustate_len > cpu_max_ext_state_size -
+ sizeof(struct savefpu)) {
+ uprintf("pid %d (%s): sigreturn xfpusave_len = 0x%zx\n",
+ td->td_proc->p_pid, td->td_name, xfpustate_len);
+ return (EINVAL);
+ }
+ xfpustate = __builtin_alloca(xfpustate_len);
+ error = copyin(PTRIN(ucp->uc_mcontext.mc_xfpustate),
+ xfpustate, xfpustate_len);
+ if (error != 0) {
+ uprintf(
+ "pid %d (%s): sigreturn copying xfpustate failed\n",
+ td->td_proc->p_pid, td->td_name);
+ return (error);
+ }
+ } else {
+ xfpustate = NULL;
+ xfpustate_len = 0;
+ }
+ ret = ia32_set_fpcontext(td, &ucp->uc_mcontext, xfpustate,
+ xfpustate_len);
+ if (ret != 0) {
+ uprintf("pid %d (%s): sigreturn set_fpcontext err %d\n",
+ td->td_proc->p_pid, td->td_name, ret);
return (ret);
+ }
regs->tf_rdi = ucp->uc_mcontext.mc_edi;
regs->tf_rsi = ucp->uc_mcontext.mc_esi;
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/include/cpufunc.h
--- a/head/sys/amd64/include/cpufunc.h Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/include/cpufunc.h Wed Feb 01 11:53:18 2012 +0200
@@ -27,7 +27,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/amd64/include/cpufunc.h 223796 2011-07-05 18:42:10Z jkim $
+ * $FreeBSD: head/sys/amd64/include/cpufunc.h 230766 2012-01-30 07:53:33Z kib $
*/
/*
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/include/float.h
--- a/head/sys/amd64/include/float.h Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/include/float.h Wed Feb 01 11:53:18 2012 +0200
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* from: @(#)float.h 7.1 (Berkeley) 5/8/90
- * $FreeBSD$
+ * $FreeBSD: head/sys/amd64/include/float.h 230475 2012-01-23 06:36:41Z das $
*/
#ifndef _MACHINE_FLOAT_H_
@@ -55,6 +55,11 @@
#define FLT_MAX_EXP 128 /* emax */
#define FLT_MAX 3.40282347E+38F /* (1-b**(-p))*b**emax */
#define FLT_MAX_10_EXP 38 /* floor(log10((1-b**(-p))*b**emax)) */
+#if __ISO_C_VISIBLE >= 2011
+#define FLT_TRUE_MIN 1.40129846E-45F /* b**(emin-p) */
+#define FLT_DECIMAL_DIG 9 /* ceil(1+p*log10(b)) */
+#define FLT_HAS_SUBNORM 1
+#endif /* __ISO_C_VISIBLE >= 2011 */
#define DBL_MANT_DIG 53
#define DBL_EPSILON 2.2204460492503131E-16
@@ -65,6 +70,11 @@
#define DBL_MAX_EXP 1024
#define DBL_MAX 1.7976931348623157E+308
#define DBL_MAX_10_EXP 308
+#if __ISO_C_VISIBLE >= 2011
+#define DBL_TRUE_MIN 4.9406564584124654E-324
+#define DBL_DECIMAL_DIG 17
+#define DBL_HAS_SUBNORM 1
+#endif /* __ISO_C_VISIBLE >= 2011 */
#define LDBL_MANT_DIG 64
#define LDBL_EPSILON 1.0842021724855044340E-19L
@@ -75,4 +85,10 @@
#define LDBL_MAX_EXP 16384
#define LDBL_MAX 1.1897314953572317650E+4932L
#define LDBL_MAX_10_EXP 4932
+#if __ISO_C_VISIBLE >= 2011
+#define LDBL_TRUE_MIN 3.6451995318824746025E-4951L
+#define LDBL_DECIMAL_DIG 21
+#define LDBL_HAS_SUBNORM 1
+#endif /* __ISO_C_VISIBLE >= 2011 */
+
#endif /* _MACHINE_FLOAT_H_ */
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/include/fpu.h
--- a/head/sys/amd64/include/fpu.h Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/include/fpu.h Wed Feb 01 11:53:18 2012 +0200
@@ -30,7 +30,7 @@
* SUCH DAMAGE.
*
* from: @(#)npx.h 5.3 (Berkeley) 1/18/91
- * $FreeBSD$
+ * $FreeBSD: head/sys/amd64/include/fpu.h 230426 2012-01-21 17:45:27Z kib $
*/
/*
@@ -43,45 +43,71 @@
/* Contents of each x87 floating point accumulator */
struct fpacc87 {
- u_char fp_bytes[10];
+ uint8_t fp_bytes[10];
};
/* Contents of each SSE extended accumulator */
struct xmmacc {
- u_char xmm_bytes[16];
+ uint8_t xmm_bytes[16];
+};
+
+/* Contents of the upper 16 bytes of each AVX extended accumulator */
+struct ymmacc {
+ uint8_t ymm_bytes[16];
};
struct envxmm {
- u_int16_t en_cw; /* control word (16bits) */
- u_int16_t en_sw; /* status word (16bits) */
- u_int8_t en_tw; /* tag word (8bits) */
- u_int8_t en_zero;
- u_int16_t en_opcode; /* opcode last executed (11 bits ) */
- u_int64_t en_rip; /* floating point instruction pointer */
- u_int64_t en_rdp; /* floating operand pointer */
- u_int32_t en_mxcsr; /* SSE sontorol/status register */
- u_int32_t en_mxcsr_mask; /* valid bits in mxcsr */
+ uint16_t en_cw; /* control word (16bits) */
+ uint16_t en_sw; /* status word (16bits) */
+ uint8_t en_tw; /* tag word (8bits) */
+ uint8_t en_zero;
+ uint16_t en_opcode; /* opcode last executed (11 bits ) */
+ uint64_t en_rip; /* floating point instruction pointer */
+ uint64_t en_rdp; /* floating operand pointer */
+ uint32_t en_mxcsr; /* SSE sontorol/status register */
+ uint32_t en_mxcsr_mask; /* valid bits in mxcsr */
};
struct savefpu {
struct envxmm sv_env;
struct {
struct fpacc87 fp_acc;
- u_char fp_pad[6]; /* padding */
+ uint8_t fp_pad[6]; /* padding */
} sv_fp[8];
struct xmmacc sv_xmm[16];
- u_char sv_pad[96];
+ uint8_t sv_pad[96];
} __aligned(16);
+struct xstate_hdr {
+ uint64_t xstate_bv;
+ uint8_t xstate_rsrv0[16];
+ uint8_t xstate_rsrv[40];
+};
+
+struct savefpu_xstate {
+ struct xstate_hdr sx_hd;
+ struct ymmacc sx_ymm[16];
+};
+
+struct savefpu_ymm {
+ struct envxmm sv_env;
+ struct {
+ struct fpacc87 fp_acc;
+ int8_t fp_pad[6]; /* padding */
+ } sv_fp[8];
+ struct xmmacc sv_xmm[16];
+ uint8_t sv_pad[96];
+ struct savefpu_xstate sv_xstate;
+} __aligned(64);
+
#ifdef _KERNEL
-struct fpu_kern_ctx {
- struct savefpu hwstate;
- struct savefpu *prev;
- uint32_t flags;
-};
-#define FPU_KERN_CTX_FPUINITDONE 0x01
+
+struct fpu_kern_ctx;
#define PCB_USER_FPU(pcb) (((pcb)->pcb_flags & PCB_KERNFPU) == 0)
+
+#define XSAVE_AREA_ALIGN 64
+
#endif
/*
@@ -114,9 +140,15 @@
int fpuformat(void);
int fpugetregs(struct thread *td);
void fpuinit(void);
-void fpusetregs(struct thread *td, struct savefpu *addr);
+void fpusave(void *addr);
+int fpusetregs(struct thread *td, struct savefpu *addr,
+ char *xfpustate, size_t xfpustate_size);
+int fpusetxstate(struct thread *td, char *xfpustate,
+ size_t xfpustate_size);
int fputrap(void);
void fpuuserinited(struct thread *td);
+struct fpu_kern_ctx *fpu_kern_alloc_ctx(u_int flags);
+void fpu_kern_free_ctx(struct fpu_kern_ctx *ctx);
int fpu_kern_enter(struct thread *td, struct fpu_kern_ctx *ctx,
u_int flags);
int fpu_kern_leave(struct thread *td, struct fpu_kern_ctx *ctx);
@@ -124,9 +156,10 @@
int is_fpu_kern_thread(u_int flags);
/*
- * Flags for fpu_kern_enter() and fpu_kern_thread().
+ * Flags for fpu_kern_alloc_ctx(), fpu_kern_enter() and fpu_kern_thread().
*/
#define FPU_KERN_NORMAL 0x0000
+#define FPU_KERN_NOWAIT 0x0001
#endif
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/include/frame.h
--- a/head/sys/amd64/include/frame.h Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/include/frame.h Wed Feb 01 11:53:18 2012 +0200
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)frame.h 5.2 (Berkeley) 1/18/91
- * $FreeBSD$
+ * $FreeBSD: head/sys/amd64/include/frame.h 230426 2012-01-21 17:45:27Z kib $
*/
#ifndef _MACHINE_FRAME_H_
@@ -81,6 +81,7 @@
};
#define TF_HASSEGS 0x1
-/* #define _MC_HASBASES 0x2 */
+#define TF_HASBASES 0x2
+#define TF_HASFPXSTATE 0x4
#endif /* _MACHINE_FRAME_H_ */
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/include/md_var.h
--- a/head/sys/amd64/include/md_var.h Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/include/md_var.h Wed Feb 01 11:53:18 2012 +0200
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD: head/sys/amd64/include/md_var.h 225576 2011-09-15 09:54:07Z kib $
+ * $FreeBSD: head/sys/amd64/include/md_var.h 230426 2012-01-21 17:45:27Z kib $
*/
#ifndef _MACHINE_MD_VAR_H_
@@ -51,6 +51,7 @@
extern u_int cpu_fxsr;
extern u_int cpu_high;
extern u_int cpu_id;
+extern u_int cpu_max_ext_state_size;
extern u_int cpu_mxcsr_mask;
extern u_int cpu_procinfo;
extern u_int cpu_procinfo2;
@@ -67,17 +68,23 @@
extern int _ucode32sel;
extern int _ufssel;
extern int _ugssel;
+extern int use_xsave;
+extern uint64_t xsave_mask;
typedef void alias_for_inthand_t(u_int cs, u_int ef, u_int esp, u_int ss);
+struct pcb;
+struct savefpu;
struct thread;
struct reg;
struct fpreg;
struct dbreg;
struct dumperinfo;
+void *alloc_fpusave(int flags);
void amd64_syscall(struct thread *td, int traced);
void busdma_swi(void);
void cpu_setregs(void);
+void ctx_fpusave(void *);
void doreti_iret(void) __asm(__STRING(doreti_iret));
void doreti_iret_fault(void) __asm(__STRING(doreti_iret_fault));
void ld_ds(void) __asm(__STRING(ld_ds));
@@ -105,5 +112,8 @@
void setidt(int idx, alias_for_inthand_t *func, int typ, int dpl, int ist);
int user_dbreg_trap(void);
void minidumpsys(struct dumperinfo *);
+struct savefpu *get_pcb_user_save_td(struct thread *td);
+struct savefpu *get_pcb_user_save_pcb(struct pcb *pcb);
+struct pcb *get_pcb_td(struct thread *td);
#endif /* !_MACHINE_MD_VAR_H_ */
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/include/pcb.h
--- a/head/sys/amd64/include/pcb.h Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/include/pcb.h Wed Feb 01 11:53:18 2012 +0200
@@ -31,7 +31,7 @@
* SUCH DAMAGE.
*
* from: @(#)pcb.h 5.10 (Berkeley) 5/12/91
- * $FreeBSD$
+ * $FreeBSD: head/sys/amd64/include/pcb.h 230426 2012-01-21 17:45:27Z kib $
*/
#ifndef _AMD64_PCB_H_
@@ -92,7 +92,8 @@
struct amd64tss *pcb_tssp;
struct savefpu *pcb_save;
- struct savefpu pcb_user_save;
+
+ uint64_t pcb_pad[2];
};
#ifdef _KERNEL
@@ -130,6 +131,7 @@
void makectx(struct trapframe *, struct pcb *);
int savectx(struct pcb *);
+
#endif
#endif /* _AMD64_PCB_H_ */
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/include/pcpu.h
--- a/head/sys/amd64/include/pcpu.h Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/include/pcpu.h Wed Feb 01 11:53:18 2012 +0200
@@ -23,7 +23,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/amd64/include/pcpu.h 230260 2012-01-17 07:21:23Z kib $
*/
#ifndef _MACHINE_PCPU_H_
@@ -226,6 +226,8 @@
}
#define curthread (__curthread())
+#define IS_BSP() (PCPU_GET(cpuid) == 0)
+
#else /* !lint || defined(__GNUCLIKE_ASM) && defined(__GNUCLIKE___TYPEOF) */
#error "this file needs to be ported to your compiler"
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/include/ptrace.h
--- a/head/sys/amd64/include/ptrace.h Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/include/ptrace.h Wed Feb 01 11:53:18 2012 +0200
@@ -27,10 +27,15 @@
* SUCH DAMAGE.
*
* @(#)ptrace.h 8.1 (Berkeley) 6/11/93
- * $FreeBSD$
+ * $FreeBSD: head/sys/amd64/include/ptrace.h 230426 2012-01-21 17:45:27Z kib $
*/
#ifndef _MACHINE_PTRACE_H_
#define _MACHINE_PTRACE_H_
+#define __HAVE_PTRACE_MACHDEP
+
+#define PT_GETXSTATE (PT_FIRSTMACH + 0)
+#define PT_SETXSTATE (PT_FIRSTMACH + 1)
+
#endif
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/include/signal.h
--- a/head/sys/amd64/include/signal.h Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/include/signal.h Wed Feb 01 11:53:18 2012 +0200
@@ -28,7 +28,7 @@
* SUCH DAMAGE.
*
* @(#)signal.h 8.1 (Berkeley) 6/11/93
- * $FreeBSD: head/sys/amd64/include/signal.h 227399 2011-11-09 18:25:50Z kib $
+ * $FreeBSD: head/sys/amd64/include/signal.h 230765 2012-01-30 07:51:52Z kib $
*/
#ifndef _MACHINE_SIGNAL_H_
@@ -99,7 +99,10 @@
long sc_fsbase;
long sc_gsbase;
- long sc_spare[6];
+ long sc_xfpustate;
+ long sc_xfpustate_len;
+
+ long sc_spare[4];
};
#endif /* __BSD_VISIBLE */
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/include/specialreg.h
--- a/head/sys/amd64/include/specialreg.h Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/include/specialreg.h Wed Feb 01 11:53:18 2012 +0200
@@ -27,7 +27,7 @@
* SUCH DAMAGE.
*
* from: @(#)specialreg.h 7.1 (Berkeley) 5/9/91
- * $FreeBSD: head/sys/amd64/include/specialreg.h 222043 2011-05-17 22:36:16Z jkim $
+ * $FreeBSD: head/sys/amd64/include/specialreg.h 230261 2012-01-17 07:23:43Z kib $
*/
#ifndef _MACHINE_SPECIALREG_H_
@@ -66,6 +66,7 @@
#define CR4_PCE 0x00000100 /* Performance monitoring counter enable */
#define CR4_FXSR 0x00000200 /* Fast FPU save/restore used by OS */
#define CR4_XMM 0x00000400 /* enable SIMD/MMX2 to use except 16 */
+#define CR4_XSAVE 0x00040000 /* XSETBV/XGETBV */
/*
* Bits in AMD64 special registers. EFER is 64 bits wide.
@@ -76,6 +77,18 @@
#define EFER_NXE 0x000000800 /* PTE No-Execute bit enable (R/W) */
/*
+ * Intel Extended Features registers
+ */
+#define XCR0 0 /* XFEATURE_ENABLED_MASK register */
+
+#define XFEATURE_ENABLED_X87 0x00000001
+#define XFEATURE_ENABLED_SSE 0x00000002
+#define XFEATURE_ENABLED_AVX 0x00000004
+
+#define XFEATURE_AVX \
+ (XFEATURE_ENABLED_X87 | XFEATURE_ENABLED_SSE | XFEATURE_ENABLED_AVX)
+
+/*
* CPUID instruction features register
*/
#define CPUID_FPU 0x00000001
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/include/sysarch.h
--- a/head/sys/amd64/include/sysarch.h Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/include/sysarch.h Wed Feb 01 11:53:18 2012 +0200
@@ -26,7 +26,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $FreeBSD$
+ * $FreeBSD: head/sys/amd64/include/sysarch.h 230426 2012-01-21 17:45:27Z kib $
*/
/*
@@ -50,12 +50,14 @@
#define I386_SET_FSBASE 8
#define I386_GET_GSBASE 9
#define I386_SET_GSBASE 10
+#define I386_GET_XFPUSTATE 11
/* Leave space for 0-127 for to avoid translating syscalls */
#define AMD64_GET_FSBASE 128
#define AMD64_SET_FSBASE 129
#define AMD64_GET_GSBASE 130
#define AMD64_SET_GSBASE 131
+#define AMD64_GET_XFPUSTATE 132
struct i386_ldt_args {
unsigned int start;
@@ -69,6 +71,16 @@
int enable;
};
+struct i386_get_xfpustate {
+ unsigned int addr;
+ int len;
+};
+
+struct amd64_get_xfpustate {
+ void *addr;
+ int len;
+};
+
#ifndef _KERNEL
__BEGIN_DECLS
int amd64_get_fsbase(void **);
diff -r 0e49bd70bd10 -r 09f923a839c9 head/sys/amd64/include/ucontext.h
--- a/head/sys/amd64/include/ucontext.h Wed Feb 01 11:53:00 2012 +0200
+++ b/head/sys/amd64/include/ucontext.h Wed Feb 01 11:53:18 2012 +0200
@@ -26,7 +26,7 @@
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
- * $FreeBSD: head/sys/amd64/include/ucontext.h 227399 2011-11-09 18:25:50Z kib $
+ * $FreeBSD: head/sys/amd64/include/ucontext.h 230426 2012-01-21 17:45:27Z kib $
*/
#ifndef _MACHINE_UCONTEXT_H_
@@ -37,7 +37,8 @@
*/
#define _MC_HASSEGS 0x1
#define _MC_HASBASES 0x2
-#define _MC_FLAG_MASK (_MC_HASSEGS | _MC_HASBASES)
+#define _MC_HASFPXSTATE 0x4
+#define _MC_FLAG_MASK (_MC_HASSEGS | _MC_HASBASES | _MC_HASFPXSTATE)
typedef struct __mcontext {
/*
@@ -93,7 +94,10 @@
__register_t mc_fsbase;
__register_t mc_gsbase;
- long mc_spare[6];
+ __register_t mc_xfpustate;
+ __register_t mc_xfpustate_len;
+
+ long mc_spare[4];
} mcontext_t;
#endif /* !_MACHINE_UCONTEXT_H_ */
More information about the Zrouter-src-freebsd
mailing list