]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
x86, xsave: enable xsave/xrstor on cpus with xsave support
authorSuresh Siddha <suresh.b.siddha@intel.com>
Tue, 29 Jul 2008 17:29:19 +0000 (10:29 -0700)
committerIngo Molnar <mingo@elte.hu>
Wed, 30 Jul 2008 17:49:24 +0000 (19:49 +0200)
Enables xsave/xrstor by turning on cr4.osxsave on cpu's which have
the xsave support. For now, features that OS supports/enabled are
FP and SSE.

Signed-off-by: Suresh Siddha <suresh.b.siddha@intel.com>
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/kernel/Makefile
arch/x86/kernel/cpu/common.c
arch/x86/kernel/i387.c
arch/x86/kernel/traps_32.c
arch/x86/kernel/traps_64.c
arch/x86/kernel/xsave.c [new file with mode: 0644]
include/asm-x86/i387.h
include/asm-x86/processor-flags.h
include/asm-x86/processor.h
include/asm-x86/xsave.h [new file with mode: 0644]

index a07ec14f33122c5531586d15a7e48251f31f9464..d6ea91abaebc1f7db7ffb9afe7d4ffd83fa44a40 100644 (file)
@@ -38,7 +38,7 @@ obj-y                 += tsc.o io_delay.o rtc.o
 
 obj-$(CONFIG_X86_TRAMPOLINE)   += trampoline.o
 obj-y                          += process.o
-obj-y                          += i387.o
+obj-y                          += i387.o xsave.o
 obj-y                          += ptrace.o
 obj-y                          += ds.o
 obj-$(CONFIG_X86_32)           += tls.o
index 80ab20d4fa39913ce2a7b4ea5676883bb6f9d96f..fabbcb7020fb6fa9b10c02ba39e68a0dcb649eb4 100644 (file)
@@ -712,6 +712,14 @@ void __cpuinit cpu_init(void)
        current_thread_info()->status = 0;
        clear_used_math();
        mxcsr_feature_mask_init();
+
+       /*
+        * Boot processor to setup the FP and extended state context info.
+        */
+       if (!smp_processor_id())
+               init_thread_xstate();
+
+       xsave_init();
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
index eb9ddd8efb828175e7be0efcc0616257c67c5943..e22a9a9dce8a81a95e99c502be9d92c2a3af3e77 100644 (file)
@@ -61,6 +61,11 @@ void __init init_thread_xstate(void)
                return;
        }
 
+       if (cpu_has_xsave) {
+               xsave_cntxt_init();
+               return;
+       }
+
        if (cpu_has_fxsr)
                xstate_size = sizeof(struct i387_fxsave_struct);
 #ifdef CONFIG_X86_32
@@ -83,6 +88,13 @@ void __cpuinit fpu_init(void)
 
        write_cr0(oldcr0 & ~(X86_CR0_TS|X86_CR0_EM)); /* clear TS and EM */
 
+       /*
+        * Boot processor to setup the FP and extended state context info.
+        */
+       if (!smp_processor_id())
+               init_thread_xstate();
+       xsave_init();
+
        mxcsr_feature_mask_init();
        /* clean state in init */
        current_thread_info()->status = 0;
index 03df8e45e5a1562e6d63f149a6189eb7964e7335..da5a5964fccb23f1fbdb6ef2d3b82d110973aaed 100644 (file)
@@ -1228,7 +1228,6 @@ void __init trap_init(void)
 
        set_bit(SYSCALL_VECTOR, used_vectors);
 
-       init_thread_xstate();
        /*
         * Should be a barrier for any external CPU state:
         */
index 513caaca7115eecf5d7a58de7cf12fbe9e60e6e4..3580a7938a2e8e7474e61dcc92769f1013dc4f7d 100644 (file)
@@ -1172,10 +1172,6 @@ void __init trap_init(void)
 #ifdef CONFIG_IA32_EMULATION
        set_system_gate(IA32_SYSCALL_VECTOR, ia32_syscall);
 #endif
