net: Add network_offset to blocks
[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 #include <arch/arch.h>
8 #include <arch/x86.h>
9 #include <arch/mmu.h>
10 #include <stdio.h>
11 #include <assert.h>
12 #include <ros/memlayout.h>
13 #include <pmap.h>
14 #include <kdebug.h>
15 #include <string.h>
16 #include <cpu_feat.h>
17
18 int x86_family, x86_model, x86_stepping;
19
20 /* Check Intel's SDM 2a for Table 3-17 for the cpuid leaves */
21 void print_cpuinfo(void)
22 {
23         uint32_t eax, ebx, ecx, edx;
24         uint32_t model, family, ext_model, ext_family;
25         uint64_t msr_val;
26         char vendor_id[13];
27         int max_std_lvl, max_extd_lvl;
28         extern char _start[];
29
30         if (sizeof(long) == 8)
31                 printk("64 bit Kernel Booting...\n");
32         else
33                 printk("32 bit Kernel Booting...\n");
34
35         // x86 Vendor Detection:
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         if (!strcmp(vendor_id, "GenuineIntel"))
48                 cpu_set_feat(CPU_FEAT_X86_VENDOR_INTEL);
49         else if (!strcmp(vendor_id, "AuthenticAMD"))
50                 cpu_set_feat(CPU_FEAT_X86_VENDOR_AMD);
51
52
53         /* intel supports a way to hide the upper leaves of cpuid, beyond 3.  the
54          * bios might have done this, so we'll make sure it is off. */
55         if (cpu_has_feat(CPU_FEAT_X86_VENDOR_INTEL)) {
56                 msr_val = read_msr(IA32_MISC_ENABLE);
57                 if (msr_val & (1 << 22))
58                         write_msr(IA32_MISC_ENABLE, msr_val & ~(1 << 22));
59         }
60         cprintf("Largest Standard Function Number Supported: %d\n", eax);
61         max_std_lvl = eax;
62         cpuid(0x80000000, 0x0, &eax, 0, 0, 0);
63         cprintf("Largest Extended Function Number Supported: 0x%08x\n", eax);
64         max_extd_lvl = eax;
65         cpuid(1, 0x0, &eax, &ebx, &ecx, &edx);
66         ext_family = (eax >> 20) & 0xff;
67         ext_model = (eax >> 16) & 0xf;
68         family = (eax >> 8) & 0xf;
69         model = (eax >> 4) & 0xf;
70         if ((family == 15) || (family == 6))
71                 model += ext_model << 4;
72         if (family == 15)
73                 family += ext_family;
74         x86_family = family;
75         x86_model = model;
76         x86_stepping = eax & 0xf;
77         printk("Family: %d\n", x86_family);
78         printk("Model: %d\n", x86_model);
79         printk("Stepping: %d\n", x86_stepping);
80         // eventually can fill this out with SDM Vol3B App B info, or
81         // better yet with stepping info.  or cpuid 8000_000{2,3,4}
82         switch ( family << 8 | model ) {
83                 case(0x061a):
84                         cprintf("Processor: Core i7\n");
85                         break;
86                 case(0x060f):
87                         cprintf("Processor: Core 2 Duo or Similar\n");
88                         break;
89                 default:
90                         cprintf("Unknown or non-Intel CPU\n");
91         }
92         if (!(edx & 0x00000020))
93                 panic("MSRs not supported!");
94         if (!(edx & 0x00001000))
95                 panic("MTRRs not supported!");
96         if (!(edx & (1 << 16)))
97                 panic("PAT not supported!");
98         if (!(edx & 0x00002000))
99                 panic("Global Pages not supported!");
100         if (!(edx & 0x00000200))
101                 panic("Local APIC Not Detected!");
102         if (ecx & 0x00200000)
103                 cprintf("x2APIC Detected\n");
104         else
105                 panic("x2APIC Not Detected\n");
106         /* Not sure how to detect AMD HW virt yet. */
107         if ((ecx & 0x00000060) && cpu_has_feat(CPU_FEAT_X86_VENDOR_INTEL)) {
108                 msr_val = read_msr(IA32_FEATURE_CONTROL);
109                 printd("64 Bit Feature Control: 0x%08x\n", msr_val);
110                 if ((msr_val & 0x5) == 0x5)
111                         printk("Hardware virtualization supported\n");
112                 else
113                         printk("Hardware virtualization not supported\n");
114         } else {
115                 printk("Hardware virtualization not detected.  (AMD?)\n");
116         }
117         /* FP and SSE Checks */
118         if (edx & 0x00000001)
119                 printk("FPU Detected\n");
120         else
121                 panic("FPU Not Detected!!\n");
122         printk("SSE support: ");
123         if (edx & (1 << 25))
124                 printk("sse ");
125         else
126                 panic("SSE Support Not Detected!!\n");
127         if (edx & (1 << 26))
128                 printk("sse2 ");
129         if (ecx & (1 << 0))
130                 printk("sse3 ");
131         if (ecx & (1 << 9))
132                 printk("ssse3 ");
133         if (ecx & (1 << 19))
134                 printk("sse4.1 ");
135         if (ecx & (1 << 20))
136                 printk("sse4.2 ");
137         if (edx & (1 << 23))
138                 printk("mmx ");
139         if ((edx & (1 << 25)) && (!(edx & (1 << 24))))
140                 panic("SSE support, but no FXSAVE!");
141         printk("\n");
142         cpuid(0x80000008, 0x0, &eax, &ebx, &ecx, &edx);
143         cprintf("Physical Address Bits: %d\n", eax & 0x000000FF);
144         msr_val = read_msr(IA32_APIC_BASE);
145         if (!(msr_val & MSR_APIC_ENABLE))
146                 panic("Local APIC Disabled!!");
147         cpuid(0x80000007, 0x0, &eax, &ebx, &ecx, &edx);
148         if (edx & 0x00000100)
149                 printk("Invariant TSC present\n");
150         else
151                 printk("Invariant TSC not present\n");
152         cpuid(0x07, 0x0, &eax, &ebx, &ecx, &edx);
153         if (ebx & 0x00000001) {
154                 printk("FS/GS Base RD/W supported\n");
155                 cpu_set_feat(CPU_FEAT_X86_FSGSBASE);
156         } else {
157                 printk("FS/GS Base RD/W not supported\n");
158                 #ifdef CONFIG_NOFASTCALL_FSBASE
159                 panic("Can't write FS Base from userspace, and no FASTCALL support!");
160                 #endif
161         }
162         cpuid(0x80000001, 0x0, &eax, &ebx, &ecx, &edx);
163         if (edx & (1 << 27)) {
164                 printk("RDTSCP supported\n");
165                 /* Set core 0's id, for use during boot (if FAST_COREID) */
166                 write_msr(MSR_TSC_AUX, 0);
167         } else {
168                 printk("RDTSCP not supported, but emulated for userspace\n");
169         }
170         /* Regardless, make sure userspace can access rdtsc (and rdtscp) */
171         lcr4(rcr4() & ~CR4_TSD);
172         printk("1 GB Jumbo pages %ssupported\n", edx & (1 << 26) ? "" : "not ");
173         if (!(edx & (1 << 29))) {
174                 printk("Not 64 bit, refusing to boot!\n");
175                 while (1)
176                         asm volatile ("hlt");
177         }
178         cpuid(0x00000006, 0x0, &eax, 0, 0, 0);
179         if (eax & (1 << 2))
180                 printk("Always running APIC detected\n");
181         else
182                 printk("Always running APIC *not* detected\n");
183
184         /* TODO: Eventually consolidate all of our "cpuid" stuff. */
185         #define CPUID_FXSR_SUPPORT          (1 << 24)
186         #define CPUID_XSAVE_SUPPORT         (1 << 26)
187         #define CPUID_XSAVEOPT_SUPPORT      (1 << 0)
188         #define CPUID_MONITOR_MWAIT         (1 << 3)
189         #define CPUID_MWAIT_PWR_MGMT        (1 << 0)
190
191         cpuid(0x01, 0x00, 0, 0, &ecx, &edx);
192         if (CPUID_FXSR_SUPPORT & edx)
193                 cpu_set_feat(CPU_FEAT_X86_FXSR);
194         if (CPUID_XSAVE_SUPPORT & ecx)
195                 cpu_set_feat(CPU_FEAT_X86_XSAVE);
196
197         cpuid(0x0d, 0x01, &eax, 0, 0, 0);
198         if (CPUID_XSAVEOPT_SUPPORT & eax)
199                 cpu_set_feat(CPU_FEAT_X86_XSAVEOPT);
200
201         cpuid(0x01, 0x00, 0, 0, &ecx, 0);
202         if (CPUID_MONITOR_MWAIT & ecx) {
203                 cpuid(0x05, 0x00, 0, 0, &ecx, 0);
204                 if (CPUID_MWAIT_PWR_MGMT & ecx)
205                         cpu_set_feat(CPU_FEAT_X86_MWAIT);
206         }
207 }
208
209 #define BIT_SPACING "        "
210 #define BIT_DASHES "----------------"
211
212 void show_mapping(pgdir_t pgdir, uintptr_t start, size_t size)
213 {
214         pte_t pte;
215         int perm;
216         page_t *page;
217         uintptr_t i;
218
219         printk("   %sVirtual    %sPhysical  Ps Dr Ac G CD WT U W P EPTE\n",
220                BIT_SPACING, BIT_SPACING);
221         printk("-------------------------------------------------%s\n", BIT_DASHES);
222         for(i = 0; i < size; i += PGSIZE, start += PGSIZE) {
223                 pte = pgdir_walk(pgdir, (void*)start, 0);
224                 printk("%p  ", start);
225                 if (pte_walk_okay(pte)) {
226                         /* A note on PTE perms.  If you look at just the PTE, you don't get
227                          * the full picture for W and U.  Those are the intersection of all
228                          * bits.  In Akaros, we do U or not at the earliest point (PML4
229                          * entries).  All other PTEs have U set.  For W, it's the opposite.
230                          * The PTE for the actual page has W or not, and all others has W
231                          * set.  W needs to be more fine-grained, but U doesn't.  Plus the
232                          * UVPT mapping requires the U to see interior pages (but have W
233                          * off). */
234                         perm = get_va_perms(pgdir, (void*)start);
235                         printk("%p  %1d  %1d  %1d  %1d %1d  %1d  %1d %1d %1d 0x%llx\n",
236                                pte_get_paddr(pte),
237                                pte_is_jumbo(pte),
238                                pte_is_dirty(pte),
239                                pte_is_accessed(pte),
240                                (pte_print(pte) & PTE_G) / PTE_G,
241                                (pte_print(pte) & __PTE_PCD) / __PTE_PCD,
242                                (pte_print(pte) & __PTE_PWT) / __PTE_PWT,
243                                (perm & PTE_U) / PTE_U,
244                                (perm & PTE_W) / PTE_W,
245                                pte_is_present(pte),
246                                *(unsigned long*)kpte_to_epte(pte));
247                 } else {
248                         printk("%p\n", 0);
249                 }
250         }
251 }
252
253 /* return 0 if ok, -1 if it failed for some reason.
254  * Be sensible and call it with 16 bytes.
255  */
256 int vendor_id(char *vid)
257 {
258         uint32_t eax, ebx, ecx, edx;
259
260         asm volatile ("cpuid;"
261                   "movl    %%ebx, (%2);"
262                   "movl    %%edx, 4(%2);"
263                   "movl    %%ecx, 8(%2);"
264                  : "=a"(eax)
265                  : "a"(0), "D"(vid)
266                  : "%ebx", "%ecx", "%edx");
267
268         vid[12] = '\0';
269         return 0;
270 }