灵符lingfu

ling-lang

↓ 0 downloads

Ling - The Omniglot Systems Language

Keywords systems, polyglot, ai, crypto, game
lingfu install ling-lang
LicenseApache-2.0 OR MIT
AuthorsLing Lin, Sanny Lin
READMECode / FilesVersionsDependency GraphDependentsSecurityBuildsSettings

Code / Files (995)

crates/ling-kernel/src/arch/x86_64/cpu.rs
use core::arch::asm;

pub unsafe fn halt() {
    asm!("hlt", options(nomem, nostack));
}

pub unsafe fn cli() {
    asm!("cli", options(nomem, nostack));
}

pub unsafe fn sti() {
    asm!("sti", options(nomem, nostack));
}

pub unsafe fn pause() {
    asm!("pause", options(nomem, nostack));
}

pub unsafe fn cpuid(eax: u32, ecx: u32) -> (u32, u32, u32, u32) {
    let a: u32;
    let bval: u32;
    let c: u32;
    let d: u32;
    asm!(
        "push rbx",
        "cpuid",
        "mov {b:e}, ebx",
        "pop rbx",
        inout("eax") eax => a,
        inout("ecx") ecx => c,
        out("edx") d,
        b = out(reg) bval,
        options(nomem, nostack)
    );
    (a, bval, c, d)
}

pub unsafe fn rdtsc() -> u64 {
    let lo: u32;
    let hi: u32;
    asm!("rdtsc", out("eax") lo, out("edx") hi, options(nomem, nostack));
    (lo as u64) | ((hi as u64) << 32)
}

pub unsafe fn read_cr2() -> u64 {
    let val: u64;
    asm!("mov {}, cr2", out(reg) val, options(nomem, nostack));
    val
}

pub unsafe fn read_cr3() -> u64 {
    let val: u64;
    asm!("mov {}, cr3", out(reg) val, options(nomem, nostack));
    val
}

pub unsafe fn read_cr0() -> u64 {
    let val: u64;
    asm!("mov {}, cr0", out(reg) val, options(nomem, nostack));
    val
}

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

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

pub unsafe fn int3() {
    asm!("int3", options(nomem, nostack));
}

pub unsafe fn read_msr(msr: u32) -> u64 {
    let lo: u32;
    let hi: u32;
    asm!("rdmsr", out("eax") lo, out("edx") hi, in("ecx") msr, options(nomem, nostack));
    (lo as u64) | ((hi as u64) << 32)
}

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

/// Restore RFLAGS saved by [`read_flags`] (the interrupt flag with it).
pub unsafe fn write_flags(flags: u64) {
    core::arch::asm!("push {0}", "popfq", in(reg) flags, options(nomem));
}

pub unsafe fn read_flags() -> u64 {
    let val: u64;
    asm!("pushfq; pop {}", out(reg) val, options(nomem, nostack));
    val
}

/// True if the CPU advertises RDRAND (CPUID.01H:ECX[30]). QEMU exposes it on
/// its default CPU models; real hardware since Ivy Bridge / Excavator.
pub unsafe fn has_rdrand() -> bool {
    let (_, _, ecx, _) = cpuid(1, 0);
    ecx & (1 << 30) != 0
}

/// One 64-bit hardware random word via RDRAND. The instruction sets CF=1 on
/// success; retry a few times per Intel's guidance, and return None if the
/// RNG is starved (extremely rare) or RDRAND is unsupported. This is the
/// kernel's real entropy source -- the CSPRNG seed the ed25519/TLS crypto
/// needs and that `users.rs`'s rdtsc-salt was explicitly a placeholder for.
pub unsafe fn rdrand64() -> Option<u64> {
    if !has_rdrand() {
        return None;
    }
    let mut attempts = 0;
    while attempts < 16 {
        let val: u64;
        let ok: u8;
        asm!(
            "rdrand {v}",
            "setc {c}",
            v = out(reg) val,
            c = out(reg_byte) ok,
            options(nomem, nostack),
        );
        if ok != 0 {
            return Some(val);
        }
        attempts += 1;
    }
    None
}

← Back to index