1/* 2 * Copyright 2002-2009, Axel D��rfler, axeld@pinc-software.de. 3 * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. 4 * Distributed under the terms of the MIT License. 5 * 6 * Copyright 2001-2002, Travis Geiselbrecht. All rights reserved. 7 * Distributed under the terms of the NewOS License. 8 */ 9#ifndef _KERNEL_ARCH_x86_CPU_H 10#define _KERNEL_ARCH_x86_CPU_H 11 12 13#ifndef _ASSEMBLER 14 15#include <module.h> 16#include <arch/x86/descriptors.h> 17 18#ifdef __x86_64__ 19# include <arch/x86/64/iframe.h> 20#else 21# include <arch/x86/32/iframe.h> 22#endif 23 24#endif // !_ASSEMBLER 25 26 27// MSR registers (possibly Intel specific) 28#define IA32_MSR_TSC 0x10 29#define IA32_MSR_APIC_BASE 0x1b 30 31#define IA32_MSR_MTRR_CAPABILITIES 0xfe 32#define IA32_MSR_SYSENTER_CS 0x174 33#define IA32_MSR_SYSENTER_ESP 0x175 34#define IA32_MSR_SYSENTER_EIP 0x176 35#define IA32_MSR_ENERGY_PERF_BIAS 0x1b0 36#define IA32_MSR_MTRR_DEFAULT_TYPE 0x2ff 37#define IA32_MSR_MTRR_PHYSICAL_BASE_0 0x200 38#define IA32_MSR_MTRR_PHYSICAL_MASK_0 0x201 39 40#define IA32_MSR_EFER 0xc0000080 41 42// x86_64 MSRs. 43#define IA32_MSR_STAR 0xc0000081 44#define IA32_MSR_LSTAR 0xc0000082 45#define IA32_MSR_FMASK 0xc0000084 46#define IA32_MSR_FS_BASE 0xc0000100 47#define IA32_MSR_GS_BASE 0xc0000101 48#define IA32_MSR_KERNEL_GS_BASE 0xc0000102 49 50// K8 MSR registers 51#define K8_MSR_IPM 0xc0010055 52 53// x86 features from cpuid eax 1, edx register 54// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-5) 55#define IA32_FEATURE_FPU (1 << 0) // x87 fpu 56#define IA32_FEATURE_VME (1 << 1) // virtual 8086 57#define IA32_FEATURE_DE (1 << 2) // debugging extensions 58#define IA32_FEATURE_PSE (1 << 3) // page size extensions 59#define IA32_FEATURE_TSC (1 << 4) // rdtsc instruction 60#define IA32_FEATURE_MSR (1 << 5) // rdmsr/wrmsr instruction 61#define IA32_FEATURE_PAE (1 << 6) // extended 3 level page table addressing 62#define IA32_FEATURE_MCE (1 << 7) // machine check exception 63#define IA32_FEATURE_CX8 (1 << 8) // cmpxchg8b instruction 64#define IA32_FEATURE_APIC (1 << 9) // local apic on chip 65// (1 << 10) // Reserved 66#define IA32_FEATURE_SEP (1 << 11) // SYSENTER/SYSEXIT 67#define IA32_FEATURE_MTRR (1 << 12) // MTRR 68#define IA32_FEATURE_PGE (1 << 13) // paging global bit 69#define IA32_FEATURE_MCA (1 << 14) // machine check architecture 70#define IA32_FEATURE_CMOV (1 << 15) // cmov instruction 71#define IA32_FEATURE_PAT (1 << 16) // page attribute table 72#define IA32_FEATURE_PSE36 (1 << 17) // page size extensions with 4MB pages 73#define IA32_FEATURE_PSN (1 << 18) // processor serial number 74#define IA32_FEATURE_CLFSH (1 << 19) // cflush instruction 75// (1 << 20) // Reserved 76#define IA32_FEATURE_DS (1 << 21) // debug store 77#define IA32_FEATURE_ACPI (1 << 22) // thermal monitor and clock ctrl 78#define IA32_FEATURE_MMX (1 << 23) // mmx instructions 79#define IA32_FEATURE_FXSR (1 << 24) // FXSAVE/FXRSTOR instruction 80#define IA32_FEATURE_SSE (1 << 25) // SSE 81#define IA32_FEATURE_SSE2 (1 << 26) // SSE2 82#define IA32_FEATURE_SS (1 << 27) // self snoop 83#define IA32_FEATURE_HTT (1 << 28) // hyperthreading 84#define IA32_FEATURE_TM (1 << 29) // thermal monitor 85#define IA32_FEATURE_IA64 (1 << 30) // IA64 processor emulating x86 86#define IA32_FEATURE_PBE (1 << 31) // pending break enable 87 88// x86 features from cpuid eax 1, ecx register 89// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-4) 90#define IA32_FEATURE_EXT_SSE3 (1 << 0) // SSE3 91#define IA32_FEATURE_EXT_PCLMULQDQ (1 << 1) // PCLMULQDQ Instruction 92#define IA32_FEATURE_EXT_DTES64 (1 << 2) // 64-Bit Debug Store 93#define IA32_FEATURE_EXT_MONITOR (1 << 3) // MONITOR/MWAIT 94#define IA32_FEATURE_EXT_DSCPL (1 << 4) // CPL qualified debug store 95#define IA32_FEATURE_EXT_VMX (1 << 5) // Virtual Machine Extensions 96#define IA32_FEATURE_EXT_SMX (1 << 6) // Safer Mode Extensions 97#define IA32_FEATURE_EXT_EST (1 << 7) // Enhanced SpeedStep 98#define IA32_FEATURE_EXT_TM2 (1 << 8) // Thermal Monitor 2 99#define IA32_FEATURE_EXT_SSSE3 (1 << 9) // Supplemental SSE-3 100#define IA32_FEATURE_EXT_CNXTID (1 << 10) // L1 Context ID 101// (1 << 11) // Reserved 102#define IA32_FEATURE_EXT_FMA (1 << 12) // Fused Multiply Add 103#define IA32_FEATURE_EXT_CX16 (1 << 13) // CMPXCHG16B 104#define IA32_FEATURE_EXT_XTPR (1 << 14) // xTPR Update Control 105#define IA32_FEATURE_EXT_PDCM (1 << 15) // Perfmon and Debug Capability 106// (1 << 16) // Reserved 107#define IA32_FEATURE_EXT_PCID (1 << 17) // Process Context Identifiers 108#define IA32_FEATURE_EXT_DCA (1 << 18) // Direct Cache Access 109#define IA32_FEATURE_EXT_SSE4_1 (1 << 19) // SSE4.1 110#define IA32_FEATURE_EXT_SSE4_2 (1 << 20) // SSE4.2 111#define IA32_FEATURE_EXT_X2APIC (1 << 21) // Extended xAPIC Support 112#define IA32_FEATURE_EXT_MOVBE (1 << 22) // MOVBE Instruction 113#define IA32_FEATURE_EXT_POPCNT (1 << 23) // POPCNT Instruction 114#define IA32_FEATURE_EXT_TSCDEADLINE (1 << 24) // Time Stamp Counter Deadline 115#define IA32_FEATURE_EXT_AES (1 << 25) // AES Instruction Extensions 116#define IA32_FEATURE_EXT_XSAVE (1 << 26) // XSAVE/XSTOR States 117#define IA32_FEATURE_EXT_OSXSAVE (1 << 27) // OS-Enabled XSAVE 118#define IA32_FEATURE_EXT_AVX (1 << 28) // Advanced Vector Extensions 119#define IA32_FEATURE_EXT_F16C (1 << 29) // 16-bit FP conversion 120#define IA32_FEATURE_EXT_RDRND (1 << 30) // RDRAND instruction 121#define IA32_FEATURE_EXT_HYPERVISOR (1 << 31) // Running on a hypervisor 122 123// x86 features from cpuid eax 0x80000001, edx register (AMD) 124// only care about the ones that are unique to this register 125#define IA32_FEATURE_AMD_EXT_SYSCALL (1 << 11) // SYSCALL/SYSRET 126#define IA32_FEATURE_AMD_EXT_NX (1 << 20) // no execute bit 127#define IA32_FEATURE_AMD_EXT_MMXEXT (1 << 22) // mmx extensions 128#define IA32_FEATURE_AMD_EXT_FFXSR (1 << 25) // fast FXSAVE/FXRSTOR 129#define IA32_FEATURE_AMD_EXT_RDTSCP (1 << 27) // rdtscp instruction 130#define IA32_FEATURE_AMD_EXT_LONG (1 << 29) // long mode 131#define IA32_FEATURE_AMD_EXT_3DNOWEXT (1 << 30) // 3DNow! extensions 132#define IA32_FEATURE_AMD_EXT_3DNOW (1 << 31) // 3DNow! 133 134// x86 defined features from cpuid eax 6, eax register 135// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-11) 136#define IA32_FEATURE_DTS (1 << 0) //Digital Thermal Sensor 137#define IA32_FEATURE_ITB (1 << 1) //Intel Turbo Boost Technology 138#define IA32_FEATURE_ARAT (1 << 2) //Always running APIC Timer 139#define IA32_FEATURE_PLN (1 << 4) //Power Limit Notification 140#define IA32_FEATURE_ECMD (1 << 5) //Extended Clock Modulation Duty 141#define IA32_FEATURE_PTM (1 << 6) //Package Thermal Management 142 143// x86 defined features from cpuid eax 6, ecx register 144// reference http://www.intel.com/Assets/en_US/PDF/appnote/241618.pdf (Table 5-11) 145#define IA32_FEATURE_APERFMPERF (1 << 0) //IA32_APERF, IA32_MPERF 146#define IA32_FEATURE_EPB (1 << 3) //IA32_ENERGY_PERF_BIAS 147 148// cr4 flags 149#define IA32_CR4_PAE (1UL << 5) 150#define IA32_CR4_GLOBAL_PAGES (1UL << 7) 151 152// Memory type ranges 153#define IA32_MTR_UNCACHED 0 154#define IA32_MTR_WRITE_COMBINING 1 155#define IA32_MTR_WRITE_THROUGH 4 156#define IA32_MTR_WRITE_PROTECTED 5 157#define IA32_MTR_WRITE_BACK 6 158 159// EFLAGS register 160#define X86_EFLAGS_CARRY 0x00000001 161#define X86_EFLAGS_RESERVED1 0x00000002 162#define X86_EFLAGS_PARITY 0x00000004 163#define X86_EFLAGS_AUXILIARY_CARRY 0x00000010 164#define X86_EFLAGS_ZERO 0x00000040 165#define X86_EFLAGS_SIGN 0x00000080 166#define X86_EFLAGS_TRAP 0x00000100 167#define X86_EFLAGS_INTERRUPT 0x00000200 168#define X86_EFLAGS_DIRECTION 0x00000400 169#define X86_EFLAGS_OVERFLOW 0x00000800 170#define X86_EFLAGS_IO_PRIVILEG_LEVEL 0x00003000 171#define X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT 12 172#define X86_EFLAGS_NESTED_TASK 0x00004000 173#define X86_EFLAGS_RESUME 0x00010000 174#define X86_EFLAGS_V86_MODE 0x00020000 175#define X86_EFLAGS_ALIGNMENT_CHECK 0x00040000 176#define X86_EFLAGS_VIRTUAL_INTERRUPT 0x00080000 177#define X86_EFLAGS_VIRTUAL_INTERRUPT_PENDING 0x00100000 178#define X86_EFLAGS_ID 0x00200000 179 180#define X86_EFLAGS_USER_FLAGS (X86_EFLAGS_CARRY | X86_EFLAGS_PARITY \ 181 | X86_EFLAGS_AUXILIARY_CARRY | X86_EFLAGS_ZERO | X86_EFLAGS_SIGN \ 182 | X86_EFLAGS_DIRECTION | X86_EFLAGS_OVERFLOW) 183 184 185// iframe types 186#define IFRAME_TYPE_SYSCALL 0x1 187#define IFRAME_TYPE_OTHER 0x2 188#define IFRAME_TYPE_MASK 0xf 189 190 191#ifndef _ASSEMBLER 192 193 194struct X86PagingStructures; 195 196 197typedef struct x86_mtrr_info { 198 uint64 base; 199 uint64 size; 200 uint8 type; 201} x86_mtrr_info; 202 203typedef struct x86_optimized_functions { 204 void (*memcpy)(void* dest, const void* source, size_t count); 205 void* memcpy_end; 206 void (*memset)(void* dest, int value, size_t count); 207 void* memset_end; 208} x86_optimized_functions; 209 210typedef struct x86_cpu_module_info { 211 module_info info; 212 uint32 (*count_mtrrs)(void); 213 void (*init_mtrrs)(void); 214 215 void (*set_mtrr)(uint32 index, uint64 base, uint64 length, 216 uint8 type); 217 status_t (*get_mtrr)(uint32 index, uint64* _base, uint64* _length, 218 uint8* _type); 219 void (*set_mtrrs)(uint8 defaultType, const x86_mtrr_info* infos, 220 uint32 count); 221 222 void (*get_optimized_functions)(x86_optimized_functions* functions); 223} x86_cpu_module_info; 224 225// features 226enum x86_feature_type { 227 FEATURE_COMMON = 0, // cpuid eax=1, ecx register 228 FEATURE_EXT, // cpuid eax=1, edx register 229 FEATURE_EXT_AMD, // cpuid eax=0x80000001, edx register (AMD) 230 FEATURE_6_EAX, // cpuid eax=6, eax registers 231 FEATURE_6_ECX, // cpuid eax=6, ecx registers 232 233 FEATURE_NUM 234}; 235 236enum x86_vendors { 237 VENDOR_INTEL = 0, 238 VENDOR_AMD, 239 VENDOR_CYRIX, 240 VENDOR_UMC, 241 VENDOR_NEXGEN, 242 VENDOR_CENTAUR, 243 VENDOR_RISE, 244 VENDOR_TRANSMETA, 245 VENDOR_NSC, 246 247 VENDOR_NUM, 248 VENDOR_UNKNOWN, 249}; 250 251 252typedef struct arch_cpu_info { 253 // saved cpu info 254 enum x86_vendors vendor; 255 uint32 feature[FEATURE_NUM]; 256 char model_name[49]; 257 const char* vendor_name; 258 int type; 259 int family; 260 int extended_family; 261 int stepping; 262 int model; 263 int extended_model; 264 265 struct X86PagingStructures* active_paging_structures; 266 267 size_t dr6; // temporary storage for debug registers (cf. 268 size_t dr7; // x86_exit_user_debug_at_kernel_entry()) 269 270 // local TSS for this cpu 271 struct tss tss; 272#ifndef __x86_64__ 273 struct tss double_fault_tss; 274#endif 275} arch_cpu_info; 276 277 278#undef PAUSE 279#define PAUSE() asm volatile ("pause;") 280 281#define nop() __asm__ ("nop"::) 282 283#define x86_read_cr0() ({ \ 284 size_t _v; \ 285 __asm__("mov %%cr0,%0" : "=r" (_v)); \ 286 _v; \ 287}) 288 289#define x86_write_cr0(value) \ 290 __asm__("mov %0,%%cr0" : : "r" (value)) 291 292#define x86_read_cr2() ({ \ 293 size_t _v; \ 294 __asm__("mov %%cr2,%0" : "=r" (_v)); \ 295 _v; \ 296}) 297 298#define x86_read_cr3() ({ \ 299 size_t _v; \ 300 __asm__("mov %%cr3,%0" : "=r" (_v)); \ 301 _v; \ 302}) 303 304#define x86_write_cr3(value) \ 305 __asm__("mov %0,%%cr3" : : "r" (value)) 306 307#define x86_read_cr4() ({ \ 308 size_t _v; \ 309 __asm__("mov %%cr4,%0" : "=r" (_v)); \ 310 _v; \ 311}) 312 313#define x86_write_cr4(value) \ 314 __asm__("mov %0,%%cr4" : : "r" (value)) 315 316#define x86_read_dr3() ({ \ 317 size_t _v; \ 318 __asm__("mov %%dr3,%0" : "=r" (_v)); \ 319 _v; \ 320}) 321 322#define x86_write_dr3(value) \ 323 __asm__("mov %0,%%dr3" : : "r" (value)) 324 325#define invalidate_TLB(va) \ 326 __asm__("invlpg (%0)" : : "r" (va)) 327 328#define wbinvd() \ 329 __asm__("wbinvd") 330 331#define out8(value,port) \ 332 __asm__ ("outb %%al,%%dx" : : "a" (value), "d" (port)) 333 334#define out16(value,port) \ 335 __asm__ ("outw %%ax,%%dx" : : "a" (value), "d" (port)) 336 337#define out32(value,port) \ 338 __asm__ ("outl %%eax,%%dx" : : "a" (value), "d" (port)) 339 340#define in8(port) ({ \ 341 uint8 _v; \ 342 __asm__ volatile ("inb %%dx,%%al" : "=a" (_v) : "d" (port)); \ 343 _v; \ 344}) 345 346#define in16(port) ({ \ 347 uint16 _v; \ 348 __asm__ volatile ("inw %%dx,%%ax":"=a" (_v) : "d" (port)); \ 349 _v; \ 350}) 351 352#define in32(port) ({ \ 353 uint32 _v; \ 354 __asm__ volatile ("inl %%dx,%%eax":"=a" (_v) : "d" (port)); \ 355 _v; \ 356}) 357 358#define out8_p(value,port) \ 359 __asm__ ("outb %%al,%%dx\n" \ 360 "\tjmp 1f\n" \ 361 "1:\tjmp 1f\n" \ 362 "1:" : : "a" (value), "d" (port)) 363 364#define in8_p(port) ({ \ 365 uint8 _v; \ 366 __asm__ volatile ("inb %%dx,%%al\n" \ 367 "\tjmp 1f\n" \ 368 "1:\tjmp 1f\n" \ 369 "1:" : "=a" (_v) : "d" (port)); \ 370 _v; \ 371}) 372 373 374#ifdef __cplusplus 375extern "C" { 376#endif 377 378struct arch_thread; 379 380#ifdef __x86_64__ 381void __x86_setup_system_time(uint64 conversionFactor, 382 uint64 conversionFactorNsecs); 383#else 384void __x86_setup_system_time(uint32 conversionFactor, 385 uint32 conversionFactorNsecs, bool conversionFactorNsecsShift); 386#endif 387 388void x86_context_switch(struct arch_thread* oldState, 389 struct arch_thread* newState); 390void x86_userspace_thread_exit(void); 391void x86_end_userspace_thread_exit(void); 392void x86_swap_pgdir(addr_t newPageDir); 393void x86_fxsave(void* fpuState); 394void x86_fxrstor(const void* fpuState); 395void x86_noop_swap(void* oldFpuState, const void* newFpuState); 396void x86_fxsave_swap(void* oldFpuState, const void* newFpuState); 397addr_t x86_get_stack_frame(); 398uint64 x86_read_msr(uint32 registerNumber); 399void x86_write_msr(uint32 registerNumber, uint64 value); 400uint32 x86_count_mtrrs(void); 401void x86_set_mtrr(uint32 index, uint64 base, uint64 length, uint8 type); 402status_t x86_get_mtrr(uint32 index, uint64* _base, uint64* _length, 403 uint8* _type); 404void x86_set_mtrrs(uint8 defaultType, const x86_mtrr_info* infos, 405 uint32 count); 406void x86_init_fpu(); 407bool x86_check_feature(uint32 feature, enum x86_feature_type type); 408void* x86_get_double_fault_stack(int32 cpu, size_t* _size); 409int32 x86_double_fault_get_cpu(void); 410 411void x86_invalid_exception(iframe* frame); 412void x86_fatal_exception(iframe* frame); 413void x86_unexpected_exception(iframe* frame); 414void x86_hardware_interrupt(iframe* frame); 415void x86_page_fault_exception(iframe* iframe); 416 417#ifndef __x86_64__ 418 419void x86_fnsave(void* fpuState); 420void x86_frstor(const void* fpuState); 421void x86_fnsave_swap(void* oldFpuState, const void* newFpuState); 422 423#endif 424 425 426#ifdef __cplusplus 427} // extern "C" { 428#endif 429 430#endif // !_ASSEMBLER 431 432#endif /* _KERNEL_ARCH_x86_CPU_H */ 433