Skip to content

Instantly share code, notes, and snippets.

@andelf
Created April 18, 2014 10:39
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save andelf/11036938 to your computer and use it in GitHub Desktop.
Save andelf/11036938 to your computer and use it in GitHub Desktop.
CPUID in Rust
#![feature(asm)]
use std::io;
fn cpuid(info: u32) -> (u32, u32, u32, u32) {
let (mut a, mut b, mut c, mut d) = (0,0,0,0);
unsafe {
asm!("mov $4, %eax
cpuid
mov %eax, $0
mov %ebx, $1
mov %ecx, $2
mov %edx, $3"
: "=r"(a), "=r"(b), "=r"(c), "=r"(d)
: "m"(info)
: "eax", "ebx", "ecx", "edx"
)
};
(a, b, c, d)
}
fn cpuid_0() -> (u32, ~str) {
let (high, b, c, d) = cpuid(0);
let mut ret = StrBuf::new();
io::extensions::u64_to_le_bytes(b as u64, 4, |v| unsafe { ret.push_bytes(v) } );
io::extensions::u64_to_be_bytes(d as u64, 4, |v| unsafe { ret.push_bytes(v) } );
io::extensions::u64_to_le_bytes(c as u64, 4, |v| unsafe { ret.push_bytes(v) } );
// unsafe { ret.push_bytes(v) }
// (&[b, c, d]).iter().map(|val| ));
println!("Vendor ID: {}", ret);
(high, ret.into_owned())
}
fn dump_feature_edx_1(edx: u32) {
let edx_flags = [
"fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
"cx8", "apic", "", "sep", "mtrr", "pge", "mca", "cmov",
"pat", "pse-36", "psn", "clfsh", "", "ds", "acpi", "mmx",
"fxsr", "sse", "sse2", "ss", "htt", "tm", "ia64", "pbe"];
for i in range(0, 32u) {
if edx & (1 << i) != 0 {
print!("{} ", edx_flags[i]);
}
}
println!("");
}
fn dump_feature_ecx_1(ecx: u32) {
let ecx_flags = [
"sse3", "pclmulqdq", "dtes64", "monitor", "ds-cpl", "vmx", "smx", "est",
"tm2", "ssse3", "cnxt-id", "", "fma", "cx16", "xtpr", "pdcm",
"", "pcid", "dca", "sse4.1", "sse4.2", "x2apic", "movbe", "popcnt",
"tsc-deadline", "aes", "xsave", "osxsave", "avx", "f16c", "rdrnd", "hypervisor"];
for i in range(0, 32u) {
if ecx & (1 << i) != 0 {
print!("{} ", ecx_flags[i]);
}
}
println!("");
}
fn dump_extended_feature_edx_7(ebx: u32) {
let ebx_flags = [
"fsgsbase", "", "", "bmi1", "hle", "avx2", "", "smep",
"bmi2", "erms", "invpcid", "rtm", "", "", "mpx", "",
"avx512f", "", "rdseed", "adx", "smap", "", "", "",
"", "", "avx512pf", "avx512er", "avx512cd", "sha", "", ""];
for i in range(0, 32u) {
if ebx & (1 << i) != 0 {
print!("{} ", ebx_flags[i]);
}
}
println!("");
}
fn cpuid_1() -> (u32, u32) {
let (a, b, c, d) = cpuid(1);
println!("Family: {}", (a & 0x0f00) >> 8);
println!("Model: {}", (a & 0xf0) >> 4);
println!("Stepping: {}", a & 0x0f);
println!("Processor Type: {}", (a & 0x2000) >> 12);
println!("Extended Model: {}", (a & 0x0f0000) >> 16);
println!("Extended Family: {}", (a & 0x0ff00000) >> 20);
println!("feature flags: {:032t} {:032t}", d, c);
print!("Feature: ");
dump_feature_edx_1(d);
dump_feature_ecx_1(c);
// println!("Extended Features: => {:032t}", b);
// dump_extended_feature_edx(b);
(d, c)
}
// ERROR?
fn cpuid_7() -> u32 {
let (_, b, _, _) = cpuid(7);
print!("Extended Features: ");
dump_extended_feature_edx_7(b);
b
}
fn processor_brand_string() -> ~str {
let (a, _, _, _) = cpuid(0x80000000);
if a < 0x80000004 {
fail!("unspported!");
}
let mut ret = StrBuf::new();
let (a, b, c, d) = cpuid(0x80000002);
(vec!(a,b,c,d)).iter().map(|&n| {
io::extensions::u64_to_le_bytes(n as u64, 4, |v| unsafe { ret.push_bytes(v) } )
}).last();
let (a, b, c, d) = cpuid(0x80000003);
(vec!(a,b,c,d)).iter().map(|&n| {
io::extensions::u64_to_le_bytes(n as u64, 4, |v| unsafe { ret.push_bytes(v) } )
}).last();
let (a, b, c, d) = cpuid(0x80000004);
(vec!(a,b,c,d)).iter().map(|&n| {
io::extensions::u64_to_le_bytes(n as u64, 4, |v| unsafe { ret.push_bytes(v) } )
}).last();
ret.into_owned()
}
fn main() {
println!("cpuid(0) -> {:?}", cpuid_0());
cpuid_1();
//cpuid_7();
println!("test => {}", cpuid(0x80000000));
println!("s => {:?}", processor_brand_string());
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment