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