// Inline asm wrappers. // // Userspace-callable: rdtsc, cpuid, svm_supported // Ring-0 stubs: read_cr3, write_cr3, vmload, vmsave, vmrun, rdmsr, wrmsr // these are here for when this code runs in a kernel context // Calling them from userspace will #GP or #UD /// Read the hardware timestamp counter (TSC) /// Used for timing guest memory access patterns (cache-timing side channels) #[inline(always)] pub fn rdtsc() -> u64 { let lo: u32; let hi: u32; unsafe { core::arch::asm!( "rdtsc", out("eax") lo, out("edx") hi, options(nomem, nostack, preserves_flags), ); } ((hi as u64) << 32) | lo as u64 } /// CPUID — leaf + subleaf, returns (eax, ebx, ecx, edx). /// rbx is LLVM-reserved so we save/restore it around the instruction. pub fn cpuid(leaf: u32, subleaf: u32) -> (u32, u32, u32, u32) { let (eax, ebx, ecx, edx): (u32, u32, u32, u32); unsafe { core::arch::asm!( "push rbx", "cpuid", "mov {ebx_out:e}, ebx", "pop rbx", inout("eax") leaf => eax, inout("ecx") subleaf => ecx, ebx_out = out(reg) ebx, out("edx") edx, options(nomem, nostack, preserves_flags), ); } (eax, ebx, ecx, edx) } /// Possible delete only used to check for AMD SVM /// Check whether the host CPU supports AMD SVM (CPUID 0x80000001 ECX bit 2). pub fn svm_supported() -> bool { let (_, _, ecx, _) = cpuid(0x8000_0001, 0); ecx & (1 << 2) != 0 } // All of these should fault at CPL > 0 (#GP or #UD). unsafe extern "C" { /// Read host CR3. Returns the physical address of the host PML4. pub fn read_cr3() -> u64; /// Write host CR3 — flushes all non-global TLB entries. pub fn write_cr3(cr3: u64); /// VMLOAD — loads guest state from the VMCB at the given physical address. AMD SVM. pub fn vmload(vmcb_pa: u64); /// VMSAVE — saves guest state back to the VMCB at the given physical address. AMD SVM. pub fn vmsave(vmcb_pa: u64); /// VMRUN — enters the guest. Does not return until a #VMEXIT occurs. AMD SVM. pub fn vmrun(vmcb_pa: u64); /// RDMSR — read model-specific register. pub fn rdmsr(msr: u32) -> u64; /// WRMSR — write model-specific register. pub fn wrmsr(msr: u32, val: u64); }