MSI cleanup and IRQ routing
[akaros.git] / kern / arch / x86 / cpuinfo.c
1 /*
2  * Copyright (c) 2009 The Regents of the University of California
3  * Barret Rhoden <brho@cs.berkeley.edu>
4  * See LICENSE for details.
5  */
6
7 #ifdef __SHARC__
8 #pragma nosharc
9 #endif
10
11 #include <arch/arch.h>
12 #include <arch/x86.h>
13 #include <arch/mmu.h>
14 #include <stdio.h>
15 #include <assert.h>
16 #include <ros/memlayout.h>
17 #include <pmap.h>
18 #include <kdebug.h>
19 #include <string.h>
20
21 /* Check Intel's SDM 2a for Table 3-17 for the cpuid leaves */
22 void print_cpuinfo(void)
23 {
24         uint32_t eax, ebx, ecx, edx;
25         uint32_t model, family;
26         uint64_t msr_val;
27         char vendor_id[13];
28         int max_std_lvl, max_extd_lvl;
29         extern char (SNT RO _start)[];
30         bool is_intel;
31
32         if (sizeof(long) == 8)
33                 printk("64 bit Kernel Booting...\n");
34         else
35                 printk("32 bit Kernel Booting...\n");
36         asm volatile ("cpuid;"
37                   "movl    %%ebx, (%2);"
38                   "movl    %%edx, 4(%2);"
39                   "movl    %%ecx, 8(%2);"
40                  : "=a"(eax)
41                  : "a"(0), "D"(vendor_id)
42                  : "%ebx", "%ecx", "%edx");
43
44         vendor_id[12] = '\0';
45         cprintf("Vendor ID: %s\n", vendor_id);
46         /* not a great check - old intel P5s have no vendor id */
47         is_intel = !strcmp(vendor_id, "GenuineIntel");
48         /* intel supports a way to hide the upper leaves of cpuid, beyond 3.  the
49          * bios might have done this, so we'll make sure it is off. */
50         if (is_intel) {
51                 msr_val = read_msr(IA32_MISC_ENABLE);
52                 if (msr_val & (1 << 22))
53                         write_msr(IA32_MISC_ENABLE, msr_val & ~(1 << 22));
54         }
55         cprintf("Largest Standard Function Number Supported: %d\n", eax);
56         max_std_lvl = eax;
57         cpuid(0x80000000, 0x0, &eax, 0, 0, 0);
58         cprintf("Largest Extended Function Number Supported: 0x%08x\n", eax);
59         max_extd_lvl = eax;
60         cpuid(1, 0x0, &eax, &ebx, &ecx, &edx);
61         family = ((eax & 0x0FF00000) >> 20) + ((eax & 0x00000F00) >> 8);
62         model = ((eax & 0x000F0000) >> 12) + ((eax & 0x000000F0) >> 4);
63         cprintf("Family: %d\n", family);
64         cprintf("Model: %d\n", model);
65         cprintf("Stepping: %d\n", eax & 0x0000000F);
66         // eventually can fill this out with SDM Vol3B App B info, or
67         // better yet with stepping info.  or cpuid 8000_000{2,3,4}
68         switch ( family << 8 | model ) {
69                 case(0x061a):
70                         cprintf("Processor: Core i7\n");
71                         break;
72                 case(0x060f):
73                         cprintf("Processor: Core 2 Duo or Similar\n");
74                         break;
75                 default:
76                         cprintf("Unknown or non-Intel CPU\n");
77         }
78         if (!(edx & 0x00000020))
79                 panic("MSRs not supported!");
80         if (!(edx & 0x00001000))
81                 panic("MTRRs not supported!");
82         if (!(edx & 0x00002000))
83                 panic("Global Pages not supported!");
84         if (!(edx & 0x00000200))
85                 panic("Local APIC Not Detected!");
86         if (ecx & 0x00200000)
87                 cprintf("x2APIC Detected\n");
88         else
89                 cprintf("x2APIC Not Detected\n");
90         /* Not sure how to detect AMD HW virt yet. */
91         if ((ecx & 0x00000060) && is_intel) {
92                 msr_val = read_msr(IA32_FEATURE_CONTROL);
93                 printd("64 Bit Feature Control: 0x%08x\n", msr_val);
94                 if ((msr_val & 0x5) == 0x5)
95                         printk("Hardware virtualization supported\n");
96                 else
97                         printk("Hardware virtualization not supported\n");
98         } else { 
99                 printk("Hardware virtualization not detected.  (AMD?)\n");
100         }
101         /* FP and SSE Checks */
102         if (edx & 0x00000001)
103                 printk("FPU Detected\n");
104         else
105                 panic("FPU Not Detected!!\n");
106         printk("SSE support: ");
107         if (edx & (1 << 25))
108                 printk("sse ");
109         else
110                 panic("SSE Support Not Detected!!\n");
111         if (edx & (1 << 26))
112                 printk("sse2 ");
113         if (ecx & (1 << 0))
114                 printk("sse3 ");
115         if (ecx & (1 << 9))
116                 printk("ssse3 ");
117         if (ecx & (1 << 19))
118                 printk("sse4.1 ");
119         if (ecx & (1 << 20))
120                 printk("sse4.2 ");
121         if (edx & (1 << 23))
122                 printk("mmx ");
123         if ((edx & (1 << 25)) && (!(edx & (1 << 24))))
124                 panic("SSE support, but no FXSAVE!");
125         printk("\n");
126         cpuid(0x80000008, 0x0, &eax, &ebx, &ecx, &edx);
127         cprintf("Physical Address Bits: %d\n", eax & 0x000000FF);
128         msr_val = read_msr(IA32_APIC_BASE);
129         if (!(msr_val & MSR_APIC_ENABLE))
130                 panic("Local APIC Disabled!!");
131         cpuid(0x80000007, 0x0, &eax, &ebx, &ecx, &edx);
132         if (edx & 0x00000100)
133                 printk("Invariant TSC present\n");
134         else
135                 printk("Invariant TSC not present\n");
136         cpuid(0x07, 0x0, &eax, &ebx, &ecx, &edx);
137         if (ebx & 0x00000001) {
138                 printk("FS/GS Base RD/W supported\n");
139                 /* Untested, since we don't have a machine that supports this.  Email us
140                  * if this fails. */
141                 printk("Attempting to enable WRFSBASE...\n");
142                 lcr4(rcr4() | (1 << 16));
143         } else {
144                 printk("FS/GS Base RD/W not supported\n");
145                 #ifdef CONFIG_NOFASTCALL_FSBASE
146                 printk("\nGIANT WARNING: Can't write FS Base from userspace, "
147                        "and no FASTCALL support!\n\n");
148                 #endif
149         }
150         cpuid(0x80000001, 0x0, &eax, &ebx, &ecx, &edx);
151         if (edx & (1 << 27)) {
152                 printk("RDTSCP supported\n");
153                 /* Set core 0's id, for use during boot (if FAST_COREID) */
154                 write_msr(MSR_TSC_AUX, 0);
155         } else {
156                 printk("RDTSCP not supported, but emulated for userspace\n");
157                 #ifdef CONFIG_FAST_COREID
158                 printk("\nCONFIG_FAST_COREID selected, but RDTSCP not available!\n");
159                 printk("\nRebuild your kernel without CONFIG_FAST_COREID\n\n");
160                 panic("Cannot boot\n");
161                 #endif
162         }
163         /* Regardless, make sure userspace can access rdtsc (and rdtscp) */
164         lcr4(rcr4() & ~CR4_TSD);
165         printk("1 GB Jumbo pages %ssupported\n", edx & (1 << 26) ? "" : "not ");
166         printk("FS/GS MSRs %ssupported\n", edx & (1 << 29) ? "" : "not ");
167         #ifdef CONFIG_X86_64
168         if (!(edx & (1 << 29))) {
169                 printk("Can't handle no FS/GS MSRs!\n");
170                 while (1)
171                         asm volatile ("hlt");
172         }
173         #endif
174         cpuid(0x00000006, 0x0, &eax, 0, 0, 0);
175         if (eax & (1 << 2))
176                 printk("Always running APIC detected\n");
177         else
178                 printk("Always running APIC *not* detected\n");
179 }
180
181 #ifdef CONFIG_X86_64
182 #define BIT_SPACING "        "
183 #define BIT_DASHES "----------------"
184 #else
185 #define BIT_SPACING ""
186 #define BIT_DASHES ""
187 #endif
188
189 void show_mapping(uintptr_t start, size_t size)
190 {
191         pde_t *pgdir = (pde_t*)vpd;
192         pte_t *pte;
193         pte_t *pde;
194         page_t *page;
195         uintptr_t i;
196
197         printk("   %sVirtual    %sPhysical  Ps Dr Ac CD WT U W P\n", BIT_SPACING,
198                BIT_SPACING);
199         printk("--------------------------------------------%s\n", BIT_DASHES);
200         for(i = 0; i < size; i += PGSIZE, start += PGSIZE) {
201                 pte = pgdir_walk(pgdir, (void*)start, 0);
202                 printk("%p  ", start);
203                 if (pte) {
204                         pde = &pgdir[PDX(start)];
205                         /* for a jumbo, pde = pte and PTE_PS (better be) = 1 */
206                         printk("%p  %1d  %1d  %1d  %1d  %1d  %1d %1d %1d\n",
207                                PTE_ADDR(*pte), (*pte & PTE_PS) >> 7, (*pte & PTE_D) >> 6,
208                                (*pte & PTE_A) >> 5, (*pte & PTE_PCD) >> 4,
209                                (*pte & PTE_PWT) >> 3, (*pte & *pde & PTE_U) >> 2,
210                                (*pte & *pde & PTE_W) >> 1, (*pte & PTE_P));
211                 } else {
212                         printk("%p\n", 0);
213                 }
214         }
215 }
216
217 /* return 0 if ok, -1 if it failed for some reason.
218  * Be sensible and call it with 16 bytes.
219  */
220 int vendor_id(char *vid)
221 {
222         uint32_t eax, ebx, ecx, edx;
223
224         asm volatile ("cpuid;"
225                   "movl    %%ebx, (%2);"
226                   "movl    %%edx, 4(%2);"
227                   "movl    %%ecx, 8(%2);"
228                  : "=a"(eax)
229                  : "a"(0), "D"(vid)
230                  : "%ebx", "%ecx", "%edx");
231
232         vid[12] = '\0';
233         return 0;
234 }