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 #define IA32_FEATURE_FPU 0x00000001 // x87 fpu 38 #define IA32_FEATURE_VME 0x00000002 // virtual 8086 39 #define IA32_FEATURE_DE 0x00000004 // debugging extensions 40 #define IA32_FEATURE_PSE 0x00000008 // page size extensions 41 #define IA32_FEATURE_TSC 0x00000010 // rdtsc instruction 42 #define IA32_FEATURE_MSR 0x00000020 // rdmsr/wrmsr instruction 43 #define IA32_FEATURE_PAE 0x00000040 // extended 3 level page table addressing 44 #define IA32_FEATURE_MCE 0x00000080 // machine check exception 45 #define IA32_FEATURE_CX8 0x00000100 // cmpxchg8b instruction 46 #define IA32_FEATURE_APIC 0x00000200 // local apic on chip 47 #define IA32_FEATURE_SEP 0x00000800 // SYSENTER/SYSEXIT 48 #define IA32_FEATURE_MTRR 0x00001000 // MTRR 49 #define IA32_FEATURE_PGE 0x00002000 // paging global bit 50 #define IA32_FEATURE_MCA 0x00004000 // machine check architecture 51 #define IA32_FEATURE_CMOV 0x00008000 // cmov instruction 52 #define IA32_FEATURE_PAT 0x00010000 // page attribute table 53 #define IA32_FEATURE_PSE36 0x00020000 // page size extensions with 4MB pages 54 #define IA32_FEATURE_PSN 0x00040000 // processor serial number 55 #define IA32_FEATURE_CLFSH 0x00080000 // cflush instruction 56 #define IA32_FEATURE_DS 0x00200000 // debug store 57 #define IA32_FEATURE_ACPI 0x00400000 // thermal monitor and clock ctrl 58 #define IA32_FEATURE_MMX 0x00800000 // mmx instructions 59 #define IA32_FEATURE_FXSR 0x01000000 // FXSAVE/FXRSTOR instruction 60 #define IA32_FEATURE_SSE 0x02000000 // SSE 61 #define IA32_FEATURE_SSE2 0x04000000 // SSE2 62 #define IA32_FEATURE_SS 0x08000000 // self snoop 63 #define IA32_FEATURE_HTT 0x10000000 // hyperthreading 64 #define IA32_FEATURE_TM 0x20000000 // thermal monitor 65 #define IA32_FEATURE_PBE 0x80000000 // pending break enable 66 67 // x86 features from cpuid eax 1, ecx register 68 #define IA32_FEATURE_EXT_SSE3 0x00000001 // SSE3 69 #define IA32_FEATURE_EXT_MONITOR 0x00000008 // MONITOR/MWAIT 70 #define IA32_FEATURE_EXT_DSCPL 0x00000010 // CPL qualified debug store 71 #define IA32_FEATURE_EXT_EST 0x00000080 // speedstep 72 #define IA32_FEATURE_EXT_TM2 0x00000100 // thermal monitor 2 73 #define IA32_FEATURE_EXT_CNXTID 0x00000400 // L1 context ID 74 75 // x86 features from cpuid eax 0x80000001, edx register (AMD) 76 // only care about the ones that are unique to this register 77 #define IA32_FEATURE_AMD_EXT_SYSCALL (1 << 11) // SYSCALL/SYSRET 78 #define IA32_FEATURE_AMD_EXT_NX (1 << 20) // no execute bit 79 #define IA32_FEATURE_AMD_EXT_MMXEXT (1 << 22) // mmx extensions 80 #define IA32_FEATURE_AMD_EXT_FFXSR (1 << 25) // fast FXSAVE/FXRSTOR 81 #define IA32_FEATURE_AMD_EXT_RDTSCP (1 << 27) // rdtscp instruction 82 #define IA32_FEATURE_AMD_EXT_LONG (1 << 29) // long mode 83 #define IA32_FEATURE_AMD_EXT_3DNOWEXT (1 << 30) // 3DNow! extensions 84 #define IA32_FEATURE_AMD_EXT_3DNOW (1 << 31) // 3DNow! 85 86 // cr4 flags 87 #define IA32_CR4_PAE (1UL << 5) 88 #define IA32_CR4_GLOBAL_PAGES (1UL << 7) 89 90 // Memory type ranges 91 #define IA32_MTR_UNCACHED 0 92 #define IA32_MTR_WRITE_COMBINING 1 93 #define IA32_MTR_WRITE_THROUGH 4 94 #define IA32_MTR_WRITE_PROTECTED 5 95 #define IA32_MTR_WRITE_BACK 6 96 97 98 // iframe types 99 #define IFRAME_TYPE_SYSCALL 0x1 100 #define IFRAME_TYPE_OTHER 0x2 101 #define IFRAME_TYPE_MASK 0xf 102 103 104 #ifndef _ASSEMBLER 105 106 struct X86PagingStructures; 107 108 109 typedef struct x86_mtrr_info { 110 uint64 base; 111 uint64 size; 112 uint8 type; 113 } x86_mtrr_info; 114 115 typedef struct x86_optimized_functions { 116 void (*memcpy)(void* dest, const void* source, size_t count); 117 void* memcpy_end; 118 void (*memset)(void* dest, int value, size_t count); 119 void* memset_end; 120 } x86_optimized_functions; 121 122 typedef struct x86_cpu_module_info { 123 module_info info; 124 uint32 (*count_mtrrs)(void); 125 void (*init_mtrrs)(void); 126 127 void (*set_mtrr)(uint32 index, uint64 base, uint64 length, 128 uint8 type); 129 status_t (*get_mtrr)(uint32 index, uint64* _base, uint64* _length, 130 uint8* _type); 131 void (*set_mtrrs)(uint8 defaultType, const x86_mtrr_info* infos, 132 uint32 count); 133 134 void (*get_optimized_functions)(x86_optimized_functions* functions); 135 } x86_cpu_module_info; 136 137 138 struct tss { 139 uint16 prev_task; 140 uint16 unused0; 141 uint32 sp0; 142 uint32 ss0; 143 uint32 sp1; 144 uint32 ss1; 145 uint32 sp2; 146 uint32 ss2; 147 uint32 cr3; 148 uint32 eip, eflags, eax, ecx, edx, ebx, esp, ebp, esi, edi; 149 uint32 es, cs, ss, ds, fs, gs; 150 uint32 ldt_seg_selector; 151 uint16 unused1; 152 uint16 io_map_base; 153 }; 154 155 struct iframe { 156 uint32 type; // iframe type 157 uint32 gs; 158 uint32 fs; 159 uint32 es; 160 uint32 ds; 161 uint32 edi; 162 uint32 esi; 163 uint32 ebp; 164 uint32 esp; 165 uint32 ebx; 166 uint32 edx; 167 uint32 ecx; 168 uint32 eax; 169 uint32 orig_eax; 170 uint32 orig_edx; 171 uint32 vector; 172 uint32 error_code; 173 uint32 eip; 174 uint32 cs; 175 uint32 flags; 176 177 // user_esp and user_ss are only present when the iframe is a userland 178 // iframe (IFRAME_IS_USER()). A kernel iframe is shorter. 179 uint32 user_esp; 180 uint32 user_ss; 181 }; 182 183 struct vm86_iframe { 184 uint32 type; // iframe type 185 uint32 __null_gs; 186 uint32 __null_fs; 187 uint32 __null_es; 188 uint32 __null_ds; 189 uint32 edi; 190 uint32 esi; 191 uint32 ebp; 192 uint32 __kern_esp; 193 uint32 ebx; 194 uint32 edx; 195 uint32 ecx; 196 uint32 eax; 197 uint32 orig_eax; 198 uint32 orig_edx; 199 uint32 vector; 200 uint32 error_code; 201 uint32 eip; 202 uint16 cs, __csh; 203 uint32 flags; 204 uint32 esp; 205 uint16 ss, __ssh; 206 207 /* vm86 mode specific part */ 208 uint16 es, __esh; 209 uint16 ds, __dsh; 210 uint16 fs, __fsh; 211 uint16 gs, __gsh; 212 }; 213 214 #define IFRAME_IS_USER(f) ((f)->cs == USER_CODE_SEG \ 215 || ((f)->flags & 0x20000) != 0) 216 #define IFRAME_IS_VM86(f) (((f)->flags & 0x20000) != 0) 217 218 // features 219 enum x86_feature_type { 220 FEATURE_COMMON = 0, // cpuid eax=1, ecx register 221 FEATURE_EXT, // cpuid eax=1, edx register 222 FEATURE_EXT_AMD, // cpuid eax=0x80000001, edx register (AMD) 223 224 FEATURE_NUM 225 }; 226 227 enum x86_vendors { 228 VENDOR_INTEL = 0, 229 VENDOR_AMD, 230 VENDOR_CYRIX, 231 VENDOR_UMC, 232 VENDOR_NEXGEN, 233 VENDOR_CENTAUR, 234 VENDOR_RISE, 235 VENDOR_TRANSMETA, 236 VENDOR_NSC, 237 238 VENDOR_NUM, 239 VENDOR_UNKNOWN, 240 }; 241 242 typedef struct arch_cpu_info { 243 // saved cpu info 244 enum x86_vendors vendor; 245 uint32 feature[FEATURE_NUM]; 246 char model_name[49]; 247 const char* vendor_name; 248 int type; 249 int family; 250 int extended_family; 251 int stepping; 252 int model; 253 int extended_model; 254 255 struct X86PagingStructures* active_paging_structures; 256 257 uint32 dr6; // temporary storage for debug registers (cf. 258 uint32 dr7; // x86_exit_user_debug_at_kernel_entry()) 259 260 // local TSS for this cpu 261 struct tss tss; 262 struct tss double_fault_tss; 263 } arch_cpu_info; 264 265 #ifdef __cplusplus 266 extern "C" { 267 #endif 268 269 #define nop() __asm__ ("nop"::) 270 271 struct arch_thread; 272 273 void __x86_setup_system_time(uint32 conversionFactor, 274 uint32 conversionFactorNsecs, bool conversionFactorNsecsShift); 275 void x86_context_switch(struct arch_thread* oldState, 276 struct arch_thread* newState); 277 void x86_userspace_thread_exit(void); 278 void x86_end_userspace_thread_exit(void); 279 void x86_enter_userspace(addr_t entry, addr_t stackTop); 280 void x86_swap_pgdir(uint32 newPageDir); 281 void i386_set_tss_and_kstack(addr_t kstack); 282 void i386_fnsave(void* fpuState); 283 void i386_fxsave(void* fpuState); 284 void i386_frstor(const void* fpuState); 285 void i386_fxrstor(const void* fpuState); 286 void i386_fnsave_swap(void* oldFpuState, const void* newFpuState); 287 void i386_fxsave_swap(void* oldFpuState, const void* newFpuState); 288 uint32 x86_read_ebp(); 289 uint32 x86_read_cr0(); 290 void x86_write_cr0(uint32 value); 291 uint32 x86_read_cr4(); 292 void x86_write_cr4(uint32 value); 293 uint64 x86_read_msr(uint32 registerNumber); 294 void x86_write_msr(uint32 registerNumber, uint64 value); 295 void x86_set_task_gate(int32 cpu, int32 n, int32 segment); 296 void* x86_get_idt(int32 cpu); 297 uint32 x86_count_mtrrs(void); 298 void x86_set_mtrr(uint32 index, uint64 base, uint64 length, uint8 type); 299 status_t x86_get_mtrr(uint32 index, uint64* _base, uint64* _length, 300 uint8* _type); 301 void x86_set_mtrrs(uint8 defaultType, const x86_mtrr_info* infos, 302 uint32 count); 303 bool x86_check_feature(uint32 feature, enum x86_feature_type type); 304 void* x86_get_double_fault_stack(int32 cpu, size_t* _size); 305 int32 x86_double_fault_get_cpu(void); 306 void x86_double_fault_exception(struct iframe* frame); 307 void x86_page_fault_exception_double_fault(struct iframe* frame); 308 309 310 #define read_cr3(value) \ 311 __asm__("movl %%cr3,%0" : "=r" (value)) 312 313 #define write_cr3(value) \ 314 __asm__("movl %0,%%cr3" : : "r" (value)) 315 316 #define read_dr3(value) \ 317 __asm__("movl %%dr3,%0" : "=r" (value)) 318 319 #define write_dr3(value) \ 320 __asm__("movl %0,%%dr3" : : "r" (value)) 321 322 #define invalidate_TLB(va) \ 323 __asm__("invlpg (%0)" : : "r" (va)) 324 325 #define wbinvd() \ 326 __asm__("wbinvd") 327 328 #define out8(value,port) \ 329 __asm__ ("outb %%al,%%dx" : : "a" (value), "d" (port)) 330 331 #define out16(value,port) \ 332 __asm__ ("outw %%ax,%%dx" : : "a" (value), "d" (port)) 333 334 #define out32(value,port) \ 335 __asm__ ("outl %%eax,%%dx" : : "a" (value), "d" (port)) 336 337 #define in8(port) ({ \ 338 uint8 _v; \ 339 __asm__ volatile ("inb %%dx,%%al" : "=a" (_v) : "d" (port)); \ 340 _v; \ 341 }) 342 343 #define in16(port) ({ \ 344 uint16 _v; \ 345 __asm__ volatile ("inw %%dx,%%ax":"=a" (_v) : "d" (port)); \ 346 _v; \ 347 }) 348 349 #define in32(port) ({ \ 350 uint32 _v; \ 351 __asm__ volatile ("inl %%dx,%%eax":"=a" (_v) : "d" (port)); \ 352 _v; \ 353 }) 354 355 #define out8_p(value,port) \ 356 __asm__ ("outb %%al,%%dx\n" \ 357 "\tjmp 1f\n" \ 358 "1:\tjmp 1f\n" \ 359 "1:" : : "a" (value), "d" (port)) 360 361 #define in8_p(port) ({ \ 362 uint8 _v; \ 363 __asm__ volatile ("inb %%dx,%%al\n" \ 364 "\tjmp 1f\n" \ 365 "1:\tjmp 1f\n" \ 366 "1:" : "=a" (_v) : "d" (port)); \ 367 _v; \ 368 }) 369 370 extern segment_descriptor* gGDT; 371 372 373 #ifdef __cplusplus 374 } // extern "C" { 375 #endif 376 377 #endif // !_ASSEMBLER 378 379 #endif /* _KERNEL_ARCH_x86_CPU_H */ 380