hardware 0.0.7

A no_std bare-metal hardware abstraction layer — all port I/O, memory and swap allocations are guarded at runtime. Do not consider this dependency stable before x.1.x
Documentation
pub(super) fn read_brand_string(out: &mut [u8; 48]) -> u8 {
    let mut pos = 0u8;
    for leaf in [0x80000002u32, 0x80000003, 0x80000004] {
        if let Some((a, b, c, d)) = crate::arch::shim::cpuid_count(leaf, 0) {
            for val in [a, b, c, d] {
                let bytes = val.to_le_bytes();
                for byte in bytes {
                    if (pos as usize) < 48 {
                        out[pos as usize] = byte;
                        pos += 1;
                    }
                }
            }
        }
    }
    while pos > 0 && (out[(pos - 1) as usize] == 0 || out[(pos - 1) as usize] == b' ') {
        pos -= 1;
    }
    pos
}

pub fn estimate_frequency() -> u64 {
    if let Some((denom, numer, crystal, _)) = crate::arch::shim::cpuid_count(0x15, 0) {
        if denom != 0 && numer != 0 {
            let crystal_hz = if crystal != 0 {
                crystal as u64
            } else {
                25_000_000u64
            };
            let tsc_hz = crystal_hz * (numer as u64) / (denom as u64);
            if tsc_hz > 100_000_000 {
                return tsc_hz;
            }
        }
    }

    if let Some(freq) = parse_frequency_from_brand() {
        return freq;
    }

    calibrate_tsc()
}

fn parse_frequency_from_brand() -> Option<u64> {
    let mut brand = [0u8; 48];
    let len = read_brand_string(&mut brand);
    if len == 0 {
        return None;
    }
    let s = &brand[..len as usize];

    let mut i = 0usize;
    while i < s.len() {
        if s[i] == b'@' {
            let mut j = i + 1;
            while j < s.len() && s[j] == b' ' {
                j += 1;
            }
            let start = j;
            let mut integer_part: u64 = 0;
            let mut frac_part: u64 = 0;
            let mut frac_digits: u32 = 0;
            let mut in_frac = false;
            while j < s.len() && (s[j].is_ascii_digit() || s[j] == b'.') {
                if s[j] == b'.' {
                    in_frac = true;
                } else if in_frac {
                    frac_part = frac_part * 10 + (s[j] - b'0') as u64;
                    frac_digits += 1;
                } else {
                    integer_part = integer_part * 10 + (s[j] - b'0') as u64;
                }
                j += 1;
            }
            if j == start {
                i += 1;
                continue;
            }
            let mut multiplier: u64 = 1_000_000;
            if j + 2 < s.len() && s[j] == b'G' && s[j + 1] == b'H' && s[j + 2] == b'z' {
                multiplier = 1_000_000_000;
            } else if j + 2 < s.len() && s[j] == b'M' && s[j + 1] == b'H' && s[j + 2] == b'z' {
                multiplier = 1_000_000;
            }
            let mut hz = integer_part * multiplier;
            if frac_digits > 0 {
                let mut div = 1u64;
                let mut d = 0u32;
                while d < frac_digits {
                    div *= 10;
                    d += 1;
                }
                hz += frac_part * multiplier / div;
            }
            if hz > 100_000_000 {
                return Some(hz);
            }
        }
        i += 1;
    }
    None
}

pub fn calibrate_tsc() -> u64 {
    0
}