moon-instructions 0.1.1

Windows Kernel Instructions
#![no_std]

pub mod vmx;

use moon_struct::{cpuid::CPUID, inner::KDESCRIPTOR};

#[macro_export]
macro_rules! debugbreak {
    () => {
        unsafe {
            core::arch::asm!("int 3");
        }
    };
}

use core::{arch::asm, ffi::c_void};

pub fn sidt(idt_info: *mut c_void) {
    unsafe {
        asm!(
            "sidt [rcx]",
            in("rcx") idt_info,
            options(nostack),
        );
    }
}

pub fn segment_limit(selector: u64) -> u64 {
    let mut result: u64;

    unsafe {
        asm!(
            "xor rax,rax",
            "lsl rax, rcx",
            out("rax") result,
            in("rcx") selector,
            options(nostack)
        );
    }

    result
}

pub fn write_xcr0(value: u64) {
    let low = value as u32;
    let high = (value >> 32) as u32;
    unsafe {
        asm!(
            "xsetbv",
            in("ecx") 0,
            in("eax") low,
            in("edx") high,
            options(nostack)
        );
    }
}

pub fn read_msr(msr: u32) -> u64 {
    let mut low: u32;
    let mut high: u32;

    unsafe {
        asm!(
            "rdmsr",
            in("ecx") msr,
            out("eax") low,
            out("edx") high,
            options(nostack)
        );
    }
    ((high as u64) << 32) | (low as u64)
}

pub fn write_msr(msr: u32, value: u64) {
    let low = value as u32;
    let high = (value >> 32) as u32;
    unsafe {
        asm!(
            "wrmsr",
            in("ecx") msr,
            in("eax") low,
            in("edx") high,
            options(nostack)
        );
    }
}

pub fn read_cr0() -> u64 {
    let mut result: u64;
    unsafe {
        asm!(
            "mov rax,cr0",
            out("rax") result,
            options(nostack)
        );
    }
    result
}

pub fn write_cr0(value: u64) {
    unsafe {
        asm!(
            "mov cr0,rcx",
            in("rcx") value,
            options(nostack)
        );
    }
}

pub fn read_cr3() -> u64 {
    let mut result: u64;
    unsafe {
        asm!(
            "xor rax,rax",
            "mov rax,cr3",
            out("rax") result,
            options(nostack)
        );
    }

    result
}

pub fn write_cr3(value: u64) {
    unsafe {
        asm!(
            "mov cr3,rcx",
            in("rcx") value,
            options(nostack)
        );
    }
}

pub fn read_cr4() -> u64 {
    let mut result: u64;
    unsafe {
        asm!(
            "xor rax,rax",
            "mov rax,cr4",
            out("rax") result,
            options(nostack)
        );
    }
    result
}

pub fn write_cr4(value: u64) {
    unsafe {
        asm!(
            "mov cr4,rcx",
            in("rcx") value,
            options(nostack)
        );
    }
}

pub fn read_cr8() -> u64 {
    let mut result: u64;
    unsafe {
        asm!(
            "xor rax,rax",
            "mov rax,cr8",
            out("rax") result,
            options(nostack)
        );
    }
    result
}

pub fn write_cr8(value: u64) {
    unsafe {
        asm!(
            "mov cr8,rcx",
            in("rcx") value,
            options(nostack)
        );
    }
}

pub fn lgdt(addr: &KDESCRIPTOR) {
    unsafe {
        asm!(
            "lgdt [rax+6]",
            in("rax") addr,
            options(nostack),
        );
    }
}

pub fn lidt(addr: &KDESCRIPTOR) {
    unsafe {
        asm!(
            "lidt [rax+6]",
            in("rax") addr,
            options(nostack),
        );
    }
}

pub fn stosq(destination: *mut u64, value: u64, count: u64) {
    unsafe {
        asm!(
            "rep stosq",
            inout("rdi") destination => _,
            in("rax") value,
            inout("rcx") count => _,
            options(nostack),
        );
    }
}

// find bit value eq 1 in binary range mask
pub fn bit_scan_forward64(index: *mut u32, mask: u64) {
    let _val: u64;
    unsafe {
        asm!(
            "bsf rax,rax",
            "mov [rcx],eax",
            inout("rax") mask => _val,
            in("rcx") index,
            options(nostack),
        );
    }
}

pub fn cpuidex(eax: u32, ecx: u32) -> CPUID {
    let mut result = CPUID::default();
    let r_eax: u32;
    let r_ebx: u32;
    let r_ecx: u32;
    let r_edx: u32;

    unsafe {
        asm!(
            "push rbx",
            "cpuid",
            "mov r8d, ebx",
            "pop rbx",
            inout("eax") eax => r_eax,
            inout("ecx") ecx => r_ecx,
            lateout("edx") r_edx,
            lateout("r8") r_ebx,
        );
    }
    result.eax = r_eax;
    result.ebx = r_ebx;
    result.ecx = r_ecx;
    result.edx = r_edx;
    result
}

// segement regeistry
pub fn read_cs() -> u64 {
    let mut result: u64;
    unsafe {
        asm!(
            "xor rax,rax",
            "mov rax,cs",
            out("rax") result,
            options(nostack)
        );
    }
    result
}

pub fn read_ds() -> u64 {
    let mut result: u64;
    unsafe {
        asm!(
            "xor rax,rax",
            "mov rax,ds",
            out("rax") result,
            options(nostack)
        );
    }
    result
}

pub fn read_es() -> u64 {
    let mut result: u64;
    unsafe {
        asm!(
            "xor rax,rax",
            "mov rax,es",
            out("rax") result,
            options(nostack)
        );
    }
    result
}

pub fn read_ss() -> u64 {
    let mut result: u64;
    unsafe {
        asm!(
            "xor rax,rax",
            "mov rax,ss",
            out("rax") result,
            options(nostack)
        );
    }
    result
}

pub fn read_fs() -> u64 {
    let mut result: u64;
    unsafe {
        asm!(
            "xor rax,rax",
            "mov rax,fs",
            out("rax") result,
            options(nostack)
        );
    }
    result
}

pub fn read_gs() -> u64 {
    let mut result: u64;
    unsafe {
        asm!(
            "xor rax,rax",
            "mov rax,gs",
            out("rax") result,
            options(nostack)
        );
    }
    result
}

pub fn read_gs_current_thread() -> u64 {
    let mut result: u64;
    unsafe {
        asm!(
            "xor rax,rax",
            "mov rax,gs:0x188",
            out("rax") result,
            options(nostack)
        );
    }
    result
}

pub fn write_rflags(value: u64) {
    unsafe {
        asm!(
            "push rcx",
            "popfq",
            in("rcx") value,
        );
    }
}

pub fn read_rflags() -> u64 {
    let mut result: u64;
    unsafe {
        asm!(
            "pushfq",
            "pop rax",
            out("rax") result,
        );
    }
    result
}