Skip to content

Commit 0b6b9b5

Browse files
add some more leaves. Likely done with this issue for now until APIC works.
1 parent 344c87a commit 0b6b9b5

File tree

1 file changed

+76
-20
lines changed

1 file changed

+76
-20
lines changed

mythril/src/emulate/cpuid.rs

Lines changed: 76 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -8,27 +8,25 @@ use bitflags::_core::num::flt2dec::to_shortest_exp_str;
88
use crate::apic::get_local_apic;
99
use crate::vcpu::VCpu;
1010

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

2329

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

3331

3432

@@ -43,13 +41,43 @@ fn get_cpu_id_result(vcpu: &vcpu::VCpu, eax_in: u32, ecx_in: u32) -> CpuIdResult
4341

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

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

84139
bitfield! {
85140
pub struct FeatureInformationECX(u32);
141+
impl Debug;
86142
//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;
143+
xsave, _: 26;
144+
hypervissor, _: 31;
89145
}
90146

91147
bitfield! {
92148
pub struct FeatureInformationEDX(u32);
149+
impl Debug;
93150
//there are a lot of features here, so only add the ones we care about for now.
94-
mtrr, _: 13,12;
151+
mtrr, _: 12;
95152
}
96153

97154
fn cpuid_model_family_stepping(actual: CpuIdResult) -> CpuIdResult {
@@ -151,7 +208,6 @@ pub fn emulate_cpuid(
151208
let ecx = guest_cpu.rcx as u32;
152209
let mut res = get_cpu_id_result(vcpu, eax, ecx);
153210

154-
155211
guest_cpu.rax = res.eax as u64 | (guest_cpu.rax & 0xffffffff00000000);
156212
guest_cpu.rbx = res.ebx as u64 | (guest_cpu.rbx & 0xffffffff00000000);
157213
guest_cpu.rcx = res.ecx as u64 | (guest_cpu.rcx & 0xffffffff00000000);

0 commit comments

Comments
 (0)