mirror of
https://github.com/apache/nuttx.git
synced 2026-06-07 17:33:08 +08:00
arch/x86_64: add support for XSAVE/XRSTOR
Add support for XSAVE/XRSTOR to handle x86_64 procesor extended states. Support for these instructions is required to support AVX instruction set Signed-off-by: p-szafonimateusz <p-szafonimateusz@xiaomi.com>
This commit is contained in:
committed by
Xiang Xiao
parent
66516918ce
commit
2192d83200
@@ -114,6 +114,30 @@
|
||||
#define X86_CR4_XMMEXCPT 0x00000400
|
||||
#define X86_CR4_FGSBASE 0x00010000
|
||||
#define X86_CR4_PCIDE 0x00020000
|
||||
#define X86_CR4_OSXSAVE 0x00040000
|
||||
|
||||
/* XCR0 */
|
||||
|
||||
#define X86_XCR0_X87 (1 << 0)
|
||||
#define X86_XCR0_SSE (1 << 1)
|
||||
#define X86_XCR0_AVX (1 << 2)
|
||||
#define X86_XCR0_BNDREG (1 << 3)
|
||||
#define X86_XCR0_BNDCSR (1 << 4)
|
||||
#define X86_XCR0_OPMASK (1 << 5)
|
||||
#define X86_XCR0_HI256 (1 << 6)
|
||||
#define X86_XCR0_HI16 (1 << 7)
|
||||
#define X86_XCR0_PT (1 << 8)
|
||||
#define X86_XCR0_PKRU (1 << 9)
|
||||
#define X86_XCR0_PASID (1 << 10)
|
||||
#define X86_XCR0_CETU (1 << 11)
|
||||
#define X86_XCR0_CETS (1 << 12)
|
||||
#define X86_XCR0_HDC (1 << 13)
|
||||
#define X86_XCR0_UINTR (1 << 14)
|
||||
#define X86_XCR0_LBR (1 << 15)
|
||||
#define X86_XCR0_HWP (1 << 16)
|
||||
#define X86_XCR0_XTILECFG (1 << 17)
|
||||
#define X86_XCR0_XTILEDATA (1 << 18)
|
||||
#define X86_XCR0_APX (1 << 19)
|
||||
|
||||
/* PAGE TABLE ENTRY Definitions */
|
||||
|
||||
@@ -161,6 +185,7 @@
|
||||
# define X86_64_CPUID_07_AVX512CD (1 << 28)
|
||||
# define X86_64_CPUID_07_AVX512BW (1 << 30)
|
||||
# define X86_64_CPUID_07_AVX512VL (1 << 31)
|
||||
#define X86_64_CPUID_XSAVE 0x0d
|
||||
#define X86_64_CPUID_TSC 0x15
|
||||
|
||||
/* MSR Definitions */
|
||||
@@ -243,6 +268,7 @@
|
||||
#define MSR_X2APIC_TMICT 0x838
|
||||
#define MSR_X2APIC_TMCCT 0x839
|
||||
#define MSR_X2APIC_TDCR 0x83e
|
||||
#define MSR_IA32_XSS 0xda0
|
||||
|
||||
/* IOAPIC related Definitions */
|
||||
|
||||
@@ -281,6 +307,42 @@
|
||||
# define X86_RST_CNT_CPU_RST 0x04
|
||||
# define X86_RST_CNT_FULL_RST 0x08
|
||||
|
||||
/* XSAVE state component bitmap */
|
||||
|
||||
#define X86_XSAVE_X87 (1 << 0) /* Bit 0: X87 state */
|
||||
#define X86_XSAVE_SSE (1 << 1) /* Bit 1: SSE state (512 bytes) */
|
||||
#define X86_XSAVE_AVX (1 << 2) /* Bit 2: AVX state (256 bytes) */
|
||||
#define X86_XSAVE_MPX_BNDREGS (1 << 3) /* Bit 3: MPX BNDREGS (64 bytes) */
|
||||
#define X86_XSAVE_MPX_BNDCSR (1 << 4) /* Bit 4: MPX BNDCSR (16 bytes) */
|
||||
#define X86_XSAVE_AVX512_OPMASK (1 << 5) /* Bit 5: AVX-512 opmask (64 bytes) */
|
||||
#define X86_XSAVE_AVX512_HI256 (1 << 6) /* Bit 6: AVX-512 ZMM_Hi256 (512 bytes) */
|
||||
#define X86_XSAVE_AVX512_HI16 (1 << 7) /* Bit 7: AVX-512 Hi16_ZMM (1024 bytes) */
|
||||
#define X86_XSAVE_PT (1 << 8) /* Bit 8: PT (72 bytes) */
|
||||
#define X86_XSAVE_PKRU (1 << 9) /* Bit 9: PKRU (4 bytes) */
|
||||
#define X86_XSAVE_PASID (1 << 10) /* Bit 10: PASID state */
|
||||
#define X86_XSAVE_CET_U (1 << 11) /* Bit 11: CET_U state */
|
||||
#define X86_XSAVE_CET_S (1 << 12) /* Bit 12: CET_S state */
|
||||
#define X86_XSAVE_HDC (1 << 13) /* Bit 13: HDC */
|
||||
#define X86_XSAVE_UINTR (1 << 14) /* Bit 14: UINTR state */
|
||||
#define X86_XSAVE_LBR (1 << 15) /* Bit 15: LBR state */
|
||||
#define X86_XSAVE_HWP (1 << 16) /* Bit 16: HWP state */
|
||||
#define X86_XSAVE_AMX_TILECFG (1 << 17) /* Bit 17: AMX TILECFG state (64 bytes) */
|
||||
#define X86_XSAVE_AMX_TILEDATA (1 << 18) /* Bit 18: AMX TILEDATA state (8192 bytes) */
|
||||
|
||||
/* XSAVE area size */
|
||||
|
||||
#define XSAVE_LEGACY_SIZE (512) /* X87 + SSE */
|
||||
#define XSAVE_HEADER_SIZE (64) /* XSAVE header */
|
||||
#define XSAVE_AVX_SIZE (256)
|
||||
#define XSAVE_MXP_BNDREGS_SIZE (64)
|
||||
#define XSAVE_MXP_BNDCSR_SIZE (16)
|
||||
#define XSAVE_AVX512OPMASK_SIZE (64)
|
||||
#define XSAVE_AVX512HI256_SIZE (512)
|
||||
#define XSAVE_AVX512HI16_SIZE (1024)
|
||||
#define XSAVE_PT_SIZE (72)
|
||||
#define XSAVE_PKRU_SIZE (4)
|
||||
#define XSAVE_HDC_SIZE (8)
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
/****************************************************************************
|
||||
|
||||
@@ -34,10 +34,11 @@
|
||||
#ifndef __ASSEMBLY__
|
||||
# include <stdint.h>
|
||||
# include <stdbool.h>
|
||||
# include <arch/arch.h>
|
||||
# include <time.h>
|
||||
#endif
|
||||
|
||||
#include <arch/arch.h>
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
@@ -353,53 +354,120 @@
|
||||
* ISR/IRQ interrupt processing.
|
||||
*/
|
||||
|
||||
#define XCPTCONTEXT_XMM_AREA_SIZE 512
|
||||
#define XMMAREA_OFFSET (XCPTCONTEXT_XMM_AREA_SIZE / 8)
|
||||
#ifndef CONFIG_ARCH_X86_64_HAVE_XSAVE
|
||||
|
||||
/* Only legacy area if XSAVE not supported */
|
||||
|
||||
# define XCPTCONTEXT_XMM_AREA_SIZE 512
|
||||
#else
|
||||
|
||||
/* XSAVE state depneds on enabled features */
|
||||
|
||||
# ifdef CONFIG_ARCH_X86_64_AVX
|
||||
# define XSTATE_AVX_STATE X86_XSAVE_AVX
|
||||
# define XSTATE_AVX_SIZE XSAVE_AVX_SIZE
|
||||
# else
|
||||
# define XSTATE_AVX_STATE 0
|
||||
# define XSTATE_AVX_SIZE 0
|
||||
# endif
|
||||
|
||||
# ifdef CONFIG_ARCH_X86_64_AVX512
|
||||
# define XSTATE_AVX512_STATE (X86_XSAVE_AVX512_OPMASK | \
|
||||
X86_XSAVE_AVX512_HI256 | \
|
||||
X86_XSAVE_AVX512_HI16)
|
||||
# define XSTATE_AVX512_SIZE (XSAVE_MXP_BNDREGS_SIZE + \
|
||||
XSAVE_MXP_BNDCSR_SIZE + \
|
||||
XSAVE_AVX512OPMASK_SIZE + \
|
||||
XSAVE_AVX512HI256_SIZE + \
|
||||
XSAVE_AVX512HI16_SIZE)
|
||||
# else
|
||||
# define XSTATE_AVX512_STATE 0
|
||||
# define XSTATE_AVX512_SIZE 0
|
||||
# endif
|
||||
|
||||
/* State component bitmap */
|
||||
|
||||
# define XSAVE_STATE_COMPONENTS (X86_XSAVE_X87 | \
|
||||
X86_XSAVE_SSE | \
|
||||
XSTATE_AVX_STATE | \
|
||||
XSTATE_AVX512_STATE)
|
||||
|
||||
/* Area for XSAVE - standard area format */
|
||||
|
||||
# define XCPTCONTEXT_XMM_AREA_SIZE (XSAVE_LEGACY_SIZE + \
|
||||
XSAVE_HEADER_SIZE + \
|
||||
XSTATE_AVX_SIZE + \
|
||||
XSTATE_AVX512_SIZE)
|
||||
#endif
|
||||
|
||||
/* Align registers to 64-bytes */
|
||||
|
||||
#ifdef CONFIG_ARCH_X86_64_AVX512
|
||||
# define XMMAREA_REG_ALIGN (13)
|
||||
#else
|
||||
# define XMMAREA_REG_ALIGN (7)
|
||||
#endif
|
||||
|
||||
/* Register offset in XMMAREA */
|
||||
|
||||
#define XMMAREA_OFFSET (XCPTCONTEXT_XMM_AREA_SIZE / 8)
|
||||
#define XMMAREA_REG_OFFSET (XMMAREA_REG_ALIGN + XMMAREA_OFFSET)
|
||||
|
||||
/* Data segments */
|
||||
|
||||
#define REG_ALIGN (0 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */
|
||||
#define REG_FS (1 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */
|
||||
#define REG_GS (2 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */
|
||||
#define REG_ES (3 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */
|
||||
#define REG_DS (4 + XMMAREA_OFFSET) /* Data segment selector */
|
||||
#define REG_FS (0 + XMMAREA_REG_OFFSET) /* " " "" " " "" " " " " */
|
||||
#define REG_GS (1 + XMMAREA_REG_OFFSET) /* " " "" " " "" " " " " */
|
||||
#define REG_ES (2 + XMMAREA_REG_OFFSET) /* " " "" " " "" " " " " */
|
||||
#define REG_DS (3 + XMMAREA_REG_OFFSET) /* Data segment selector */
|
||||
|
||||
/* Remaining regs */
|
||||
|
||||
#define REG_RAX (5 + XMMAREA_OFFSET) /* " " "" " " */
|
||||
#define REG_RBX (6 + XMMAREA_OFFSET) /* " " "" " " */
|
||||
#define REG_RBP (7 + XMMAREA_OFFSET) /* " " "" " " */
|
||||
#define REG_R10 (8 + XMMAREA_OFFSET) /* " " "" " " */
|
||||
#define REG_R11 (9 + XMMAREA_OFFSET) /* " " "" " " */
|
||||
#define REG_R12 (10 + XMMAREA_OFFSET) /* " " "" " " */
|
||||
#define REG_R13 (11 + XMMAREA_OFFSET) /* " " "" " " */
|
||||
#define REG_R14 (12 + XMMAREA_OFFSET) /* " " "" " " */
|
||||
#define REG_R15 (13 + XMMAREA_OFFSET) /* " " "" " " */
|
||||
#define REG_RAX (4 + XMMAREA_REG_OFFSET) /* " " "" " " */
|
||||
#define REG_RBX (5 + XMMAREA_REG_OFFSET) /* " " "" " " */
|
||||
#define REG_RBP (6 + XMMAREA_REG_OFFSET) /* " " "" " " */
|
||||
#define REG_R10 (7 + XMMAREA_REG_OFFSET) /* " " "" " " */
|
||||
#define REG_R11 (8 + XMMAREA_REG_OFFSET) /* " " "" " " */
|
||||
#define REG_R12 (9 + XMMAREA_REG_OFFSET) /* " " "" " " */
|
||||
#define REG_R13 (10 + XMMAREA_REG_OFFSET) /* " " "" " " */
|
||||
#define REG_R14 (11 + XMMAREA_REG_OFFSET) /* " " "" " " */
|
||||
#define REG_R15 (12 + XMMAREA_REG_OFFSET) /* " " "" " " */
|
||||
|
||||
/* ABI calling convention */
|
||||
|
||||
#define REG_R9 (14 + XMMAREA_OFFSET) /* " " "" " " */
|
||||
#define REG_R8 (15 + XMMAREA_OFFSET) /* " " "" " " */
|
||||
#define REG_RCX (16 + XMMAREA_OFFSET) /* " " "" " " */
|
||||
#define REG_RDX (17 + XMMAREA_OFFSET) /* " " "" " " */
|
||||
#define REG_RSI (18 + XMMAREA_OFFSET) /* " " "" " " */
|
||||
#define REG_RDI (19 + XMMAREA_OFFSET) /* " " "" " " */
|
||||
#define REG_R9 (13 + XMMAREA_REG_OFFSET) /* " " "" " " */
|
||||
#define REG_R8 (14 + XMMAREA_REG_OFFSET) /* " " "" " " */
|
||||
#define REG_RCX (15 + XMMAREA_REG_OFFSET) /* " " "" " " */
|
||||
#define REG_RDX (16 + XMMAREA_REG_OFFSET) /* " " "" " " */
|
||||
#define REG_RSI (17 + XMMAREA_REG_OFFSET) /* " " "" " " */
|
||||
#define REG_RDI (18 + XMMAREA_REG_OFFSET) /* " " "" " " */
|
||||
|
||||
/* IRQ saved */
|
||||
|
||||
#define REG_ERRCODE (20 + XMMAREA_OFFSET) /* Error code */
|
||||
#define REG_RIP (21 + XMMAREA_OFFSET) /* Pushed by process on interrupt processing */
|
||||
#define REG_CS (22 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */
|
||||
#define REG_RFLAGS (23 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */
|
||||
#define REG_RSP (24 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */
|
||||
#define REG_SS (25 + XMMAREA_OFFSET) /* " " "" " " "" " " " " */
|
||||
#define REG_ERRCODE (19 + XMMAREA_REG_OFFSET) /* Error code */
|
||||
#define REG_RIP (20 + XMMAREA_REG_OFFSET) /* Pushed by process on interrupt processing */
|
||||
#define REG_CS (21 + XMMAREA_REG_OFFSET) /* " " "" " " "" " " " " */
|
||||
#define REG_RFLAGS (22 + XMMAREA_REG_OFFSET) /* " " "" " " "" " " " " */
|
||||
#define REG_RSP (23 + XMMAREA_REG_OFFSET) /* " " "" " " "" " " " " */
|
||||
#define REG_SS (24 + XMMAREA_REG_OFFSET) /* " " "" " " "" " " " " */
|
||||
|
||||
#define XMMAREA_REGS (25)
|
||||
|
||||
/* NOTE 2: This is not really state data. Rather, this is just a convenient
|
||||
* way to pass parameters from the interrupt handler to C code.
|
||||
*/
|
||||
|
||||
#define XCPTCONTEXT_REGS (26 + XCPTCONTEXT_XMM_AREA_SIZE / 8)
|
||||
#define XCPTCONTEXT_SIZE (8 * XCPTCONTEXT_REGS + XCPTCONTEXT_XMM_AREA_SIZE)
|
||||
#define XCPTCONTEXT_REGS (XMMAREA_REGS + XMMAREA_REG_ALIGN + \
|
||||
XCPTCONTEXT_XMM_AREA_SIZE / 8)
|
||||
|
||||
#define XCPTCONTEXT_SIZE (8 * XCPTCONTEXT_REGS)
|
||||
|
||||
/* Always align XCPTCONTEXT to 64-bytes to support XSAVE */
|
||||
|
||||
#define XCPTCONTEXT_ALIGN (64)
|
||||
|
||||
#define XCP_ALIGN_MASK (XCPTCONTEXT_ALIGN - 1)
|
||||
#define XCP_ALIGN_DOWN(a) ((a) & ~XCP_ALIGN_MASK)
|
||||
#define XCP_ALIGN_UP(a) (((a) + XCP_ALIGN_MASK) & ~XCP_ALIGN_MASK)
|
||||
|
||||
/****************************************************************************
|
||||
* Public Types
|
||||
@@ -432,9 +500,9 @@ struct xcptcontext
|
||||
uint64_t saved_rflags;
|
||||
uint64_t saved_rsp;
|
||||
|
||||
/* Register save area */
|
||||
/* Register save area - allocated from stack in up_initial_state() */
|
||||
|
||||
uint64_t regs[XCPTCONTEXT_REGS] aligned_data(16);
|
||||
uint64_t *regs;
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
@@ -28,6 +28,13 @@ config ARCH_X86_64_ACPI_BIOS
|
||||
|
||||
endif # ARCH_X86_64_ACPI
|
||||
|
||||
config ARCH_X86_64_HAVE_XSAVE
|
||||
bool "XSAVE support"
|
||||
default y
|
||||
---help---
|
||||
Select to enable the use of XSAVE and FPU/SSE/AVX functions
|
||||
of x86_64
|
||||
|
||||
config ARCH_X86_64_MMX
|
||||
bool "MMX support"
|
||||
depends on ARCH_HAVE_MMX
|
||||
|
||||
@@ -150,13 +150,6 @@ config INTEL64_ONESHOT_MAXTIMERS
|
||||
|
||||
endif
|
||||
|
||||
config ARCH_INTEL64_HAVE_XSAVE
|
||||
bool "XSAVE support"
|
||||
default y
|
||||
---help---
|
||||
Select to enable the use of XSAVE and FPU/SSE/AVX functions
|
||||
of x86_64
|
||||
|
||||
config ARCH_INTEL64_HAVE_PCID
|
||||
bool "PCID support"
|
||||
default y
|
||||
|
||||
@@ -108,10 +108,24 @@ void x86_64_check_and_enable_capability(void)
|
||||
goto err;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_ARCH_INTEL64_HAVE_XSAVE
|
||||
#if defined(CONFIG_ARCH_HAVE_SSE) || defined(CONFIG_ARCH_X86_64_AVX) || \
|
||||
defined(CONFIG_ARCH_X86_64_AVX512)
|
||||
__enable_sse_avx();
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_X86_64_HAVE_XSAVE
|
||||
/* Check XSAVE state area size for the current XCR0 state */
|
||||
|
||||
asm volatile("cpuid" : "=b" (ebx)
|
||||
: "a" (X86_64_CPUID_XSAVE), "c" (0)
|
||||
: "rdx", "memory");
|
||||
|
||||
if (XCPTCONTEXT_XMM_AREA_SIZE < ebx)
|
||||
{
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_ARCH_INTEL64_HAVE_PCID
|
||||
__enable_pcid();
|
||||
#endif
|
||||
|
||||
@@ -64,8 +64,8 @@ struct intel64_cpu_s g_cpu_priv[CONFIG_SMP_NCPUS];
|
||||
|
||||
/* Allocate stack for interrupts and isr */
|
||||
|
||||
uint8_t g_intstackalloc[IRQ_STACK_ALLOC] aligned_data(16);
|
||||
uint8_t g_isrstackalloc[IRQ_STACK_ALLOC] aligned_data(16);
|
||||
uint8_t g_intstackalloc[IRQ_STACK_ALLOC] aligned_data(64);
|
||||
uint8_t g_isrstackalloc[IRQ_STACK_ALLOC] aligned_data(64);
|
||||
|
||||
/****************************************************************************
|
||||
* Private Functions
|
||||
|
||||
@@ -53,6 +53,15 @@ x86_64_fullcontextrestore:
|
||||
|
||||
cli
|
||||
|
||||
#ifndef CONFIG_ARCH_X86_64_HAVE_XSAVE
|
||||
/* Restore xmm registers */
|
||||
fxrstorq (%rdi)
|
||||
#else
|
||||
movl $XSAVE_STATE_COMPONENTS, %eax
|
||||
xor %edx, %edx
|
||||
xrstor (%rdi)
|
||||
#endif
|
||||
|
||||
/* Create an interrupt stack frame for the final iret.
|
||||
*
|
||||
*
|
||||
@@ -115,9 +124,6 @@ x86_64_fullcontextrestore:
|
||||
* XXX: Should use wrgsbase and wrfsbase to restore the gs and fs register
|
||||
*/
|
||||
|
||||
/* restore xmm registers */
|
||||
fxrstorq (%rdi)
|
||||
|
||||
/* Restore the correct value of EAX and then return */
|
||||
|
||||
popq %rdi
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include <nuttx/config.h>
|
||||
#include <arch/arch.h>
|
||||
#include <arch/irq.h>
|
||||
#include <arch/multiboot2.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
@@ -33,6 +34,25 @@
|
||||
* Pre-processor definitions
|
||||
****************************************************************************/
|
||||
|
||||
/* Get XCR0 register value */
|
||||
|
||||
#if defined(CONFIG_ARCH_X86_64_AVX512)
|
||||
# define X86_XCR0_VAL (X86_XCR0_X87 | X86_XCR0_SSE | X86_XCR0_AVX | \
|
||||
X86_XCR0_OPMASK | X86_XCR0_HI256 | X86_XCR0_HI16)
|
||||
#elif defined(CONFIG_ARCH_X86_64_AVX)
|
||||
# define X86_XCR0_VAL (X86_XCR0_X87 | X86_XCR0_SSE | X86_XCR0_AVX)
|
||||
#else
|
||||
# define X86_XCR0_VAL (X86_XCR0_X87 | X86_XCR0_SSE)
|
||||
#endif
|
||||
|
||||
/* Get CR4 register value */
|
||||
|
||||
#ifdef CONFIG_ARCH_X86_64_HAVE_XSAVE
|
||||
# define X86_CR4_FPU_VAL (X86_CR4_OSXSAVE | X86_CR4_OSXFSR | X86_CR4_XMMEXCPT)
|
||||
#else
|
||||
# define X86_CR4_FPU_VAL (X86_CR4_OSXFSR | X86_CR4_XMMEXCPT)
|
||||
#endif
|
||||
|
||||
/* Memory Map: _sbss is the start of the BSS region (see ld.script) _ebss is
|
||||
* the end of the BSS region (see ld.script). The idle task stack starts at
|
||||
* the end of BSS and is of size CONFIG_IDLETHREAD_STACKSIZE. The IDLE thread
|
||||
@@ -319,6 +339,9 @@ start64:
|
||||
movabs $g_idle_topstack, %rbx
|
||||
mov (%rbx), %rsp
|
||||
|
||||
/* Allocate space XCPTCONTEXT */
|
||||
leaq -XCPTCONTEXT_SIZE(%rsp), %rsp
|
||||
|
||||
/* Set bsp_done flag */
|
||||
movl $1, bsp_done
|
||||
|
||||
@@ -352,7 +375,7 @@ ap_start:
|
||||
.size __pmode_entry, . - __pmode_entry
|
||||
|
||||
g_cpu_count:
|
||||
.long 1
|
||||
.long 1
|
||||
|
||||
/****************************************************************************
|
||||
* Name: __revoke_low_memory
|
||||
@@ -408,11 +431,21 @@ __enable_sse_avx:
|
||||
|
||||
/* Enable Saving XMM context */
|
||||
mov %cr4, %rax
|
||||
or $(X86_CR4_OSXFSR | X86_CR4_XMMEXCPT), %rax
|
||||
or $X86_CR4_FPU_VAL, %rax
|
||||
mov %rax, %cr4
|
||||
|
||||
#ifdef CONFIG_ARCH_X86_64_HAVE_XSAVE
|
||||
/* Configure XSAVE/XRSTOR for user state*/
|
||||
mov $X86_XCR0_VAL, %eax
|
||||
|
||||
xor %rdx, %rdx
|
||||
xor %rcx, %rcx
|
||||
xsetbv
|
||||
|
||||
#else
|
||||
/* Setup MXCSR, masking all SSE precision exception */
|
||||
ldmxcsr mxcsr_mem
|
||||
#endif
|
||||
|
||||
ret
|
||||
|
||||
|
||||
@@ -33,6 +33,14 @@
|
||||
#include "x86_64_internal.h"
|
||||
#include "sched/sched.h"
|
||||
|
||||
/****************************************************************************
|
||||
* Pre-processor Definitions
|
||||
****************************************************************************/
|
||||
|
||||
#if XCPTCONTEXT_SIZE % XCPTCONTEXT_ALIGN != 0
|
||||
# error XCPTCONTEXT_SIZE must be aligned to XCPTCONTEXT_ALIGN !
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
@@ -83,22 +91,39 @@ void up_initial_state(struct tcb_s *tcb)
|
||||
|
||||
memset(xcp, 0, sizeof(struct xcptcontext));
|
||||
|
||||
/* set the FCW to 1f80 */
|
||||
/* Allocate area for XCPTCONTEXT */
|
||||
|
||||
xcp->regs = (uint64_t *)XCP_ALIGN_DOWN((uintptr_t)tcb->stack_base_ptr +
|
||||
tcb->adj_stack_size -
|
||||
XCPTCONTEXT_SIZE);
|
||||
|
||||
/* Reset the xcp registers */
|
||||
|
||||
memset(xcp->regs, 0, XCPTCONTEXT_SIZE);
|
||||
|
||||
#ifndef CONFIG_ARCH_X86_64_HAVE_XSAVE
|
||||
/* Set the FCW to 1f80 */
|
||||
|
||||
xcp->regs[1] = (uint64_t)0x0000037f00000000;
|
||||
|
||||
/* set the MXCSR to 1f80 */
|
||||
/* Set the MXCSR to 1f80 */
|
||||
|
||||
xcp->regs[3] = (uint64_t)0x0000000000001f80;
|
||||
#else
|
||||
/* Initialize XSAVE region with a valid state */
|
||||
|
||||
asm volatile("xsave %0"
|
||||
: "=m" (*xcp->regs)
|
||||
: "a" (XSAVE_STATE_COMPONENTS), "d" (0)
|
||||
: "memory");
|
||||
#endif
|
||||
|
||||
/* Save the initial stack pointer... the value of the stackpointer before
|
||||
* the "interrupt occurs."
|
||||
*/
|
||||
|
||||
xcp->regs[REG_RSP] = (uint64_t)tcb->stack_base_ptr +
|
||||
tcb->adj_stack_size;
|
||||
xcp->regs[REG_RBP] = (uint64_t)tcb->stack_base_ptr +
|
||||
tcb->adj_stack_size;
|
||||
xcp->regs[REG_RSP] = (uint64_t)xcp->regs - 8;
|
||||
xcp->regs[REG_RBP] = (uint64_t)xcp->regs - 8;
|
||||
|
||||
/* Save the task entry point */
|
||||
|
||||
|
||||
@@ -68,8 +68,14 @@ up_saveusercontext:
|
||||
movq %r14, (8*REG_R14)(%rdi)
|
||||
movq %r15, (8*REG_R15)(%rdi)
|
||||
|
||||
/* save xmm registers */
|
||||
#ifndef CONFIG_ARCH_X86_64_HAVE_XSAVE
|
||||
/* Save xmm registers */
|
||||
fxsaveq (%rdi)
|
||||
#else
|
||||
movl $XSAVE_STATE_COMPONENTS, %eax
|
||||
xor %edx, %edx
|
||||
xsave (%rdi)
|
||||
#endif
|
||||
|
||||
/* Save the value of SP as will be at the time of the IRET that will
|
||||
* appear to be the return from this function.
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
void x86_64_sigdeliver(void)
|
||||
{
|
||||
struct tcb_s *rtcb = this_task();
|
||||
uint64_t regs_area[XCPTCONTEXT_REGS + 2];
|
||||
uint64_t regs_area[XCPTCONTEXT_REGS + 8];
|
||||
uint64_t *regs;
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
@@ -72,9 +72,9 @@ void x86_64_sigdeliver(void)
|
||||
rtcb, rtcb->xcp.sigdeliver, rtcb->sigpendactionq.head);
|
||||
DEBUGASSERT(rtcb->xcp.sigdeliver != NULL);
|
||||
|
||||
/* Align regs to 16 byte boundary for SSE instructions. */
|
||||
/* Align regs to 64 byte boundary for XSAVE */
|
||||
|
||||
regs = (uint64_t *)(((uint64_t)(regs_area) + 15) & (~(uint64_t)15));
|
||||
regs = (uint64_t *)(((uint64_t)(regs_area) + 63) & (~(uint64_t)63));
|
||||
|
||||
/* Save the real return state on the stack ASAP before any chance we went
|
||||
* sleeping and break the register profile. We entered this function with
|
||||
|
||||
@@ -729,12 +729,18 @@ isr_common:
|
||||
mov %fs, %ax /* Lower 16-bits of rax. */
|
||||
pushq %rax /* Save the data segment descriptor */
|
||||
|
||||
/* align to 16-bytes boundary */
|
||||
leaq -8(%rsp), %rsp
|
||||
/* Align to 64-bytes boundary */
|
||||
leaq -(XMMAREA_REG_ALIGN * 8)(%rsp), %rsp
|
||||
|
||||
/* save xmm registers */
|
||||
leaq -512(%rsp), %rsp
|
||||
/* Save xmm registers */
|
||||
leaq -XCPTCONTEXT_XMM_AREA_SIZE(%rsp), %rsp
|
||||
#ifndef CONFIG_ARCH_X86_64_HAVE_XSAVE
|
||||
fxsaveq (%rsp)
|
||||
#else
|
||||
movl $XSAVE_STATE_COMPONENTS, %eax
|
||||
xor %edx, %edx
|
||||
xsave (%rsp)
|
||||
#endif
|
||||
|
||||
/* The current value of the SP points to the beginning of the state save
|
||||
* structure. Save that in RDI as the input parameter to isr_handler.
|
||||
@@ -786,12 +792,18 @@ irq_common:
|
||||
mov %fs, %ax /* Lower 16-bits of rax. */
|
||||
pushq %rax /* Save the data segment descriptor */
|
||||
|
||||
/* align to 16-bytes boundary */
|
||||
leaq -8(%rsp), %rsp
|
||||
/* Align to 64-bytes boundary */
|
||||
leaq -(XMMAREA_REG_ALIGN * 8)(%rsp), %rsp
|
||||
|
||||
/* save xmm registers */
|
||||
leaq -512(%rsp), %rsp
|
||||
/* Save xmm registers */
|
||||
leaq -XCPTCONTEXT_XMM_AREA_SIZE(%rsp), %rsp
|
||||
#ifndef CONFIG_ARCH_X86_64_HAVE_XSAVE
|
||||
fxsaveq (%rsp)
|
||||
#else
|
||||
movl $XSAVE_STATE_COMPONENTS, %eax
|
||||
xor %edx, %edx
|
||||
xsave (%rsp)
|
||||
#endif
|
||||
|
||||
/* The current value of the SP points to the beginning of the state save
|
||||
* structure. Save that in RDI as the input parameter to irq_handler.
|
||||
@@ -811,20 +823,28 @@ irq_common:
|
||||
je .Lnoswitch
|
||||
|
||||
/* A context swith will be performed. EAX holds the address of the new
|
||||
* register save structure.
|
||||
* register save structure.
|
||||
*
|
||||
* Jump to x86_64_fullcontextrestore(). We perform a call here, but that function
|
||||
* never returns. The address of the new register save block is the argument
|
||||
* to the x86_64_fullcontextrestore().
|
||||
*/
|
||||
*/
|
||||
|
||||
mov %rax, %rdi
|
||||
call x86_64_fullcontextrestore
|
||||
|
||||
.Lnoswitch:
|
||||
#ifndef CONFIG_ARCH_X86_64_HAVE_XSAVE
|
||||
fxrstorq (%rsp)
|
||||
leaq 512(%rsp), %rsp
|
||||
leaq 8(%rsp), %rsp
|
||||
#else
|
||||
movl $XSAVE_STATE_COMPONENTS, %eax
|
||||
xor %edx, %edx
|
||||
xrstor (%rsp)
|
||||
#endif
|
||||
leaq XCPTCONTEXT_XMM_AREA_SIZE(%rsp), %rsp
|
||||
|
||||
/* Align to 64-bytes boundary */
|
||||
leaq (XMMAREA_REG_ALIGN * 8)(%rsp), %rsp
|
||||
|
||||
popq %rax
|
||||
mov %fs, %ax
|
||||
|
||||
+8
-1
@@ -79,11 +79,18 @@
|
||||
# define DUMP_FORMAT " %016" PRIxPTR ""
|
||||
#endif
|
||||
|
||||
/* Architecture can overwrite the default XCPTCONTEXT alignment */
|
||||
|
||||
#ifndef XCPTCONTEXT_ALIGN
|
||||
# define XCPTCONTEXT_ALIGN 16
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Private Data
|
||||
****************************************************************************/
|
||||
|
||||
static uintptr_t g_last_regs[XCPTCONTEXT_REGS] aligned_data(16);
|
||||
static uintptr_t
|
||||
g_last_regs[XCPTCONTEXT_REGS] aligned_data(XCPTCONTEXT_ALIGN);
|
||||
static FAR const char *g_policy[4] =
|
||||
{
|
||||
"FIFO", "RR", "SPORADIC"
|
||||
|
||||
Reference in New Issue
Block a user