Phoenix
Object-oriented orthogonally persistent operating system
cpu_instr.h
Go to the documentation of this file.
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_ */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines