Skip to content

Commit d51e1ae

Browse files
refactored cpuid_model_family_stepping
1 parent 1374639 commit d51e1ae

File tree

2 files changed

+69
-50
lines changed

2 files changed

+69
-50
lines changed

mythril/src/emulate/cpuid.rs

Lines changed: 68 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use core::convert::TryInto;
66
use bitfield::bitfield;
77
use bitflags::_core::num::flt2dec::to_shortest_exp_str;
88
use crate::apic::get_local_apic;
9+
use crate::vcpu::VCpu;
910

1011
//Used https://c9x.me/x86/html/file_module_x86_id_45.html as guid for implementing this.
1112
const CPUID_NAME: u32 = 0;
@@ -28,25 +29,7 @@ const MAX_CPUID_INPUT: u32 = 0x80000004;
2829
//
2930
// }
3031

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-
}
4132

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-
}
5033

5134

5235
fn get_cpu_id_result(vcpu: &vcpu::VCpu, eax_in: u32, ecx_in: u32) -> CpuIdResult {
@@ -59,33 +42,8 @@ fn get_cpu_id_result(vcpu: &vcpu::VCpu, eax_in: u32, ecx_in: u32) -> CpuIdResult
5942
);
6043

6144
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-
}
45+
CPUID_NAME => cpuid_name(vcpu, actual),
46+
CPUID_MODEL_FAMILY_STEPPING => cpuid_model_family_stepping(actual)
8947
INTEL_CORE_CACHE_TOPOLOGY => {
9048
let core_cpus = vcpu.vm.read().config.cpus();
9149

@@ -103,7 +61,71 @@ fn get_cpu_id_result(vcpu: &vcpu::VCpu, eax_in: u32, ecx_in: u32) -> CpuIdResult
10361
}
10462
}
10563

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

135-
<<<<<<< HEAD
136157
// Hide hypervisor feature
137158
res.ecx &= !(1 << 31);
138159

139160
// Hide TSC deadline timer
140161
res.ecx &= !(1 << 24);
141-
=======
142-
>>>>>>> handle CPUID_MODEL_FAMILY_STEPPING
143162
}
144163

145164
guest_cpu.rax = res.eax as u64 | (guest_cpu.rax & 0xffffffff00000000);

mythril/src/vcpu.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ pub struct VCpu {
9494
pub local_apic: virtdev::lapic::LocalApic,
9595
pending_interrupts: BTreeMap<u8, InjectedInterruptType>,
9696
stack: Vec<u8>,
97-
vcpu_apic
97+
vcpu_apic_id: usize
9898
}
9999

100100
impl VCpu {

0 commit comments

Comments
 (0)