-       /*
-        * initialize the per thread extended state:
-        */
-       init_thread_xstate();
        /*
         * Should be a barrier for any external CPU state:
         */
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c
new file mode 100644 (file)
index 0000000..c68b7c4
--- /dev/null
@@ -0,0 +1,87 @@
+/*
+ * xsave/xrstor support.
+ *
+ * Author: Suresh Siddha <suresh.b.siddha@intel.com>
+ */
+#include <linux/bootmem.h>
+#include <linux/compat.h>
+#include <asm/i387.h>
+
+/*
+ * Supported feature mask by the CPU and the kernel.
+ */
+unsigned int pcntxt_hmask, pcntxt_lmask;
+
+/*
+ * Represents init state for the supported extended state.
+ */
+struct xsave_struct *init_xstate_buf;
+
+/*
+ * Enable the extended processor state save/restore feature
+ */
+void __cpuinit xsave_init(void)
+{
+       if (!cpu_has_xsave)
+               return;
+
+       set_in_cr4(X86_CR4_OSXSAVE);
+
+       /*
+        * Enable all the features that the HW is capable of
+        * and the Linux kernel is aware of.
+        *
+        * xsetbv();
+        */
+       asm volatile(".byte 0x0f,0x01,0xd1" : : "c" (0),
+                    "a" (pcntxt_lmask), "d" (pcntxt_hmask));
+}
+
+/*
+ * setup the xstate image representing the init state
+ */
+void setup_xstate_init(void)
+{
+       init_xstate_buf = alloc_bootmem(xstate_size);
+       init_xstate_buf->i387.mxcsr = MXCSR_DEFAULT;
+}
+
+/*
+ * Enable and initialize the xsave feature.
+ */
+void __init xsave_cntxt_init(void)
+{
+       unsigned int eax, ebx, ecx, edx;
+
+       cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx);
+
+       pcntxt_lmask = eax;
+       pcntxt_hmask = edx;
+
+       if ((pcntxt_lmask & XSTATE_FPSSE) != XSTATE_FPSSE) {
+               printk(KERN_ERR "FP/SSE not shown under xsave features %x\n",
+                      pcntxt_lmask);
+               BUG();
+       }
+
+       /*
+        * for now OS knows only about FP/SSE
+        */
+       pcntxt_lmask = pcntxt_lmask & XCNTXT_LMASK;
+       pcntxt_hmask = pcntxt_hmask & XCNTXT_HMASK;
+
+       xsave_init();
+
+       /*
+        * Recompute the context size for enabled features
+        */
+       cpuid_count(0xd, 0, &eax, &ebx, &ecx, &edx);
+
+       xstate_size = ebx;
+
+       setup_xstate_init();
+
+       printk(KERN_INFO "xsave/xrstor: enabled xstate_bv 0x%Lx, "
+              "cntxt size 0x%x\n",
+              (pcntxt_lmask | ((u64) pcntxt_hmask << 32)), xstate_size);
+}
index 3958de6aad0ee506bcfa9aead6e8e52cf58e1646..6a664789667038499245b1eebce089a7402a5532 100644 (file)
@@ -18,6 +18,7 @@
 #include <asm/sigcontext.h>
 #include <asm/user.h>
 #include <asm/uaccess.h>
+#include <asm/xsave.h>
 
 extern void fpu_init(void);
 extern void mxcsr_feature_mask_init(void);
index 5dd79774f693c176d66e8e2d5ef7639d85569c25..dc5f0712f9fa450430718880447c23f6af4c9965 100644 (file)
@@ -59,6 +59,7 @@
 #define X86_CR4_OSFXSR 0x00000200 /* enable fast FPU save and restore */
 #define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */
 #define X86_CR4_VMXE   0x00002000 /* enable VMX virtualization */
+#define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */
 
 /*
  * x86-64 Task Priority Register, CR8
index d60b4d81febefdbc632088f00adebffbfcd5f5f4..d7c0221c02780c24e723d81c302605c8c28214d0 100644 (file)
@@ -346,6 +346,18 @@ struct i387_soft_struct {
        u32                     entry_eip;
 };
 
+struct xsave_hdr_struct {
+       u64 xstate_bv;
+       u64 reserved1[2];
+       u64 reserved2[5];
+} __attribute__((packed));
+
+struct xsave_struct {
+       struct i387_fxsave_struct i387;
+       struct xsave_hdr_struct xsave_hdr;
+       /* new processor state extensions will go here */
+} __attribute__ ((packed, aligned (64)));
+
 union thread_xstate {
        struct i387_fsave_struct        fsave;
        struct i387_fxsave_struct       fxsave;
diff --git a/include/asm-x86/xsave.h b/include/asm-x86/xsave.h
new file mode 100644 (file)
index 0000000..6d70e62
--- /dev/null
@@ -0,0 +1,26 @@
+#ifndef __ASM_X86_XSAVE_H
+#define __ASM_X86_XSAVE_H
+
+#include <asm/processor.h>
+#include <asm/i387.h>
+
+#define XSTATE_FP      0x1
+#define XSTATE_SSE     0x2
+
+#define XSTATE_FPSSE   (XSTATE_FP | XSTATE_SSE)
+
+#define FXSAVE_SIZE    512
+
+/*
+ * These are the features that the OS can handle currently.
+ */
+#define XCNTXT_LMASK   (XSTATE_FP | XSTATE_SSE)
+#define XCNTXT_HMASK   0x0
+
+extern unsigned int xstate_size, pcntxt_hmask, pcntxt_lmask;
+extern struct xsave_struct *init_xstate_buf;
+
+extern void xsave_cntxt_init(void);
+extern void xsave_init(void);
+
+#endif