x86: Remove the POLL_CONSOLE hack
[akaros.git] / kern / arch / x86 / trap.h
index c842e24..ab28349 100644 (file)
 #include <arch/pci.h>
 #include <arch/pic.h>
 #include <arch/topology.h>
+#include <cpu_feat.h>
 #include <arch/io.h>
 #include <stdio.h>
 
@@ -158,36 +159,114 @@ extern void sysenter_handler(void);
 
 /* Defined and set up in in arch/init.c, used for XMM initialization */
 extern struct ancillary_state x86_default_fpu;
-extern uint64_t x86_default_xcr0;
 
 static inline void save_fp_state(struct ancillary_state *silly)
 {
+       uint64_t x86_default_xcr0 = __proc_global_info.x86_default_xcr0;
        uint32_t eax, edx;
 
-       edx = x86_default_xcr0 >> 32;
-       eax = x86_default_xcr0;
-       asm volatile("xsaveopt64 %0" : : "m"(*silly), "a"(eax), "d"(edx));
+       /* PLEASE NOTE:
+        * AMD CPUs ignore the FOP/FIP/FDP fields when there is
+        * no pending exception. When you are on AMD, we zero these fields in the
+        * ancillary_state argument before saving. This way, if you are on AMD and
+        * re-using an ancillary_state memory region, an old save's information
+        * won't leak into your new data. The side-effect of this is that you can't
+        * trust these fields to report accurate information on AMD unless an
+        * exception was pending. Granted, AMD says that only exception handlers
+        * should care about FOP/FIP/FDP, so that's probably okay.
+        *
+        * You should also note that on newer Intel 64 processors, while the value
+        * of the FOP is always saved and restored, it contains the opcode of the
+        * most recent x87 FPU instruction that triggered an unmasked exception,
+        * rather than simply the most recent opcode. Some older Xeons and P4s had
+        * the fopcode compatibility mode feature, which you could use to make the
+        * FOP update on every x87 non-control instruction, but that has been
+        * eliminated in newer hardware.
+        *
+        */
+       if (cpu_has_feat(CPU_FEAT_X86_VENDOR_AMD)) {
+               silly->fp_head_64d.fop      = 0x0;
+               silly->fp_head_64d.fpu_ip   = 0x0;
+               silly->fp_head_64d.cs       = 0x0;
+               silly->fp_head_64d.padding1 = 0x0; // padding1 is FIP or rsvd, proc dep.
+               silly->fp_head_64d.fpu_dp   = 0x0;
+               silly->fp_head_64d.ds       = 0x0;
+               silly->fp_head_64d.padding2 = 0x0; // padding2 is FDP or rsvd, proc dep.
+       }
+
+
+       if (cpu_has_feat(CPU_FEAT_X86_XSAVEOPT)) {
+               edx = x86_default_xcr0 >> 32;
+               eax = x86_default_xcr0;
+               asm volatile("xsaveopt64 %0" : : "m"(*silly), "a"(eax), "d"(edx));
+       } else if (cpu_has_feat(CPU_FEAT_X86_XSAVE)) {
+               edx = x86_default_xcr0 >> 32;
+               eax = x86_default_xcr0;
+               asm volatile("xsave64 %0" : : "m"(*silly), "a"(eax), "d"(edx));
+       } else {
+               asm volatile("fxsave64 %0" : : "m"(*silly));
+       }
 }
 
 static inline void init_fp_state(void);
 static inline void restore_fp_state(struct ancillary_state *silly)
 {
+       uint64_t x86_default_xcr0 = __proc_global_info.x86_default_xcr0;
        int err = 0;
        uint32_t eax, edx;
 
-       edx = x86_default_xcr0 >> 32;
-       eax = x86_default_xcr0;
-       asm volatile(ASM_STAC               ";"
-                        "1: xrstor64 %1         ;"
-                    "2: " ASM_CLAC "        ;"
-                    ".section .fixup, \"ax\";"
-                    "3: mov %4, %0          ;"
-                    "   jmp 2b              ;"
-                    ".previous              ;"
-                    _ASM_EXTABLE(1b, 3b)
-                    : "=r" (err)
-                    : "m"(*silly), "a"(eax), "d"(edx),
-                      "i" (-EINVAL), "0" (err));
+       /*
+        * Since AMD CPUs ignore the FOP/FIP/FDP fields when there is
+        * no pending exception, we clear those fields before restoring
+        * when we are both on AMD and there is no pending exception in
+        * the ancillary_state argument to restore_fp_state.
+        * If there is a pending exception in the ancillary_state,
+        * these fields will be written to the FPU upon executing
+        * a restore instruction, and there is nothing to worry about.
+        *
+        * See CVE-2006-1056 and CVE-2013-2076 on cve.mitre.org.
+        *
+        * We check for a pending exception by checking FSW.ES (bit 7)
+        *
+        * FNINIT clears FIP and FDP and, even though it is technically a
+        * control instruction, it clears FOP because it is initializing the FPU.
+        *
+        * NOTE: This might not be the most efficient way to do things, and
+        *       could be an optimization target for context switch performance
+        *       on AMD processors in the future.
+        */
+       if (!(silly->fp_head_64d.fsw & 0x80)
+               && cpu_has_feat(CPU_FEAT_X86_VENDOR_AMD))
+               asm volatile ("fninit;");
+
+       if (cpu_has_feat(CPU_FEAT_X86_XSAVE)) {
+               edx = x86_default_xcr0 >> 32;
+               eax = x86_default_xcr0;
+               asm volatile(ASM_STAC               ";"
+                            "1: xrstor64 %1         ;"
+                            "2: " ASM_CLAC "        ;"
+                            ".section .fixup, \"ax\";"
+                            "3: mov %4, %0          ;"
+                            "   jmp 2b              ;"
+                            ".previous              ;"
+                            _ASM_EXTABLE(1b, 3b)
+                            : "=r" (err)
+                            : "m"(*silly), "a"(eax), "d"(edx),
+                              "i" (-EINVAL), "0" (err));
+       } else {
+               asm volatile(ASM_STAC               ";"
+                            "1: fxrstor64 %1         ;"
+                            "2: " ASM_CLAC "        ;"
+                            ".section .fixup, \"ax\";"
+                            "3: mov %2, %0          ;"
+                            "   jmp 2b              ;"
+                            ".previous              ;"
+                            _ASM_EXTABLE(1b, 3b)
+                            : "=r" (err)
+                            : "m"(*silly),
+                              "i" (-EINVAL), "0" (err));
+       }
+
 
        if (err) {
                printk("Error restoring fp state!");