MSR support and more CPUID info
authorBarret Rhoden <brho@cs.berkeley.edu>
Sat, 7 Mar 2009 23:44:05 +0000 (15:44 -0800)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sat, 7 Mar 2009 23:44:05 +0000 (15:44 -0800)
inc/x86.h
kern/init.c
kern/pmap.c

index 67ad5c9..7c53625 100644 (file)
--- a/inc/x86.h
+++ b/inc/x86.h
@@ -3,6 +3,14 @@
 
 #include <inc/types.h>
 
+/* Model Specific Registers */
+#define IA32_APIC_BASE         0x1b
+
+#define MSR_APIC_ENABLE        0x00000800
+
+/* CPUID */
+#define CPUID_PSE_SUPPORT 0x00000008
+
 static __inline void breakpoint(void) __attribute__((always_inline));
 static __inline uint8_t inb(int port) __attribute__((always_inline));
 static __inline void insb(int port, void *addr, int cnt) __attribute__((always_inline));
@@ -34,6 +42,8 @@ static __inline uint32_t read_ebp(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 uint64_t read_tsc(void) __attribute__((always_inline));
+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 void
 breakpoint(void)
@@ -274,4 +284,19 @@ read_tsc(void)
         return tsc;
 }
 
+static __inline uint64_t 
+read_msr(uint32_t reg)
+{
+       uint32_t edx, eax;
+       asm volatile("rdmsr" : "=d"(edx), "=a"(eax) : "c"(reg));
+       return (uint64_t)edx << 32 | eax;
+}
+
+static __inline void 
+write_msr(uint32_t reg, uint64_t val)
+{
+       asm volatile("wrmsr" : : "d"((uint32_t)(val >> 32)),
+                                "a"((uint32_t)(val & 0xFFFFFFFF)), 
+                                "c"(reg));
+}
 #endif /* !JOS_INC_X86_H */
index 406bf8d..e4b72f1 100644 (file)
@@ -9,6 +9,7 @@
 #include <inc/assert.h>
 #include <inc/multiboot.h>
 #include <inc/stab.h>
+#include <inc/x86.h>
 
 #include <kern/monitor.h>
 #include <kern/console.h>
@@ -58,8 +59,8 @@ void kernel_init(multiboot_info_t *mboot_info)
        //ENV_CREATE(user_badsegment);
        //ENV_CREATE(user_divzero);
        ENV_CREATE(user_hello);
-       ENV_CREATE(user_buggyhello);
-       ENV_CREATE(user_evilhello);
+       //ENV_CREATE(user_buggyhello);
+       //ENV_CREATE(user_evilhello);
 #endif // TEST*
 
        // We only have one user environment for now, so just run it.
@@ -110,21 +111,61 @@ void _warn(const char *file, int line, const char *fmt,...)
 }
 
 void print_cpuinfo(void) {
-       int func_num;
+       uint32_t eax, ebx, ecx, edx;
+       uint32_t model, family;
+       uint64_t msr_val;
        char vendor_id[13];
 
-       asm volatile ("subl    %0, %0;"
-                  "cpuid;"
-                  "movl    %%ebx, (%1);"
-                  "movl    %%edx, 4(%1);"
-                  "movl    %%ecx, 8(%1);"
-                     : "=a"(func_num) 
-                                 : "D"(vendor_id)
+       asm volatile ("cpuid;"
+                  "movl    %%ebx, (%2);"
+                  "movl    %%edx, 4(%2);"
+                  "movl    %%ecx, 8(%2);"
+                     : "=a"(eax) 
+                                 : "a"(0), "D"(vendor_id)
                      : "%ebx", "%ecx", "%edx");
 
        vendor_id[12] = '\0';
-       cprintf("Largest Standard Function Number Supported: %d\n", func_num);
        cprintf("Vendor ID: %s\n", vendor_id);
+       cprintf("Largest Standard Function Number Supported: %d\n", eax);
+       cpuid(0x80000000, &eax, 0, 0, 0);
+       cprintf("Largest Extended Function Number Supported: 0x%08x\n", eax);
+       cpuid(1, &eax, &ebx, &ecx, &edx);
+       family = ((eax & 0x0FF00000) >> 20) + ((eax & 0x00000F00) >> 8);
+       model = ((eax & 0x000F0000) >> 12) + ((eax & 0x000000F0) >> 4);
+       cprintf("Family: %d\n", family);
+       cprintf("Model: %d\n", model);
+       cprintf("Stepping: %d\n", eax & 0x0000000F);
+       // eventually can fill this out with SDM Vol3B App B info, or 
+       // better yet with stepping info.  
+       switch ( family << 8 | model ) {
+               case(0x060f):
+                       cprintf("Processor: Core 2 Duo or Similar\n");
+                       break;
+               default:
+                       cprintf("Unknown or non-Intel CPU\n");
+       }
+       if (edx & 0x00000010)
+               cprintf("Model Specific Registers supported\n");
+       else
+               panic("MSRs not supported!");
+       if (edx & 0x00000100)
+               cprintf("Local APIC Detected\n");
+       else
+               panic("Local APIC Not Detected!");
+       
+       cpuid(0x80000008, &eax, &ebx, &ecx, &edx);
+       cprintf("Physical Address Bits: %d\n", eax & 0x000000FF);
+
+
+       /*
+       msr_val = read_msr(IA32_APIC_BASE);
+       msr_val & ~MSR_APIC_ENABLE;
+       write_msr(IA32_APIC_BASE, msr_val);
+       if (edx & 0x00000100)
+               cprintf("Local APIC Detected\n");
+       else
+               panic("Local APIC Not Detected!");
+               */
 }
 
 
index 4114aee..683591d 100644 (file)
@@ -244,17 +244,14 @@ void
 i386_vm_init(void)
 {
        pde_t* pgdir;
-       uint32_t cr0;
+       uint32_t cr0, edx;
        size_t n;
        bool pse;
 
        // check for PSE support
-       asm volatile ("movl    $1, %%eax;"
-                  "cpuid;"
-                  "andl    $0x00000008, %%edx;"
-                     : "=d"(pse) 
-                                 : 
-                     : "%eax");
+       cpuid(1, 0, 0, 0, &edx);
+       pse = edx & CPUID_PSE_SUPPORT;
+
        // turn on PSE
        if (pse) {
                cprintf("PSE capability detected.\n");
@@ -881,10 +878,10 @@ user_mem_check(struct Env *env, const void *DANGEROUS va, size_t len, int perm)
        num_pages = PPN(end - start);
        for (i = 0; i < num_pages; i++, start += PGSIZE) {
                pte = pgdir_walk(env->env_pgdir, start, 0);
-               // ensures the bits we want on are turned on.  if not, E_FAULT
+               // ensures the bits we want on are turned on.  if not, error out
                if ( !pte || ((*pte & perm) != perm) ) {
                        if (i = 0)
-                               user_mem_check_addr = va;
+                               user_mem_check_addr = (void*)va;
                        else
                                user_mem_check_addr = start;
                        return NULL;