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 318