1 #ifndef LIBCFLAT_PROCESSOR_H 2 #define LIBCFLAT_PROCESSOR_H 3 4 #include "libcflat.h" 5 #include <stdint.h> 6 7 #ifdef __x86_64__ 8 # define R "r" 9 # define W "q" 10 # define S "8" 11 #else 12 # define R "e" 13 # define W "l" 14 # define S "4" 15 #endif 16 17 #define X86_CR0_PE 0x00000001 18 #define X86_CR0_MP 0x00000002 19 #define X86_CR0_TS 0x00000008 20 #define X86_CR0_WP 0x00010000 21 #define X86_CR0_PG 0x80000000 22 #define X86_CR4_VMXE 0x00000001 23 #define X86_CR4_TSD 0x00000004 24 #define X86_CR4_DE 0x00000008 25 #define X86_CR4_PSE 0x00000010 26 #define X86_CR4_PAE 0x00000020 27 #define X86_CR4_PCIDE 0x00020000 28 #define X86_CR4_SMAP 0x00200000 29 30 #define X86_IA32_EFER 0xc0000080 31 #define X86_EFER_LMA (1UL << 8) 32 33 struct descriptor_table_ptr { 34 u16 limit; 35 ulong base; 36 } __attribute__((packed)); 37 38 static inline void barrier(void) 39 { 40 asm volatile ("" : : : "memory"); 41 } 42 43 static inline void clac(void) 44 { 45 asm volatile (".byte 0x0f, 0x01, 0xca" : : : "memory"); 46 } 47 48 static inline void stac(void) 49 { 50 asm volatile (".byte 0x0f, 0x01, 0xcb" : : : "memory"); 51 } 52 53 static inline u16 read_cs(void) 54 { 55 unsigned val; 56 57 asm ("mov %%cs, %0" : "=mr"(val)); 58 return val; 59 } 60 61 static inline u16 read_ds(void) 62 { 63 unsigned val; 64 65 asm ("mov %%ds, %0" : "=mr"(val)); 66 return val; 67 } 68 69 static inline u16 read_es(void) 70 { 71 unsigned val; 72 73 asm ("mov %%es, %0" : "=mr"(val)); 74 return val; 75 } 76 77 static inline u16 read_ss(void) 78 { 79 unsigned val; 80 81 asm ("mov %%ss, %0" : "=mr"(val)); 82 return val; 83 } 84 85 static inline u16 read_fs(void) 86 { 87 unsigned val; 88 89 asm ("mov %%fs, %0" : "=mr"(val)); 90 return val; 91 } 92 93 static inline u16 read_gs(void) 94 { 95 unsigned val; 96 97 asm ("mov %%gs, %0" : "=mr"(val)); 98 return val; 99 } 100 101 static inline unsigned long read_rflags(void) 102 { 103 unsigned long f; 104 asm ("pushf; pop %0\n\t" : "=rm"(f)); 105 return f; 106 } 107 108 static inline void write_ds(unsigned val) 109 { 110 asm ("mov %0, %%ds" : : "rm"(val) : "memory"); 111 } 112 113 static inline void write_es(unsigned val) 114 { 115 asm ("mov %0, %%es" : : "rm"(val) : "memory"); 116 } 117 118 static inline void write_ss(unsigned val) 119 { 120 asm ("mov %0, %%ss" : : "rm"(val) : "memory"); 121 } 122 123 static inline void write_fs(unsigned val) 124 { 125 asm ("mov %0, %%fs" : : "rm"(val) : "memory"); 126 } 127 128 static inline void write_gs(unsigned val) 129 { 130 asm ("mov %0, %%gs" : : "rm"(val) : "memory"); 131 } 132 133 static inline u64 rdmsr(u32 index) 134 { 135 u32 a, d; 136 asm volatile ("rdmsr" : "=a"(a), "=d"(d) : "c"(index) : "memory"); 137 return a | ((u64)d << 32); 138 } 139 140 static inline void wrmsr(u32 index, u64 val) 141 { 142 u32 a = val, d = val >> 32; 143 asm volatile ("wrmsr" : : "a"(a), "d"(d), "c"(index) : "memory"); 144 } 145 146 static inline uint64_t rdpmc(uint32_t index) 147 { 148 uint32_t a, d; 149 asm volatile ("rdpmc" : "=a"(a), "=d"(d) : "c"(index)); 150 return a | ((uint64_t)d << 32); 151 } 152 153 static inline void write_cr0(ulong val) 154 { 155 asm volatile ("mov %0, %%cr0" : : "r"(val) : "memory"); 156 } 157 158 static inline ulong read_cr0(void) 159 { 160 ulong val; 161 asm volatile ("mov %%cr0, %0" : "=r"(val) : : "memory"); 162 return val; 163 } 164 165 static inline void write_cr2(ulong val) 166 { 167 asm volatile ("mov %0, %%cr2" : : "r"(val) : "memory"); 168 } 169 170 static inline ulong read_cr2(void) 171 { 172 ulong val; 173 asm volatile ("mov %%cr2, %0" : "=r"(val) : : "memory"); 174 return val; 175 } 176 177 static inline void write_cr3(ulong val) 178 { 179 asm volatile ("mov %0, %%cr3" : : "r"(val) : "memory"); 180 } 181 182 static inline ulong read_cr3(void) 183 { 184 ulong val; 185 asm volatile ("mov %%cr3, %0" : "=r"(val) : : "memory"); 186 return val; 187 } 188 189 static inline void write_cr4(ulong val) 190 { 191 asm volatile ("mov %0, %%cr4" : : "r"(val) : "memory"); 192 } 193 194 static inline ulong read_cr4(void) 195 { 196 ulong val; 197 asm volatile ("mov %%cr4, %0" : "=r"(val) : : "memory"); 198 return val; 199 } 200 201 static inline void write_cr8(ulong val) 202 { 203 asm volatile ("mov %0, %%cr8" : : "r"(val) : "memory"); 204 } 205 206 static inline ulong read_cr8(void) 207 { 208 ulong val; 209 asm volatile ("mov %%cr8, %0" : "=r"(val) : : "memory"); 210 return val; 211 } 212 213 static inline void lgdt(const struct descriptor_table_ptr *ptr) 214 { 215 asm volatile ("lgdt %0" : : "m"(*ptr)); 216 } 217 218 static inline void sgdt(struct descriptor_table_ptr *ptr) 219 { 220 asm volatile ("sgdt %0" : "=m"(*ptr)); 221 } 222 223 static inline void lidt(const struct descriptor_table_ptr *ptr) 224 { 225 asm volatile ("lidt %0" : : "m"(*ptr)); 226 } 227 228 static inline void sidt(struct descriptor_table_ptr *ptr) 229 { 230 asm volatile ("sidt %0" : "=m"(*ptr)); 231 } 232 233 static inline void lldt(unsigned val) 234 { 235 asm volatile ("lldt %0" : : "rm"(val)); 236 } 237 238 static inline u16 sldt(void) 239 { 240 u16 val; 241 asm volatile ("sldt %0" : "=rm"(val)); 242 return val; 243 } 244 245 static inline void ltr(u16 val) 246 { 247 asm volatile ("ltr %0" : : "rm"(val)); 248 } 249 250 static inline u16 str(void) 251 { 252 u16 val; 253 asm volatile ("str %0" : "=rm"(val)); 254 return val; 255 } 256 257 static inline void write_dr6(ulong val) 258 { 259 asm volatile ("mov %0, %%dr6" : : "r"(val) : "memory"); 260 } 261 262 static inline ulong read_dr6(void) 263 { 264 ulong val; 265 asm volatile ("mov %%dr6, %0" : "=r"(val)); 266 return val; 267 } 268 269 static inline void write_dr7(ulong val) 270 { 271 asm volatile ("mov %0, %%dr7" : : "r"(val) : "memory"); 272 } 273 274 static inline ulong read_dr7(void) 275 { 276 ulong val; 277 asm volatile ("mov %%dr7, %0" : "=r"(val)); 278 return val; 279 } 280 281 struct cpuid { u32 a, b, c, d; }; 282 283 static inline struct cpuid cpuid_indexed(u32 function, u32 index) 284 { 285 struct cpuid r; 286 asm volatile ("cpuid" 287 : "=a"(r.a), "=b"(r.b), "=c"(r.c), "=d"(r.d) 288 : "0"(function), "2"(index)); 289 return r; 290 } 291 292 static inline struct cpuid cpuid(u32 function) 293 { 294 return cpuid_indexed(function, 0); 295 } 296 297 static inline void pause(void) 298 { 299 asm volatile ("pause"); 300 } 301 302 static inline void cli(void) 303 { 304 asm volatile ("cli"); 305 } 306 307 static inline void sti(void) 308 { 309 asm volatile ("sti"); 310 } 311 312 static inline unsigned long long rdtsc() 313 { 314 long long r; 315 316 #ifdef __x86_64__ 317 unsigned a, d; 318 319 asm volatile ("rdtsc" : "=a"(a), "=d"(d)); 320 r = a | ((long long)d << 32); 321 #else 322 asm volatile ("rdtsc" : "=A"(r)); 323 #endif 324 return r; 325 } 326 327 static inline void wrtsc(u64 tsc) 328 { 329 unsigned a = tsc, d = tsc >> 32; 330 331 asm volatile("wrmsr" : : "a"(a), "d"(d), "c"(0x10)); 332 } 333 334 static inline void irq_disable(void) 335 { 336 asm volatile("cli"); 337 } 338 339 static inline void irq_enable(void) 340 { 341 asm volatile("sti"); 342 } 343 344 static inline void invlpg(volatile void *va) 345 { 346 asm volatile("invlpg (%0)" ::"r" (va) : "memory"); 347 } 348 349 static inline void safe_halt(void) 350 { 351 asm volatile("sti; hlt"); 352 } 353 354 #ifdef __x86_64__ 355 static inline void write_rflags(u64 r) 356 { 357 asm volatile("push %0; popf\n\t" : : "q"(r) : "cc"); 358 } 359 #endif 360 361 #endif 362