Martin Roth | 9b1b335 | 2016-02-24 12:27:06 -0800 | [diff] [blame] | 1 | /* |
| 2 | * cpuid.c -- |
| 3 | * |
| 4 | * Implements CPUID querying functions |
| 5 | * |
| 6 | */ |
| 7 | #include "stdin.h" |
| 8 | #include "cpuid.h" |
| 9 | |
| 10 | struct cpu_ident cpu_id; |
| 11 | |
| 12 | void get_cpuid() |
| 13 | { |
| 14 | unsigned int *v, dummy[3]; |
| 15 | char *p, *q; |
| 16 | |
| 17 | /* Get max std cpuid & vendor ID */ |
| 18 | cpuid(0x0, &cpu_id.max_cpuid, &cpu_id.vend_id.uint32_array[0], |
| 19 | &cpu_id.vend_id.uint32_array[2], &cpu_id.vend_id.uint32_array[1]); |
| 20 | cpu_id.vend_id.char_array[11] = 0; |
| 21 | |
| 22 | /* Get processor family information & feature flags */ |
| 23 | if (cpu_id.max_cpuid >= 1) { |
| 24 | cpuid(0x00000001, &cpu_id.vers.flat, &cpu_id.info.flat, |
| 25 | &cpu_id.fid.uint32_array[1], &cpu_id.fid.uint32_array[0]); |
| 26 | } |
| 27 | |
| 28 | /* Get the digital thermal sensor & power management status bits */ |
| 29 | if(cpu_id.max_cpuid >= 6) { |
| 30 | cpuid(0x00000006, &cpu_id.dts_pmp, &dummy[0], &dummy[1], &dummy[2]); |
| 31 | } |
| 32 | |
| 33 | /* Get the max extended cpuid */ |
| 34 | cpuid(0x80000000, &cpu_id.max_xcpuid, &dummy[0], &dummy[1], &dummy[2]); |
| 35 | |
| 36 | /* Get extended feature flags, only save EDX */ |
| 37 | if (cpu_id.max_xcpuid >= 0x80000001) { |
| 38 | cpuid(0x80000001, &dummy[0], &dummy[1], |
| 39 | &dummy[2], &cpu_id.fid.uint32_array[2]); |
| 40 | } |
| 41 | |
| 42 | /* Get the brand ID */ |
| 43 | if (cpu_id.max_xcpuid >= 0x80000004) { |
| 44 | v = (unsigned int *)&cpu_id.brand_id; |
| 45 | cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]); |
| 46 | cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]); |
| 47 | cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]); |
| 48 | cpu_id.brand_id.char_array[47] = 0; |
| 49 | } |
| 50 | /* |
| 51 | * Intel chips right-justify this string for some dumb reason; |
| 52 | * undo that brain damage: |
| 53 | */ |
| 54 | p = q = &cpu_id.brand_id.char_array[0]; |
| 55 | while (*p == ' ') |
| 56 | p++; |
| 57 | if (p != q) { |
| 58 | while (*p) |
| 59 | *q++ = *p++; |
| 60 | while (q <= &cpu_id.brand_id.char_array[48]) |
| 61 | *q++ = '\0'; /* Zero-pad the rest */ |
| 62 | } |
| 63 | |
| 64 | /* Get cache information */ |
| 65 | switch(cpu_id.vend_id.char_array[0]) { |
| 66 | case 'A': |
| 67 | /* AMD Processors */ |
| 68 | /* The cache information is only in ecx and edx so only save |
| 69 | * those registers */ |
| 70 | if (cpu_id.max_xcpuid >= 0x80000005) { |
| 71 | cpuid(0x80000005, &dummy[0], &dummy[1], |
| 72 | &cpu_id.cache_info.uint[0], &cpu_id.cache_info.uint[1]); |
| 73 | } |
| 74 | if (cpu_id.max_xcpuid >= 0x80000006) { |
| 75 | cpuid(0x80000006, &dummy[0], &dummy[1], |
| 76 | &cpu_id.cache_info.uint[2], &cpu_id.cache_info.uint[3]); |
| 77 | } |
| 78 | break; |
| 79 | case 'G': |
| 80 | /* Intel Processors, Need to do this in init.c */ |
| 81 | break; |
| 82 | } |
| 83 | |
| 84 | /* Turn off mon bit since monitor based spin wait may not be reliable */ |
| 85 | cpu_id.fid.bits.mon = 0; |
| 86 | |
| 87 | } |