Skip to content

Commit 86e1d74

Browse files
add some more leaves. Likely done with this issue for now until APIC works.
1 parent e937d36 commit 86e1d74

File tree

1 file changed

+77
-19
lines changed

1 file changed

+77
-19
lines changed

mythril/src/emulate/cpuid.rs

Lines changed: 77 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -7,27 +7,25 @@ use bitfield::bitfield;
77
use crate::apic::get_local_apic;
88
use crate::vcpu::VCpu;
99

10-
//Used https://c9x.me/x86/html/file_module_x86_id_45.html as guid for implementing this.
1110
const CPUID_NAME: u32 = 0;
1211
const CPUID_MODEL_FAMILY_STEPPING: u32 = 1;
1312
const CPUID_CACHE_TLB_INFO: u32 = 2;
1413
const INTEL_CORE_CACHE_TOPOLOGY: u32 = 4;
14+
const THERMAL_AND_POWER_MANAGEMENT: u32 = 6;
15+
const STRUCTURED_EXTENDED_FEATURE_FLAGS: u32 = 7;
16+
const ARCHITECTURAL_PERFORMANCE: u32 = 0xA;
17+
const EXTENDED_TOPOLOGY_ENUMERATION: u32 = 0xB;
18+
const PROCESSOR_EXTENDED_STATE_ENUMERATION: u32 = 0xD;
19+
const V2_EXTENDED_TOPOLOGY_ENUMERATION: u32 = 0x1F;
20+
const EXTENDED_FUNCTION_CPUID_INFORMATION: u32 = 0x80000000;
1521
const CPUID_BRAND_STRING_1: u32 = 0x80000002;
1622
const CPUID_BRAND_STRING_2: u32 = 0x80000003;
1723
const CPUID_BRAND_STRING_3: u32 = 0x80000004;
18-
const MAX_CPUID_INPUT: u32 = 0x80000004;
24+
const MAX_CPUID_INPUT: u32 = 0x80000008;
1925
//todo //CPUID leaves above 2 and below 80000000H are visible only when
2026
// // IA32_MISC_ENABLE[bit 22] has its default value of 0.
2127

2228

23-
//
24-
// bitfield! {
25-
// pub struct IntelCoreCacheTopologyEaxRes(u32)
26-
// impl Debug;
27-
// impl Copy;
28-
//
29-
// }
30-
3129

3230

3331

@@ -42,13 +40,43 @@ fn get_cpu_id_result(vcpu: &vcpu::VCpu, eax_in: u32, ecx_in: u32) -> CpuIdResult
4240

4341
match eax_in {
4442
CPUID_NAME => cpuid_name(vcpu, actual),
45-
CPUID_MODEL_FAMILY_STEPPING => cpuid_model_family_stepping(actual)
46-
INTEL_CORE_CACHE_TOPOLOGY => {
47-
let core_cpus = vcpu.vm.read().config.cpus();
48-
49-
todo!()
43+
CPUID_MODEL_FAMILY_STEPPING => cpuid_model_family_stepping(actual),
44+
INTEL_CORE_CACHE_TOPOLOGY => intel_cache_topo(actual),
45+
THERMAL_AND_POWER_MANAGEMENT => {
46+
todo!("Portions of this output are per core, but presumably we don't support this. Additionally there is stuff about APIC timers here, also unsure if supported.")
47+
}
48+
STRUCTURED_EXTENDED_FEATURE_FLAGS => {
49+
// nothing here seems to suspicious so just return actual:
50+
actual
51+
}
52+
ARCHITECTURAL_PERFORMANCE => {
53+
// For now I assume performance counters are unsupported, but if one wanted
54+
// to support performance counters this would need to be handled here, and other places
55+
actual
56+
}
57+
EXTENDED_TOPOLOGY_ENUMERATION => {
58+
todo!("This basically requires APIC stuff to be done.")
5059
}
51-
CPUID_BRAND_STRING_1..=CPUID_BRAND_STRING_2 => {
60+
PROCESSOR_EXTENDED_STATE_ENUMERATION => {
61+
actual
62+
}
63+
// There are bunch more leaves after PROCESSOR_EXTENDED_STATE_ENUMERATION, however most of them seem unlikely to be used/ not relevant
64+
V2_EXTENDED_TOPOLOGY_ENUMERATION => {
65+
todo!("Requires APIC")
66+
}
67+
0x40000000..=0x4FFFFFFF=> {
68+
// these are software reserved.
69+
actual
70+
}
71+
EXTENDED_FUNCTION_CPUID_INFORMATION => {
72+
CpuIdResult{
73+
eax: MAX_CPUID_INPUT,
74+
ebx: 0,
75+
ecx: 0,
76+
edx: 0
77+
}
78+
}
79+
CPUID_BRAND_STRING_1..=CPUID_BRAND_STRING_3 => {
5280
if vcpu.vm.read().config.override_cpu_name() { todo!("CPU Brand string not implemented yet") }
5381
actual
5482
}
@@ -60,6 +88,33 @@ fn get_cpu_id_result(vcpu: &vcpu::VCpu, eax_in: u32, ecx_in: u32) -> CpuIdResult
6088
}
6189
}
6290

91+
bitfield! {
92+
pub struct IntelCoreCacheTopologyEaxRes(u32);
93+
impl Debug;
94+
cache_type,_:4,0;
95+
cache_level,_:7,5;
96+
self_init_cache_level,_:8;
97+
fully_associative,_:9;
98+
max_addressable_ids_logical,_:14,25;
99+
max_addressable_ids_physical,_:26,31;
100+
}
101+
102+
103+
104+
fn intel_cache_topo(mut actual: CpuIdResult) -> CpuIdResult {
105+
let mut cache_topo_eax = IntelCoreCacheTopologyEaxRes(actual.eax);
106+
cache_topo_eax.set_max_addressable_ids_logical(todo!("waiting on apics"));
107+
cache_topo_eax.set_max_addressable_ids_physical(todo!("waiting on apics"));
108+
let eax = cache_topo_eax.0;
109+
CpuIdResult {
110+
eax,
111+
//no changes should be required for these:
112+
ebx: actual.ebx,
113+
ecx: actual.ecx,
114+
edx: actual.edx
115+
}
116+
}
117+
63118
bitfield! {
64119
pub struct IntelTypeFamilyModelSteppingIDEaxRes(u32);
65120
impl Debug;
@@ -82,15 +137,17 @@ bitfield! {
82137

83138
bitfield! {
84139
pub struct FeatureInformationECX(u32);
140+
impl Debug;
85141
//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;
142+
xsave, _: 26;
143+
hypervissor, _: 31;
88144
}
89145

90146
bitfield! {
91147
pub struct FeatureInformationEDX(u32);
148+
impl Debug;
92149
//there are a lot of features here, so only add the ones we care about for now.
93-
mtrr, _: 13,12;
150+
mtrr, _: 12;
94151
}
95152

96153
fn cpuid_model_family_stepping(actual: CpuIdResult) -> CpuIdResult {
@@ -162,6 +219,7 @@ pub fn emulate_cpuid(
162219
res.edx = crate::percore::read_core_id().raw as u32;
163220
}
164221

222+
165223
guest_cpu.rax = res.eax as u64 | (guest_cpu.rax & 0xffffffff00000000);
166224
guest_cpu.rbx = res.ebx as u64 | (guest_cpu.rbx & 0xffffffff00000000);
167225
guest_cpu.rcx = res.ecx as u64 | (guest_cpu.rcx & 0xffffffff00000000);

0 commit comments

Comments
 (0)