/* * xsave/xrstor support. * * Author: Suresh Siddha */ #include #include #include /* * 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); }