[e16e8f2] | 1 | /* ----------------------------------------------------------------------- * |
---|
| 2 | * |
---|
| 3 | * Copyright 2006-2009 Erwan Velu - All Rights Reserved |
---|
| 4 | * |
---|
| 5 | * Portions of this file taken from the Linux kernel, |
---|
| 6 | * Copyright 1991-2009 Linus Torvalds and contributors |
---|
| 7 | * |
---|
| 8 | * This program is free software; you can redistribute it and/or modify |
---|
| 9 | * it under the terms of the GNU General Public License version 2 |
---|
| 10 | * as published by the Free Software Foundation, Inc., |
---|
| 11 | * 51 Franklin St, Fifth Floor, Boston MA 02110-1301; |
---|
| 12 | * incorporated herein by reference. |
---|
| 13 | * |
---|
| 14 | * ----------------------------------------------------------------------- */ |
---|
| 15 | |
---|
| 16 | #ifndef _CPUID_H |
---|
| 17 | #define _CPUID_H |
---|
| 18 | |
---|
| 19 | #include <stdbool.h> |
---|
| 20 | #include <stdint.h> |
---|
| 21 | #include <stdio.h> |
---|
| 22 | #include <cpufeature.h> |
---|
| 23 | #include <sys/bitops.h> |
---|
| 24 | #include <sys/cpu.h> |
---|
| 25 | #include <sys/io.h> |
---|
| 26 | #include <klibc/compiler.h> |
---|
| 27 | |
---|
| 28 | #define PAGE_SIZE 4096 |
---|
| 29 | |
---|
| 30 | #define CPU_MODEL_SIZE 48 |
---|
| 31 | #define CPU_VENDOR_SIZE 48 |
---|
| 32 | |
---|
| 33 | #define CPU_FLAGS(m_) \ |
---|
| 34 | m_(bool, fpu, /* Onboard FPU */) \ |
---|
| 35 | m_(bool, vme, /* Virtual Mode Extensions */) \ |
---|
| 36 | m_(bool, de, /* Debugging Extensions */) \ |
---|
| 37 | m_(bool, pse, /* Page Size Extensions */) \ |
---|
| 38 | m_(bool, tsc, /* Time Stamp Counter */) \ |
---|
| 39 | m_(bool, msr, /* Model-Specific Registers, RDMSR, WRMSR */) \ |
---|
| 40 | m_(bool, pae, /* Physical Address Extensions */) \ |
---|
| 41 | m_(bool, mce, /* Machine Check Architecture */) \ |
---|
| 42 | m_(bool, cx8, /* CMPXCHG8 instruction */) \ |
---|
| 43 | m_(bool, apic, /* Onboard APIC */) \ |
---|
| 44 | m_(bool, sep, /* SYSENTER/SYSEXIT */) \ |
---|
| 45 | m_(bool, mtrr, /* Memory Type Range Registers */) \ |
---|
| 46 | m_(bool, pge, /* Page Global Enable */) \ |
---|
| 47 | m_(bool, mca, /* Machine Check Architecture */) \ |
---|
| 48 | m_(bool, cmov, /* CMOV instruction (FCMOVCC and FCOMI too if FPU present) */) \ |
---|
| 49 | m_(bool, pat, /* Page Attribute Table */) \ |
---|
| 50 | m_(bool, pse_36, /* 36-bit PSEs */) \ |
---|
| 51 | m_(bool, psn, /* Processor serial number */) \ |
---|
| 52 | m_(bool, clflsh, /* Supports the CLFLUSH instruction */) \ |
---|
| 53 | m_(bool, dts, /* Debug Trace Store */) \ |
---|
| 54 | m_(bool, acpi, /* ACPI via MSR */) \ |
---|
| 55 | m_(bool, pbe, /* Pending Break Enable */) \ |
---|
| 56 | m_(bool, mmx, /* Multimedia Extensions */) \ |
---|
| 57 | m_(bool, fxsr, /* FXSAVE and FXRSTOR instructions (fast save and restore of FPU context), and CR4.OSFXSR available */) \ |
---|
| 58 | m_(bool, sse, /* Streaming SIMD Extensions */) \ |
---|
| 59 | m_(bool, sse2, /* Streaming SIMD Extensions 2 */) \ |
---|
| 60 | m_(bool, ss, /* CPU self snoop */) \ |
---|
| 61 | m_(bool, htt, /* Hyper-Threading */) \ |
---|
| 62 | m_(bool, acc, /* Automatic clock control */) \ |
---|
| 63 | m_(bool, syscall, /* SYSCALL/SYSRET */) \ |
---|
| 64 | m_(bool, mp, /* MP Capable. */) \ |
---|
| 65 | m_(bool, nx, /* Execute Disable */) \ |
---|
| 66 | m_(bool, mmxext, /* AMD MMX extensions */) \ |
---|
| 67 | m_(bool, fxsr_opt, /* FXSAVE/FXRSTOR optimizations */) \ |
---|
| 68 | m_(bool, gbpages, /* "pdpe1gb" GB pages */) \ |
---|
| 69 | m_(bool, rdtscp, /* RDTSCP */) \ |
---|
| 70 | m_(bool, lm, /* Long Mode (x86-64) */) \ |
---|
| 71 | m_(bool, nowext, /* AMD 3DNow! extensions */) \ |
---|
| 72 | m_(bool, now, /* 3DNow! */) \ |
---|
| 73 | m_(bool, smp, /* A smp configuration has been found */) \ |
---|
| 74 | m_(bool, pni, /* Streaming SIMD Extensions-3 */) \ |
---|
| 75 | m_(bool, pclmulqd, /* PCLMULQDQ instruction */) \ |
---|
| 76 | m_(bool, dtes64, /* 64-bit Debug Store */) \ |
---|
| 77 | m_(bool, vmx, /* Hardware virtualization */) \ |
---|
| 78 | m_(bool, smx, /* Safer Mode */) \ |
---|
| 79 | m_(bool, est, /* Enhanced SpeedStep */) \ |
---|
| 80 | m_(bool, tm2, /* Thermal Monitor 2 */) \ |
---|
| 81 | m_(bool, sse3, /* Supplemental SSE-3 */) \ |
---|
| 82 | m_(bool, cid, /* Context ID */) \ |
---|
| 83 | m_(bool, fma, /* Fused multiply-add */) \ |
---|
| 84 | m_(bool, cx16, /* CMPXCHG16B */) \ |
---|
| 85 | m_(bool, xtpr, /* Send Task Priority Messages */) \ |
---|
| 86 | m_(bool, pdcm, /* Performance Capabilities */) \ |
---|
| 87 | m_(bool, dca, /* Direct Cache Access */) \ |
---|
| 88 | m_(bool, xmm4_1, /* "sse4_1" SSE-4.1 */) \ |
---|
| 89 | m_(bool, xmm4_2, /* "sse4_2" SSE-4.2 */) \ |
---|
| 90 | m_(bool, x2apic, /* x2APIC */) \ |
---|
| 91 | m_(bool, movbe, /* MOVBE instruction */) \ |
---|
| 92 | m_(bool, popcnt, /* POPCNT instruction */) \ |
---|
| 93 | m_(bool, aes, /* AES Instruction */) \ |
---|
| 94 | m_(bool, xsave, /* XSAVE/XRSTOR/XSETBV/XGETBV */) \ |
---|
| 95 | m_(bool, osxsave, /* XSAVE enabled in the OS */) \ |
---|
| 96 | m_(bool, avx, /* Advanced Vector Extensions */) \ |
---|
| 97 | m_(bool, hypervisor, /* Running on a hypervisor */) \ |
---|
| 98 | m_(bool, ace2, /* Advanced Cryptography Engine v2 */) \ |
---|
| 99 | m_(bool, ace2_en, /* ACE v2 enabled */) \ |
---|
| 100 | m_(bool, phe, /* PadLock Hash Engine */) \ |
---|
| 101 | m_(bool, phe_en, /* PadLock Hash Engine Enabled */) \ |
---|
| 102 | m_(bool, pmm, /* PadLock Montgomery Multiplier */) \ |
---|
| 103 | m_(bool, pmm_en, /* PadLock Montgomery Multiplier enabled */) \ |
---|
| 104 | m_(bool, svm, /* Secure virtual machine */) \ |
---|
| 105 | m_(bool, extapic, /* Extended APIC space */) \ |
---|
| 106 | m_(bool, cr8_legacy, /* CR8 in 32-bit mode */) \ |
---|
| 107 | m_(bool, abm, /* Advanced bit manipulation */) \ |
---|
| 108 | m_(bool, sse4a, /* SSE4-A */) \ |
---|
| 109 | m_(bool, misalignsse, /* Misaligned SSE mode */) \ |
---|
| 110 | m_(bool, nowprefetch, /* 3DNow prefetch instructions */) \ |
---|
| 111 | m_(bool, osvw, /* OS Visible Workaround */) \ |
---|
| 112 | m_(bool, ibs, /* Instruction Based Sampling */) \ |
---|
| 113 | m_(bool, sse5, /* SSE5 */) \ |
---|
| 114 | m_(bool, skinit, /* SKINIT/STGI instructions */) \ |
---|
| 115 | m_(bool, wdt, /* Watchdog Timer */) \ |
---|
| 116 | m_(bool, ida, /* Intel Dynamic Acceleration */) \ |
---|
| 117 | m_(bool, arat, /* Always Running APIC Timer */) \ |
---|
| 118 | m_(bool, tpr_shadow, /* Intel TPR Shadow */) \ |
---|
| 119 | m_(bool, vnmi, /* Intel Virtual NMI */) \ |
---|
| 120 | m_(bool, flexpriority, /* Intel FlexPriority */) \ |
---|
| 121 | m_(bool, ept, /* Intel Extended Page Table */) \ |
---|
| 122 | m_(bool, vpid, /* Intel Virtual Processor ID */) |
---|
| 123 | |
---|
| 124 | #define STRUCT_MEMBERS(type_, name_, comment_) type_ name_; |
---|
| 125 | |
---|
| 126 | #define STRUCT_MEMBER_NAMES(type_, name_, comment_) #name_ , |
---|
| 127 | |
---|
| 128 | #define STRUCTURE_MEMBER_OFFSETS(type_, name_, comment_) \ |
---|
| 129 | offsetof(s_cpu_flags, name_), |
---|
| 130 | |
---|
| 131 | typedef struct { |
---|
| 132 | CPU_FLAGS(STRUCT_MEMBERS) |
---|
| 133 | } s_cpu_flags; |
---|
| 134 | |
---|
| 135 | extern size_t cpu_flags_offset[]; |
---|
| 136 | extern const char *cpu_flags_names[]; |
---|
| 137 | extern size_t cpu_flags_count; |
---|
| 138 | |
---|
| 139 | typedef struct { |
---|
| 140 | char vendor[CPU_VENDOR_SIZE]; |
---|
| 141 | uint8_t vendor_id; |
---|
| 142 | uint8_t family; |
---|
| 143 | char model[CPU_MODEL_SIZE]; |
---|
| 144 | uint8_t model_id; |
---|
| 145 | uint8_t stepping; |
---|
| 146 | uint8_t num_cores; |
---|
| 147 | uint16_t l1_data_cache_size; |
---|
| 148 | uint16_t l1_instruction_cache_size; |
---|
| 149 | uint16_t l2_cache_size; |
---|
| 150 | s_cpu_flags flags; |
---|
| 151 | } s_cpu; |
---|
| 152 | |
---|
| 153 | extern bool get_cpu_flag_value_from_name(s_cpu *cpu, const char * flag); |
---|
| 154 | /**********************************************************************************/ |
---|
| 155 | /**********************************************************************************/ |
---|
| 156 | /* From this point this is some internal stuff mainly taken from the linux kernel */ |
---|
| 157 | /**********************************************************************************/ |
---|
| 158 | /**********************************************************************************/ |
---|
| 159 | |
---|
| 160 | /* |
---|
| 161 | * EFLAGS bits |
---|
| 162 | */ |
---|
| 163 | #define X86_EFLAGS_CF 0x00000001 /* Carry Flag */ |
---|
| 164 | #define X86_EFLAGS_PF 0x00000004 /* Parity Flag */ |
---|
| 165 | #define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */ |
---|
| 166 | #define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */ |
---|
| 167 | #define X86_EFLAGS_SF 0x00000080 /* Sign Flag */ |
---|
| 168 | #define X86_EFLAGS_TF 0x00000100 /* Trap Flag */ |
---|
| 169 | #define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */ |
---|
| 170 | #define X86_EFLAGS_DF 0x00000400 /* Direction Flag */ |
---|
| 171 | #define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */ |
---|
| 172 | #define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */ |
---|
| 173 | #define X86_EFLAGS_NT 0x00004000 /* Nested Task */ |
---|
| 174 | #define X86_EFLAGS_RF 0x00010000 /* Resume Flag */ |
---|
| 175 | #define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */ |
---|
| 176 | #define X86_EFLAGS_AC 0x00040000 /* Alignment Check */ |
---|
| 177 | #define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */ |
---|
| 178 | #define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */ |
---|
| 179 | #define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */ |
---|
| 180 | |
---|
| 181 | #define X86_VENDOR_INTEL 0 |
---|
| 182 | #define X86_VENDOR_CYRIX 1 |
---|
| 183 | #define X86_VENDOR_AMD 2 |
---|
| 184 | #define X86_VENDOR_UMC 3 |
---|
| 185 | #define X86_VENDOR_NEXGEN 4 |
---|
| 186 | #define X86_VENDOR_CENTAUR 5 |
---|
| 187 | #define X86_VENDOR_RISE 6 |
---|
| 188 | #define X86_VENDOR_TRANSMETA 7 |
---|
| 189 | #define X86_VENDOR_NSC 8 |
---|
| 190 | #define X86_VENDOR_UNKNOWN 9 |
---|
| 191 | #define X86_VENDOR_NUM 10 |
---|
| 192 | |
---|
| 193 | #define cpu_has(c, bit) test_bit(bit, (c)->x86_capability) |
---|
| 194 | |
---|
| 195 | // Taken from asm/processor-flags.h |
---|
| 196 | // NSC/Cyrix CPU configuration register indexes |
---|
| 197 | #define CX86_CCR2 0xc2 |
---|
| 198 | #define CX86_CCR3 0xc3 |
---|
| 199 | #define CX86_DIR0 0xfe |
---|
| 200 | #define CX86_DIR1 0xff |
---|
| 201 | |
---|
| 202 | static const char Cx86_model[][9] = { |
---|
| 203 | "Cx486", "Cx486", "5x86 ", "6x86", "MediaGX ", "6x86MX ", |
---|
| 204 | "M II ", "Unknown" |
---|
| 205 | }; |
---|
| 206 | |
---|
| 207 | static const char Cx486_name[][5] = { |
---|
| 208 | "SLC", "DLC", "SLC2", "DLC2", "SRx", "DRx", |
---|
| 209 | "SRx2", "DRx2" |
---|
| 210 | }; |
---|
| 211 | |
---|
| 212 | static const char Cx486S_name[][4] = { |
---|
| 213 | "S", "S2", "Se", "S2e" |
---|
| 214 | }; |
---|
| 215 | |
---|
| 216 | static const char Cx486D_name[][4] = { |
---|
| 217 | "DX", "DX2", "?", "?", "?", "DX4" |
---|
| 218 | }; |
---|
| 219 | |
---|
| 220 | |
---|
| 221 | /* |
---|
| 222 | * CPU type and hardware bug flags. Kept separately for each CPU. |
---|
| 223 | * Members of this structure are referenced in head.S, so think twice |
---|
| 224 | * before touching them. [mj] |
---|
| 225 | */ |
---|
| 226 | |
---|
| 227 | struct cpuinfo_x86 { |
---|
| 228 | uint8_t x86; /* CPU family */ |
---|
| 229 | uint8_t x86_vendor; /* CPU vendor */ |
---|
| 230 | uint8_t x86_model; |
---|
| 231 | uint8_t x86_mask; |
---|
| 232 | char wp_works_ok; /* It doesn't on 386's */ |
---|
| 233 | char hlt_works_ok; /* Problems on some 486Dx4's and old 386's */ |
---|
| 234 | char hard_math; |
---|
| 235 | char rfu; |
---|
| 236 | int cpuid_level; /* Maximum supported CPUID level, -1=no CPUID */ |
---|
| 237 | uint32_t x86_capability[NCAPINTS]; |
---|
| 238 | char x86_vendor_id[16]; |
---|
| 239 | char x86_model_id[64]; |
---|
| 240 | uint16_t x86_l1_data_cache_size; /* in KB, if available */ |
---|
| 241 | uint16_t x86_l1_instruction_cache_size; /* in KB, if available */ |
---|
| 242 | uint16_t x86_l2_cache_size; /* in KB, if available */ |
---|
| 243 | int x86_cache_alignment; /* in bytes */ |
---|
| 244 | char fdiv_bug; |
---|
| 245 | char f00f_bug; |
---|
| 246 | char coma_bug; |
---|
| 247 | char pad0; |
---|
| 248 | int x86_power; |
---|
| 249 | unsigned long loops_per_jiffy; |
---|
| 250 | #ifdef CONFIG_SMP |
---|
| 251 | cpumask_t llc_shared_map; /* cpus sharing the last level cache */ |
---|
| 252 | #endif |
---|
| 253 | unsigned char x86_num_cores; /* cpuid returned the number of cores */ |
---|
| 254 | unsigned char booted_cores; /* number of cores as seen by OS */ |
---|
| 255 | unsigned char apicid; |
---|
| 256 | unsigned char x86_clflush_size; |
---|
| 257 | |
---|
| 258 | } __attribute__ ((__packed__)); |
---|
| 259 | |
---|
| 260 | struct cpu_model_info { |
---|
| 261 | int vendor; |
---|
| 262 | int family; |
---|
| 263 | char *model_names[16]; |
---|
| 264 | }; |
---|
| 265 | |
---|
| 266 | /* attempt to consolidate cpu attributes */ |
---|
| 267 | struct cpu_dev { |
---|
| 268 | const char *c_vendor; |
---|
| 269 | |
---|
| 270 | /* some have two possibilities for cpuid string */ |
---|
| 271 | const char *c_ident[2]; |
---|
| 272 | |
---|
| 273 | struct cpu_model_info c_models[4]; |
---|
| 274 | |
---|
| 275 | void (*c_init) (struct cpuinfo_x86 * c); |
---|
| 276 | void (*c_identify) (struct cpuinfo_x86 * c); |
---|
| 277 | unsigned int (*c_size_cache) (struct cpuinfo_x86 * c, unsigned int size); |
---|
| 278 | }; |
---|
| 279 | |
---|
| 280 | /* |
---|
| 281 | * Structure definitions for SMP machines following the |
---|
| 282 | * Intel Multiprocessing Specification 1.1 and 1.4. |
---|
| 283 | */ |
---|
| 284 | |
---|
| 285 | /* |
---|
| 286 | * This tag identifies where the SMP configuration |
---|
| 287 | * information is. |
---|
| 288 | */ |
---|
| 289 | |
---|
| 290 | #define SMP_MAGIC_IDENT (('_'<<24)|('P'<<16)|('M'<<8)|'_') |
---|
| 291 | |
---|
| 292 | struct intel_mp_floating { |
---|
| 293 | char mpf_signature[4]; /* "_MP_" */ |
---|
| 294 | uint32_t mpf_physptr; /* Configuration table address */ |
---|
| 295 | uint8_t mpf_length; /* Our length (paragraphs) */ |
---|
| 296 | uint8_t mpf_specification; /* Specification version */ |
---|
| 297 | uint8_t mpf_checksum; /* Checksum (makes sum 0) */ |
---|
| 298 | uint8_t mpf_feature1; /* Standard or configuration ? */ |
---|
| 299 | uint8_t mpf_feature2; /* Bit7 set for IMCR|PIC */ |
---|
| 300 | uint8_t mpf_feature3; /* Unused (0) */ |
---|
| 301 | uint8_t mpf_feature4; /* Unused (0) */ |
---|
| 302 | uint8_t mpf_feature5; /* Unused (0) */ |
---|
| 303 | }; |
---|
| 304 | |
---|
| 305 | static inline uint8_t getCx86(uint8_t reg) { |
---|
| 306 | outb(reg, 0x22); |
---|
| 307 | return inb(0x23); |
---|
| 308 | } |
---|
| 309 | |
---|
| 310 | static inline void setCx86(uint8_t reg, uint8_t data) { |
---|
| 311 | outb(reg, 0x22); |
---|
| 312 | outb(data, 0x23); |
---|
| 313 | } |
---|
| 314 | |
---|
| 315 | extern void get_cpu_vendor(struct cpuinfo_x86 *c); |
---|
| 316 | extern void detect_cpu(s_cpu * cpu); |
---|
| 317 | #endif |
---|