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