Skip to content

Commit 4b3d324

Browse files
got some basic cpuid stuff working.
1 parent be47bfc commit 4b3d324

File tree

3 files changed

+70
-16
lines changed

3 files changed

+70
-16
lines changed

mythril/Cargo.lock

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mythril/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ serde_json = {version = "^1", default-features = false, features = ["alloc"] }
2828
spin = "0.5"
2929
ux = { version = "0.1.3", default-features = false }
3030
managed = { version = "0.8.0", features = ["map", "alloc"], default-features = false }
31+
bitfield = "0.13.2"
3132

3233
[dependencies.iced-x86]
3334
version = "1.8.0"

mythril/src/emulate/cpuid.rs

Lines changed: 62 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,88 @@
11
use crate::error::Result;
22
use crate::{vcpu, vmexit};
3+
use raw_cpuid::CpuIdResult;
4+
use arrayvec::ArrayVec;
5+
use core::convert::TryInto;
6+
use bitfield::bitfield;
37

48
//Used https://c9x.me/x86/html/file_module_x86_id_45.html as guid for implementing this.
59
const CPUID_NAME: u32 = 0;
610
const CPUID_MODEL_FAMILY_STEPPING: u32 = 1;
711
const CPUID_CACHE_TLB_INFO: u32 = 2;
8-
const INTEL_CORE_CACHE_TOPOLOGY : u32 = 4;
12+
const INTEL_CORE_CACHE_TOPOLOGY: u32 = 4;
913
const CPUID_BRAND_STRING_1: u32 = 0x80000002;
1014
const CPUID_BRAND_STRING_2: u32 = 0x80000003;
1115
const CPUID_BRAND_STRING_3: u32 = 0x80000004;
16+
const MAX_CPUID_INPUT: u32 = 0x80000004;
1217
//todo //CPUID leaves above 2 and below 80000000H are visible only when
1318
// // IA32_MISC_ENABLE[bit 22] has its default value of 0.
1419

1520

21+
//
22+
// bitfield! {
23+
// pub struct IntelCoreCacheTopologyEaxRes(u32)
24+
// impl Debug;
25+
// impl Copy;
26+
//
27+
// }
1628

17-
pub fn emulate_cpuid(
18-
vcpu: &mut vcpu::VCpu,
19-
guest_cpu: &mut vmexit::GuestCpuState,
20-
) -> Result<()> {
21-
let eax = guest_cpu.rax as u32;
29+
bitfield! {
30+
pub struct IntelTypeFamilyModelSteppingIDEaxRes(u32);
31+
impl Debug;
32+
stepping_id, _: 3,0;
33+
model,_:7,4;
34+
family_id,_:11,8;
35+
processor_type,_:13,12;
36+
extended_model_id,_:19,16;
37+
extended_family_id,_:27,20;
38+
}
39+
40+
fn get_cpu_id_result(vcpu: &vcpu::VCpu, eax: u32, ecx: u32) -> Option<CpuIdResult> {
41+
const NAME_CREATION_ERROR_MESSAGE: &'static str = "Somehow bytes was not actually a 12 element array";
2242

2343
match eax {
2444
CPUID_NAME => {
25-
if vcpu.vm.read().config.override_cpu_name(){
26-
todo!()
45+
if vcpu.vm.read().config.override_cpu_name() {
46+
let cpu_name = "MythrilCPU__";
47+
let bytes = cpu_name.chars().map(|char| char as u8).collect::<ArrayVec<[u8; 12]>>();
48+
let first_bytes: [u8; 4] = bytes[0..4].try_into().expect(NAME_CREATION_ERROR_MESSAGE);
49+
let second_bytes: [u8; 4] = bytes[4..8].try_into().expect(NAME_CREATION_ERROR_MESSAGE);
50+
let third_bytes: [u8; 4] = bytes[8..12].try_into().expect(NAME_CREATION_ERROR_MESSAGE);
51+
return Some(CpuIdResult {
52+
eax: MAX_CPUID_INPUT,
53+
ebx: u32::from_le_bytes(first_bytes),
54+
ecx: u32::from_le_bytes(second_bytes),
55+
edx: u32::from_le_bytes(third_bytes),
56+
});
2757
}
28-
},
29-
CPUID_MODEL_FAMILY_STEPPING => todo!(),
58+
}
59+
CPUID_MODEL_FAMILY_STEPPING => {
60+
61+
}
3062
INTEL_CORE_CACHE_TOPOLOGY => {
31-
_vcpu.vm.read().config.cpus()
63+
let core_cpus = vcpu.vm.read().config.cpus();
64+
65+
todo!()
66+
}
67+
CPUID_BRAND_STRING_1..=CPUID_BRAND_STRING_2 => {
68+
if vcpu.vm.read().config.override_cpu_name() { todo!("CPU Brand string not implemented yet") }
69+
return None;
3270
}
33-
CPUID_BRAND_STRING_1 => todo!(),
34-
CPUID_BRAND_STRING_2 => todo!(),
3571
_ => {
36-
// dbg!(eax);
37-
// todo!("If you are reading this then a invalid arg was passed to cpuid. In principle we should prob fault here or something, but this probably indicates a bug.")
72+
//TODO for code review. Idk how I feel about silently fallingback on real cpuid here.
73+
// I would perhaps prefer to put a todo!() and explicitly implement stuff.
74+
return None;
3875
}
39-
}
76+
};
77+
panic!()
78+
}
79+
80+
pub fn emulate_cpuid(
81+
vcpu: &mut vcpu::VCpu,
82+
guest_cpu: &mut vmexit::GuestCpuState,
83+
) -> Result<()> {
84+
let eax = guest_cpu.rax as u32;
85+
4086

4187
//FIXME: for now just use the actual cpuid
4288
let mut res = raw_cpuid::native_cpuid::cpuid_count(

0 commit comments

Comments
 (0)