Phoenix
Object-oriented orthogonally persistent operating system
|
00001 /* 00002 * /phoenix/kernel/sys/arch/x86_64/cpu_instr.h 00003 * 00004 * This file is a part of Phoenix operating system. 00005 * Copyright (c) 2011-2012, Artyom Lebedev <artyom.lebedev@gmail.com> 00006 * All rights reserved. 00007 * See COPYING file for copyright details. 00008 */ 00009 00010 #ifndef CPU_INSTR_H_ 00011 #define CPU_INSTR_H_ 00012 00019 #ifdef AUTONOMOUS_LINKING 00020 namespace { 00021 #endif /* AUTONOMOUS_LINKING */ 00022 00023 namespace cpu { 00024 00025 inline u64 00026 bsf(u64 string) 00027 { 00028 u64 rc; 00029 00030 ASM ("bsfq %[string], %[rc]" : [rc]"=r"(rc) : [string]"r"(string)); 00031 return rc; 00032 } 00033 00034 inline u8 00035 inb(u16 port) 00036 { 00037 u8 value; 00038 00039 ASM ("inb %w[port], %[value]" : [value]"=a"(value) : [port]"Nd"(port)); 00040 return value; 00041 } 00042 00043 inline u16 00044 inw(u16 port) 00045 { 00046 u16 value; 00047 00048 ASM ("inw %w[port], %[value]" : [value]"=a"(value) : [port]"Nd"(port)); 00049 return value; 00050 } 00051 00052 inline u32 00053 inl(u16 port) 00054 { 00055 u32 value; 00056 00057 ASM ("inl %w[port], %[value]" : [value]"=a"(value) : [port]"Nd"(port)); 00058 return value; 00059 } 00060 00061 inline void 00062 outb(u16 port, u8 value) 00063 { 00064 ASM ("outb %b[value], %w[port]" : : [value]"a"(value), [port]"Nd"(port)); 00065 } 00066 00067 inline void 00068 outw(u16 port, u16 value) 00069 { 00070 ASM ("outw %w[value], %w[port]": : [value]"a"(value), [port]"Nd"(port)); 00071 00072 } 00073 00074 inline void 00075 outl(u16 port, u32 value) 00076 { 00077 ASM ("outl %[value], %w[port]" : : [value]"a"(value), [port]"Nd"(port)); 00078 } 00079 00080 inline void 00081 invlpg(vaddr_t va) 00082 { 00083 ASM ("invlpg %[va]" : : [va]"m"(*static_cast<u8 *>(reinterpret_cast<void *>(va)))); 00084 } 00085 00086 inline u64 00087 rcr0() 00088 { 00089 register u64 r; 00090 00091 ASM ("mov %%cr0, %[r]" : [r]"=r"(r)); 00092 return r; 00093 } 00094 00095 inline void 00096 wcr0(u64 x) 00097 { 00098 ASM ("mov %[x], %%cr0" : : [x]"r"(x)); 00099 } 00100 00101 inline u64 00102 rcr2() 00103 { 00104 register u64 r; 00105 00106 ASM ("mov %%cr2, %[r]" : [r]"=r"(r)); 00107 return r; 00108 } 00109 00110 inline void 00111 wcr2(u64 x) 00112 { 00113 ASM ("mov %[x], %%cr2" : : [x]"r"(x)); 00114 } 00115 00116 inline u64 00117 rcr3() 00118 { 00119 register u64 r; 00120 00121 ASM ("mov %%cr3, %[r]" : [r]"=r"(r)); 00122 return r; 00123 } 00124 00125 inline void 00126 wcr3(u64 x) 00127 { 00128 ASM ("mov %[x], %%cr3" : : [x]"r"(x)); 00129 } 00130 00131 inline u64 00132 rcr4() 00133 { 00134 register u64 r; 00135 00136 ASM ("mov %%cr4, %[r]" : [r]"=r"(r)); 00137 return r; 00138 } 00139 00140 inline void 00141 wcr4(u64 x) 00142 { 00143 ASM ("mov %[x], %%cr4" : : [x]"r"(x)); 00144 } 00145 00146 inline void 00147 cpuid(u32 op, u32 subop, u32 *eax, u32 *ebx, u32 *ecx, u32 *edx) 00148 { 00149 u32 _eax, _ebx, _ecx, _edx; 00150 ASM ( 00151 "cpuid" 00152 : "=a"(_eax), "=b"(_ebx), "=c"(_ecx), "=d"(_edx) 00153 : "a"(op), "c"(subop) 00154 ); 00155 if (eax) { 00156 *eax = _eax; 00157 } 00158 if (ebx) { 00159 *ebx = _ebx; 00160 } 00161 if (ecx) { 00162 *ecx = _ecx; 00163 } 00164 if (edx) { 00165 *edx = _edx; 00166 } 00167 } 00168 00169 inline u64 00170 rdtsc() 00171 { 00172 u64 rcL, rcH; 00173 00174 ASM ("rdtsc" : "=a"(rcL), "=d"(rcH)); 00175 return rcL | (rcH << 32); 00176 } 00177 00178 inline void 00179 hlt() 00180 { 00181 ASM("hlt"); 00182 } 00183 00184 inline void 00185 cli() 00186 { 00187 ASM("cli"); 00188 } 00189 00190 /* Pseudo instructions */ 00191 inline u64 00192 GetFlags() 00193 { 00194 u64 rc; 00195 ASM ( 00196 "pushfq\n" 00197 "popq %[flags]\n" 00198 : [flags]"=r"(rc) 00199 ); 00200 return rc; 00201 } 00202 00203 inline void 00204 SetFlags(u64 value) 00205 { 00206 ASM ( 00207 "pushq %[flags]\n" 00208 "popfq\n" 00209 : 00210 : [flags]"r"(value) 00211 ); 00212 } 00213 00214 inline void 00215 sti() 00216 { 00217 ASM("sti"); 00218 } 00219 00220 00221 inline void 00222 lgdt(void *p) 00223 { 00224 ASM ( 00225 "lgdt %[gdt]" 00226 : 00227 : [gdt]"m"(*static_cast<u8 *>(p)) 00228 ); 00229 } 00230 00231 inline void 00232 lidt(void *p) 00233 { 00234 ASM ( 00235 "lidt %[idt]" 00236 : 00237 : [idt]"m"(*static_cast<u8 *>(p)) 00238 ); 00239 } 00240 00241 inline void 00242 lldt(u16 sel) 00243 { 00244 ASM ( 00245 "lldt %[ldt]" 00246 : 00247 : [ldt]"r"(sel) 00248 ); 00249 } 00250 00251 inline void 00252 sgdt(void *p) 00253 { 00254 ASM ( 00255 "sgdt %[gdt]" 00256 : [gdt]"=m"(*static_cast<u8 *>(p)) 00257 ); 00258 } 00259 00260 inline void 00261 sidt(void *p) 00262 { 00263 ASM ( 00264 "sidt %[idt]" 00265 : [idt]"=m"(*static_cast<u8 *>(p)) 00266 ); 00267 } 00268 00269 inline u16 00270 sldt() 00271 { 00272 u16 sel; 00273 ASM ( 00274 "sldt %[ldt]" 00275 : [ldt]"=r"(sel) 00276 ); 00277 return sel; 00278 } 00279 00280 inline void 00281 ltr(u16 sel) 00282 { 00283 ASM ( 00284 "ltr %[sel]" 00285 : 00286 : [sel]"r"(sel) 00287 ); 00288 } 00289 00290 inline u16 00291 str() 00292 { 00293 u16 sel; 00294 ASM ( 00295 "str %[sel]" 00296 : [sel]"=&r"(sel) 00297 ); 00298 return sel; 00299 } 00300 00301 inline u64 00302 rdmsr(u32 msr) 00303 { 00304 u64 rcL, rcH; 00305 ASM ( 00306 "rdmsr" 00307 : "=a"(rcL), "=d"(rcH) 00308 : "c"(msr) 00309 ); 00310 return rcL | (rcH << 32); 00311 } 00312 00313 inline void 00314 wrmsr(u32 msr, u64 value) 00315 { 00316 ASM ( 00317 "wrmsr" 00318 : 00319 : "c"(msr), "a"(value & 0xffffffff), "d"(value >> 32) 00320 ); 00321 } 00322 00323 inline void 00324 sysenter() 00325 { 00326 ASM ("sysenter"); 00327 } 00328 00329 inline void 00330 sysexit(u32 eip, u32 esp) 00331 { 00332 ASM ( 00333 "sysexit" 00334 : 00335 : "d"(eip), "c"(esp) 00336 ); 00337 } 00338 00339 inline void 00340 pause() 00341 { 00342 ASM ("pause"); 00343 } 00344 00345 inline void 00346 lfence() 00347 { 00348 ASM ("lfence"); 00349 } 00350 00351 inline void 00352 sfence() 00353 { 00354 ASM ("sfence"); 00355 } 00356 00357 inline void 00358 mfence() 00359 { 00360 ASM ("mfence"); 00361 } 00362 00366 inline void 00367 Pause() 00368 { 00369 pause(); 00370 } 00371 00375 inline void Halt() __NORETURN; 00376 inline void 00377 Halt() 00378 { 00379 cli(); 00380 while (true) { 00381 hlt(); 00382 } 00383 } 00384 00391 inline bool 00392 DisableInterrupts() 00393 { 00394 bool ret = GetFlags() & cpu_reg::EFLAGS_IF; 00395 cli(); 00396 return ret; 00397 } 00398 00402 inline void 00403 EnableInterrupts() 00404 { 00405 sti(); 00406 } 00407 00408 } /* namespace cpu */ 00409 00410 #ifdef AUTONOMOUS_LINKING 00411 } 00412 #endif /* AUTONOMOUS_LINKING */ 00413 00414 #endif /* CPU_INSTR_H_ */