Home | History | Annotate | Download | only in gplinclude
      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