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