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 void write_ds(unsigned val) 66 { 67 asm ("mov %0, %%ds" : : "rm"(val) : "memory"); 68 } 69 70 static inline void write_es(unsigned val) 71 { 72 asm ("mov %0, %%es" : : "rm"(val) : "memory"); 73 } 74 75 static inline void write_ss(unsigned val) 76 { 77 asm ("mov %0, %%ss" : : "rm"(val) : "memory"); 78 } 79 80 static inline void write_fs(unsigned val) 81 { 82 asm ("mov %0, %%fs" : : "rm"(val) : "memory"); 83 } 84 85 static inline void write_gs(unsigned val) 86 { 87 asm ("mov %0, %%gs" : : "rm"(val) : "memory"); 88 } 89 90 static inline u64 rdmsr(u32 index) 91 { 92 u32 a, d; 93 asm volatile ("rdmsr" : "=a"(a), "=d"(d) : "c"(index) : "memory"); 94 return a | ((u64)d << 32); 95 } 96 97 static inline void wrmsr(u32 index, u64 val) 98 { 99 u32 a = val, d = val >> 32; 100 asm volatile ("wrmsr" : : "a"(a), "d"(d), "c"(index) : "memory"); 101 } 102 103 static inline uint64_t rdpmc(uint32_t index) 104 { 105 uint32_t a, d; 106 asm volatile ("rdpmc" : "=a"(a), "=d"(d) : "c"(index)); 107 return a | ((uint64_t)d << 32); 108 } 109 110 static inline void write_cr0(ulong val) 111 { 112 asm volatile ("mov %0, %%cr0" : : "r"(val) : "memory"); 113 } 114 115 static inline ulong read_cr0(void) 116 { 117 ulong val; 118 asm volatile ("mov %%cr0, %0" : "=r"(val) : : "memory"); 119 return val; 120 } 121 122 static inline void write_cr2(ulong val) 123 { 124 asm volatile ("mov %0, %%cr2" : : "r"(val) : "memory"); 125 } 126 127 static inline ulong read_cr2(void) 128 { 129 ulong val; 130 asm volatile ("mov %%cr2, %0" : "=r"(val) : : "memory"); 131 return val; 132 } 133 134 static inline void write_cr3(ulong val) 135 { 136 asm volatile ("mov %0, %%cr3" : : "r"(val) : "memory"); 137 } 138 139 static inline ulong read_cr3(void) 140 { 141 ulong val; 142 asm volatile ("mov %%cr3, %0" : "=r"(val) : : "memory"); 143 return val; 144 } 145 146 static inline void write_cr4(ulong val) 147 { 148 asm volatile ("mov %0, %%cr4" : : "r"(val) : "memory"); 149 } 150 151 static inline ulong read_cr4(void) 152 { 153 ulong val; 154 asm volatile ("mov %%cr4, %0" : "=r"(val) : : "memory"); 155 return val; 156 } 157 158 static inline void write_cr8(ulong val) 159 { 160 asm volatile ("mov %0, %%cr8" : : "r"(val) : "memory"); 161 } 162 163 static inline ulong read_cr8(void) 164 { 165 ulong val; 166 asm volatile ("mov %%cr8, %0" : "=r"(val) : : "memory"); 167 return val; 168 } 169 170 static inline void lgdt(const struct descriptor_table_ptr *ptr) 171 { 172 asm volatile ("lgdt %0" : : "m"(*ptr)); 173 } 174 175 static inline void sgdt(struct descriptor_table_ptr *ptr) 176 { 177 asm volatile ("sgdt %0" : "=m"(*ptr)); 178 } 179 180 static inline void lidt(const struct descriptor_table_ptr *ptr) 181 { 182 asm volatile ("lidt %0" : : "m"(*ptr)); 183 } 184 185 static inline void sidt(struct descriptor_table_ptr *ptr) 186 { 187 asm volatile ("sidt %0" : "=m"(*ptr)); 188 } 189 190 static inline void lldt(unsigned val) 191 { 192 asm volatile ("lldt %0" : : "rm"(val)); 193 } 194 195 static inline u16 sldt(void) 196 { 197 u16 val; 198 asm volatile ("sldt %0" : "=rm"(val)); 199 return val; 200 } 201 202 static inline void ltr(u16 val) 203 { 204 asm volatile ("ltr %0" : : "rm"(val)); 205 } 206 207 static inline u16 str(void) 208 { 209 u16 val; 210 asm volatile ("str %0" : "=rm"(val)); 211 return val; 212 } 213 214 static inline void write_dr6(ulong val) 215 { 216 asm volatile ("mov %0, %%dr6" : : "r"(val) : "memory"); 217 } 218 219 static inline ulong read_dr6(void) 220 { 221 ulong val; 222 asm volatile ("mov %%dr6, %0" : "=r"(val)); 223 return val; 224 } 225 226 static inline void write_dr7(ulong val) 227 { 228 asm volatile ("mov %0, %%dr7" : : "r"(val) : "memory"); 229 } 230 231 static inline ulong read_dr7(void) 232 { 233 ulong val; 234 asm volatile ("mov %%dr7, %0" : "=r"(val)); 235 return val; 236 } 237 238 struct cpuid { u32 a, b, c, d; }; 239 240 static inline struct cpuid cpuid_indexed(u32 function, u32 index) 241 { 242 struct cpuid r; 243 asm volatile ("cpuid" 244 : "=a"(r.a), "=b"(r.b), "=c"(r.c), "=d"(r.d) 245 : "0"(function), "2"(index)); 246 return r; 247 } 248 249 static inline struct cpuid cpuid(u32 function) 250 { 251 return cpuid_indexed(function, 0); 252 } 253 254 static inline void pause(void) 255 { 256 asm volatile ("pause"); 257 } 258 259 static inline void cli(void) 260 { 261 asm volatile ("cli"); 262 } 263 264 static inline void sti(void) 265 { 266 asm volatile ("sti"); 267 } 268 269 static inline unsigned long long rdtsc() 270 { 271 long long r; 272 273 #ifdef __x86_64__ 274 unsigned a, d; 275 276 asm volatile ("rdtsc" : "=a"(a), "=d"(d)); 277 r = a | ((long long)d << 32); 278 #else 279 asm volatile ("rdtsc" : "=A"(r)); 280 #endif 281 return r; 282 } 283 284 static inline void wrtsc(u64 tsc) 285 { 286 unsigned a = tsc, d = tsc >> 32; 287 288 asm volatile("wrmsr" : : "a"(a), "d"(d), "c"(0x10)); 289 } 290 291 static inline void irq_disable(void) 292 { 293 asm volatile("cli"); 294 } 295 296 static inline void irq_enable(void) 297 { 298 asm volatile("sti"); 299 } 300 301 static inline void invlpg(void *va) 302 { 303 asm volatile("invlpg (%0)" ::"r" (va) : "memory"); 304 } 305 #endif 306