Skip to content

Commit e937d36

Browse files
refactored cpuid_model_family_stepping
1 parent ceaa8e8 commit e937d36

File tree

2 files changed

+69
-47
lines changed

2 files changed

+69
-47
lines changed

mythril/src/emulate/cpuid.rs

Lines changed: 68 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ use raw_cpuid::CpuIdResult;
44
use arrayvec::ArrayVec;
55
use core::convert::TryInto;
66
use bitfield::bitfield;
7-
use bitflags::_core::num::flt2dec::to_shortest_exp_str;
87
use crate::apic::get_local_apic;
8+
use crate::vcpu::VCpu;
99

1010
//Used https://c9x.me/x86/html/file_module_x86_id_45.html as guid for implementing this.
1111
const CPUID_NAME: u32 = 0;
@@ -28,25 +28,7 @@ const MAX_CPUID_INPUT: u32 = 0x80000004;
2828
//
2929
// }
3030

31-
bitfield! {
32-
pub struct IntelTypeFamilyModelSteppingIDEaxRes(u32);
33-
impl Debug;
34-
stepping_id, _: 3,0;
35-
model,_:7,4;
36-
family_id,_:11,8;
37-
processor_type,_:13,12;
38-
extended_model_id,_:19,16;
39-
extended_family_id,_:27,20;
40-
}
4131

42-
bitfield! {
43-
pub struct BrandCFlushMaxIDsInitialAPIC(u32);
44-
impl Debug;
45-
brand_idx, _: 7,0;
46-
cflush,_:15,8;
47-
max_processor_ids,_:23,16;
48-
apic_id,_:31,24;
49-
}
5032

5133

5234
fn get_cpu_id_result(vcpu: &vcpu::VCpu, eax_in: u32, ecx_in: u32) -> CpuIdResult {
@@ -59,33 +41,8 @@ fn get_cpu_id_result(vcpu: &vcpu::VCpu, eax_in: u32, ecx_in: u32) -> CpuIdResult
5941
);
6042

6143
match eax_in {
62-
CPUID_NAME => cpuid_name(vcpu, &mut actual),
63-
CPUID_MODEL_FAMILY_STEPPING => {
64-
let family_model_stepping = IntelTypeFamilyModelSteppingIDEaxRes(actual.eax);
65-
//we can change family_model_stepping, but for now just use actual.
66-
let eax = family_model_stepping.0;
67-
let mut brand_cflush_max_initial = BrandCFlushMaxIDsInitialAPIC(actual.ebx);
68-
brand_cflush_max_initial.set_apic_id(get_local_apic().id());//in principle this is redundant
69-
let ebx = brand_cflush_max_initial.0;
70-
let mut ecx = actual.ecx;
71-
let mut edx = actual.edx;
72-
// I would have made type safe bindings for this but then I saw how many fields there where...
73-
74-
// Disable MTRR
75-
edx &= !(1 << 12);
76-
77-
// Disable XSAVE
78-
ecx &= !(1 << 26);
79-
80-
// Hide hypervisor feature
81-
ecx &= !(1 << 31);
82-
CpuIdResult{
83-
eax,
84-
ebx,
85-
ecx,
86-
edx
87-
}
88-
}
44+
CPUID_NAME => cpuid_name(vcpu, actual),
45+
CPUID_MODEL_FAMILY_STEPPING => cpuid_model_family_stepping(actual)
8946
INTEL_CORE_CACHE_TOPOLOGY => {
9047
let core_cpus = vcpu.vm.read().config.cpus();
9148

@@ -103,7 +60,71 @@ fn get_cpu_id_result(vcpu: &vcpu::VCpu, eax_in: u32, ecx_in: u32) -> CpuIdResult
10360
}
10461
}
10562

106-
fn cpuid_name(vcpu: &VCpu, actual: &mut CpuIdResult) -> CpuIdResult {
63+
bitfield! {
64+
pub struct IntelTypeFamilyModelSteppingIDEaxRes(u32);
65+
impl Debug;
66+
stepping_id, _: 3,0;
67+
model,_:7,4;
68+
family_id,_:11,8;
69+
processor_type,_:13,12;
70+
extended_model_id,_:19,16;
71+
extended_family_id,_:27,20;
72+
}
73+
74+
bitfield! {
75+
pub struct BrandCFlushMaxIDsInitialAPIC(u32);
76+
impl Debug;
77+
brand_idx, _: 7,0;
78+
cflush,_:15,8;
79+
max_processor_ids,_:23,16;
80+
apic_id,_:31,24;
81+
}
82+
83+
bitfield! {
84+
pub struct FeatureInformationECX(u32);
85+
//there are a lot of features here, so only add the ones we care about for now.
86+
xsave, _: 27,26;
87+
hypervissor, _: 32,31;
88+
}
89+
90+
bitfield! {
91+
pub struct FeatureInformationEDX(u32);
92+
//there are a lot of features here, so only add the ones we care about for now.
93+
mtrr, _: 13,12;
94+
}
95+
96+
fn cpuid_model_family_stepping(actual: CpuIdResult) -> CpuIdResult {
97+
let family_model_stepping = IntelTypeFamilyModelSteppingIDEaxRes(actual.eax);
98+
//we can change family_model_stepping, but for now just use actual.
99+
let eax = family_model_stepping.0;
100+
let mut brand_cflush_max_initial = BrandCFlushMaxIDsInitialAPIC(actual.ebx);
101+
brand_cflush_max_initial.set_apic_id(todo!("Waiting on virtual APICs"));
102+
brand_cflush_max_initial.set_max_processor_ids(todo!("Waiting on virtual APICs"));
103+
let ebx = brand_cflush_max_initial.0;
104+
let mut features_ecx = FeatureInformationECX(actual.ecx);
105+
let mut features_edx = FeatureInformationEDX(actual.edx);
106+
// I would have made type safe bindings for this but then I saw how many fields there where...
107+
108+
// Disable MTRR
109+
features_edx.set_mtrr(0);
110+
111+
// Disable XSAVE
112+
// ecx &= !(1 << 26);
113+
features_ecx.set_xsave(0);
114+
115+
// Hide hypervisor feature
116+
features_ecx.set_hypervisor(0);
117+
let ecx = features_ecx.0;
118+
let edx = features_edx.0;
119+
CpuIdResult {
120+
eax,
121+
ebx,
122+
ecx,
123+
edx
124+
}
125+
}
126+
127+
fn cpuid_name(vcpu: &VCpu, actual: CpuIdResult) -> CpuIdResult {
107128
if vcpu.vm.read().config.override_cpu_name() {
108129
let cpu_name = "MythrilCPU__";
109130
let bytes = cpu_name.chars().map(|char| char as u8).collect::<ArrayVec<[u8; 12]>>();

mythril/src/vcpu.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ pub struct VCpu {
104104
pub local_apic: virtdev::lapic::LocalApic,
105105
pending_interrupts: BTreeMap<u8, InjectedInterruptType>,
106106
stack: &'static mut [u8; PER_CORE_HOST_STACK_SIZE],
107+
vcpu_apic_id: usize
107108
}
108109

109110
impl VCpu {

0 commit comments

Comments
 (0)