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