x86: Detection for RDFSBASE and friends
authorBarret Rhoden <brho@cs.berkeley.edu>
Thu, 8 Dec 2011 00:42:46 +0000 (16:42 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Thu, 15 Dec 2011 22:48:41 +0000 (14:48 -0800)
These are new extensions that we'll eventually use to deal with the TLS
vulnerabilities that we have on x86 from exposing the LDT.

To do the detection, we needed to pass through a second uint32, which
some of the cpuid leaves require.

kern/arch/i686/apic.c
kern/arch/i686/arch.h
kern/arch/i686/console.c
kern/arch/i686/cpuinfo.c
kern/arch/i686/pmap.c
kern/arch/i686/x86.h

index c220f17..5c4aa2b 100644 (file)
@@ -102,7 +102,7 @@ void set_core_timer(uint32_t usec, bool periodic)
 uint32_t lapic_get_default_id(void)
 {
        uint32_t ebx;
-       cpuid(1, 0, &ebx, 0, 0);
+       cpuid(0x1, 0x0, 0, &ebx, 0, 0);
        // p6 family only uses 4 bits here, and 0xf is reserved for the IOAPIC
        return (ebx & 0xFF000000) >> 24;
 }
index a864f97..335fca2 100644 (file)
@@ -79,7 +79,7 @@ static __inline uint64_t
 read_tsc_serialized(void)
 {
     uint64_t tsc;
-       cpuid(0, 0, 0, 0, 0);
+       cpuid(0x0, 0x0, 0, 0, 0, 0);
        tsc = read_tsc();
        return tsc;
 }
index 69db09b..a192a60 100644 (file)
@@ -408,7 +408,7 @@ kbd_proc_data(void)
 #ifdef __CONFIG_KB_CORE0_ONLY__
        /* Ghetto hack to avoid crashing brho's buggy nehalem. */
        uint32_t eax, ebx, ecx, edx, family, model, stepping;
-       cpuid(1, &eax, &ebx, &ecx, &edx);
+       cpuid(0x1, 0x0, &eax, &ebx, &ecx, &edx);
        family = ((eax & 0x0FF00000) >> 20) + ((eax & 0x00000F00) >> 8);
        model = ((eax & 0x000F0000) >> 12) + ((eax & 0x000000F0) >> 4);
        stepping = eax & 0x0000000F;
index abbaa56..d54bd19 100644 (file)
@@ -18,6 +18,7 @@
 #include <kdebug.h>
 #include <string.h>
 
+/* Check Intel's SDM 2a for Table 3-17 for the cpuid leaves */
 void print_cpuinfo(void)
 {
        uint32_t eax, ebx, ecx, edx;
@@ -37,9 +38,9 @@ void print_cpuinfo(void)
        vendor_id[12] = '\0';
        cprintf("Vendor ID: %s\n", vendor_id);
        cprintf("Largest Standard Function Number Supported: %d\n", eax);
-       cpuid(0x80000000, &eax, 0, 0, 0);
+       cpuid(0x80000000, 0x0, &eax, 0, 0, 0);
        cprintf("Largest Extended Function Number Supported: 0x%08x\n", eax);
-       cpuid(1, &eax, &ebx, &ecx, &edx);
+       cpuid(1, 0x0, &eax, &ebx, &ecx, &edx);
        family = ((eax & 0x0FF00000) >> 20) + ((eax & 0x00000F00) >> 8);
        model = ((eax & 0x000F0000) >> 12) + ((eax & 0x000000F0) >> 4);
        cprintf("Family: %d\n", family);
@@ -104,7 +105,7 @@ void print_cpuinfo(void)
        if ((edx & (1 << 25)) && (!(edx & (1 << 24))))
                panic("SSE support, but no FXSAVE!");
        printk("\n");
-       cpuid(0x80000008, &eax, &ebx, &ecx, &edx);
+       cpuid(0x80000008, 0x0, &eax, &ebx, &ecx, &edx);
        cprintf("Physical Address Bits: %d\n", eax & 0x000000FF);
        cprintf("Cores per Die: %d\n", (ecx & 0x000000FF) + 1);
     cprintf("This core's Default APIC ID: 0x%08x\n", lapic_get_default_id());
@@ -117,11 +118,17 @@ void print_cpuinfo(void)
                cprintf("I am the Boot Strap Processor\n");
        else
                cprintf("I am an Application Processor\n");
-       cpuid(0x80000007, &eax, &ebx, &ecx, &edx);
+       cpuid(0x80000007, 0x0, &eax, &ebx, &ecx, &edx);
        if (edx & 0x00000100)
                printk("Invariant TSC present\n");
        else
                printk("Invariant TSC not present\n");
+       cpuid(0x07, 0x0, &eax, &ebx, &ecx, &edx);
+       if (ebx & 0x00000001)
+               printk("FS/GS Base RD/W supported\n");
+       else
+               printk("FS/GS Base RD/W not supported\n");
+
 }
 
 void show_mapping(uintptr_t start, size_t size)
index ed80700..128d11b 100644 (file)
@@ -72,7 +72,7 @@ nvram_read(int r)
 bool enable_pse(void)
 {
        uint32_t edx, cr4;
-       cpuid(1, 0, 0, 0, &edx);
+       cpuid(0x1, 0x0, 0, 0, 0, &edx);
        if (edx & CPUID_PSE_SUPPORT) {
                cr4 = rcr4();
                cr4 |= CR4_PSE;
index da0c596..84f0c57 100644 (file)
@@ -61,7 +61,8 @@ static __inline void write_eflags(uint32_t eflags) __attribute__((always_inline)
 static __inline uint32_t read_ebp(void) __attribute__((always_inline));
 static __inline uint32_t read_eip(void) __attribute__((always_inline));
 static __inline uint32_t read_esp(void) __attribute__((always_inline));
-static __inline void cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp);
+static __inline void cpuid(uint32_t info1, uint32_t info2, uint32_t *eaxp,
+                           uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp);
 static __inline uint64_t read_msr(uint32_t reg) __attribute__((always_inline));
 static __inline void write_msr(uint32_t reg, uint64_t val) __attribute__((always_inline));
 static __inline uint32_t read_mmreg32(uint32_t reg) __attribute__((always_inline));
@@ -272,12 +273,14 @@ read_esp(void)
 }
 
 static __inline void
-cpuid(uint32_t info, uint32_t *eaxp, uint32_t *ebxp, uint32_t *ecxp, uint32_t *edxp)
+cpuid(uint32_t info1, uint32_t info2, uint32_t *eaxp, uint32_t *ebxp,
+      uint32_t *ecxp, uint32_t *edxp)
 {
        uint32_t eax, ebx, ecx, edx;
+       /* Can select with both eax (info1) and ecx (info2) */
        asm volatile("cpuid" 
                : "=a" (eax), "=b" (ebx), "=c" (ecx), "=d" (edx)
-               : "a" (info));
+               : "a" (info1), "c" (info2));
        if (eaxp)
                *eaxp = eax;
        if (ebxp)