Add flags that VMs need. But many other things do as well.
[akaros.git] / kern / arch / x86 / cpuinfo.c
index e110bf9..6aafd3f 100644 (file)
@@ -25,7 +25,9 @@ void print_cpuinfo(void)
        uint32_t model, family;
        uint64_t msr_val;
        char vendor_id[13];
+       int max_std_lvl, max_extd_lvl;
        extern char (SNT RO _start)[];
+       bool is_intel;
 
        if (sizeof(long) == 8)
                printk("64 bit Kernel Booting...\n");
@@ -41,9 +43,20 @@ void print_cpuinfo(void)
 
        vendor_id[12] = '\0';
        cprintf("Vendor ID: %s\n", vendor_id);
+       /* not a great check - old intel P5s have no vendor id */
+       is_intel = !strcmp(vendor_id, "GenuineIntel");
+       /* intel supports a way to hide the upper leaves of cpuid, beyond 3.  the
+        * bios might have done this, so we'll make sure it is off. */
+       if (is_intel) {
+               msr_val = read_msr(IA32_MISC_ENABLE);
+               if (msr_val & (1 << 22))
+                       write_msr(IA32_MISC_ENABLE, msr_val & ~(1 << 22));
+       }
        cprintf("Largest Standard Function Number Supported: %d\n", eax);
+       max_std_lvl = eax;
        cpuid(0x80000000, 0x0, &eax, 0, 0, 0);
        cprintf("Largest Extended Function Number Supported: 0x%08x\n", eax);
+       max_extd_lvl = eax;
        cpuid(1, 0x0, &eax, &ebx, &ecx, &edx);
        family = ((eax & 0x0FF00000) >> 20) + ((eax & 0x00000F00) >> 8);
        model = ((eax & 0x000F0000) >> 12) + ((eax & 0x000000F0) >> 4);
@@ -74,7 +87,8 @@ void print_cpuinfo(void)
                cprintf("x2APIC Detected\n");
        else
                cprintf("x2APIC Not Detected\n");
-       if (ecx & 0x00000060) {
+       /* Not sure how to detect AMD HW virt yet. */
+       if ((ecx & 0x00000060) && is_intel) {
                msr_val = read_msr(IA32_FEATURE_CONTROL);
                printd("64 Bit Feature Control: 0x%08x\n", msr_val);
                if ((msr_val & 0x5) == 0x5)
@@ -82,7 +96,7 @@ void print_cpuinfo(void)
                else
                        printk("Hardware virtualization not supported\n");
        } else { 
-               printk("Hardware virtualization not supported\n");
+               printk("Hardware virtualization not detected.  (AMD?)\n");
        }
        /* FP and SSE Checks */
        if (edx & 0x00000001)
@@ -120,20 +134,43 @@ void print_cpuinfo(void)
        else
                printk("Invariant TSC not present\n");
        cpuid(0x07, 0x0, &eax, &ebx, &ecx, &edx);
-       if (ebx & 0x00000001)
+       if (ebx & 0x00000001) {
                printk("FS/GS Base RD/W supported\n");
-       else
+               /* Untested, since we don't have a machine that supports this.  Email us
+                * if this fails. */
+               printk("Attempting to enable WRFSBASE...\n");
+               lcr4(rcr4() | (1 << 16));
+       } else {
                printk("FS/GS Base RD/W not supported\n");
+               #ifdef CONFIG_NOFASTCALL_FSBASE
+               printk("\nGIANT WARNING: Can't write FS Base from userspace, "
+                      "and no FASTCALL support!\n\n");
+               #endif
+       }
        cpuid(0x80000001, 0x0, &eax, &ebx, &ecx, &edx);
-       if (edx & (1 << 27))
+       if (edx & (1 << 27)) {
                printk("RDTSCP supported\n");
-       else
-               printk("RDTSCP not supported: don't trust detailed measurements\n");
+               /* Set core 0's id, for use during boot (if FAST_COREID) */
+               write_msr(MSR_TSC_AUX, 0);
+       } else {
+               printk("RDTSCP not supported, but emulated for userspace\n");
+               #ifdef CONFIG_FAST_COREID
+               printk("\nCONFIG_FAST_COREID selected, but RDTSCP not available!\n");
+               printk("\nRebuild your kernel without CONFIG_FAST_COREID\n\n");
+               panic("Cannot boot\n");
+               #endif
+       }
+       /* Regardless, make sure userspace can access rdtsc (and rdtscp) */
+       lcr4(rcr4() & ~CR4_TSD);
+       printk("1 GB Jumbo pages %ssupported\n", edx & (1 << 26) ? "" : "not ");
        printk("FS/GS MSRs %ssupported\n", edx & (1 << 29) ? "" : "not ");
-       msr_val = read_msr(IA32_MISC_ENABLE);
-       /* we want this to be not set for cpuid.6h to work. */
-       if (msr_val & (1 << 22))
-               write_msr(IA32_MISC_ENABLE, msr_val & ~(1 << 22));
+       #ifdef CONFIG_X86_64
+       if (!(edx & (1 << 29))) {
+               printk("Can't handle no FS/GS MSRs!\n");
+               while (1)
+                       asm volatile ("hlt");
+       }
+       #endif
        cpuid(0x00000006, 0x0, &eax, 0, 0, 0);
        if (eax & (1 << 2))
                printk("Always running APIC detected\n");
@@ -176,25 +213,3 @@ void show_mapping(uintptr_t start, size_t size)
                }
        }
 }
-
-/* Like backtrace, this is probably not the best place for this. */
-void spinlock_debug(spinlock_t *lock)
-{
-#ifdef CONFIG_SPINLOCK_DEBUG
-       eipdebuginfo_t debuginfo;
-       char buf[256];
-       uint32_t eip = (uint32_t)lock->call_site;
-
-       if (!eip) {
-               printk("Lock %p: never locked\n", lock);
-               return;
-       }
-       debuginfo_eip(eip, &debuginfo);
-       memset(buf, 0, 256);
-       strncpy(buf, debuginfo.eip_fn_name, MIN(debuginfo.eip_fn_namelen, 256));
-       buf[MIN(debuginfo.eip_fn_namelen, 255)] = 0;
-       printk("Lock %p: last locked at [<%p>] in %s(%p) on core %d\n", lock, eip, buf,
-              debuginfo.eip_fn_addr, lock->calling_core);
-#endif
-}
-