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