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