Skip to content

Commit 97bcec6

Browse files
impl cpuid_model_family_stepping
1 parent 479b515 commit 97bcec6

File tree

5 files changed

+58
-27
lines changed

5 files changed

+58
-27
lines changed

.mythril_githooks/pre-commit

Lines changed: 0 additions & 13 deletions
This file was deleted.

mythril/src/emulate/cpuid.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::error::Result;
22
use crate::vcpu::VCpu;
3+
use crate::virtdev::lapic::VirtualAPICID;
34
use crate::{vcpu, vmexit};
45
use arrayvec::ArrayVec;
56
use bitfield::bitfield;
@@ -142,15 +143,22 @@ bitfield! {
142143
mtrr, set_mtrr: 12;
143144
}
144145

145-
fn cpuid_model_family_stepping(actual: CpuIdResult) -> CpuIdResult {
146+
fn cpuid_model_family_stepping(cpu: &VCpu, actual: CpuIdResult) -> CpuIdResult {
146147
let family_model_stepping =
147148
IntelTypeFamilyModelSteppingIDEaxRes(actual.eax);
148149
//we can change family_model_stepping, but for now just use actual.
149150
let eax = family_model_stepping.0;
150151
let mut brand_cflush_max_initial = BrandCFlushMaxIDsInitialAPIC(actual.ebx);
151-
brand_cflush_max_initial.set_apic_id(todo!("Waiting on virtual APICs"));
152152
brand_cflush_max_initial
153-
.set_max_processor_ids(todo!("Waiting on virtual APICs"));
153+
.set_apic_id(cpu.local_apic.virtual_apic_id.0 as u32);
154+
let max =
155+
cpu.vm
156+
.virtual_ids
157+
.values()
158+
.fold(VirtualAPICID(0), |accum, this_id| {
159+
*if this_id.0 > accum.0 { this_id } else { accum }
160+
});
161+
brand_cflush_max_initial.set_max_processor_ids(max.0 as u32);
154162
let ebx = brand_cflush_max_initial.0;
155163
let mut features_ecx = FeatureInformationECX(actual.ecx);
156164
let mut features_edx = FeatureInformationEDX(actual.edx);

mythril/src/vcpu.rs

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,8 @@ pub fn mp_entry_point() -> ! {
4141
vm
4242
};
4343

44-
let mut vcpu = VCpu::new(vm.clone()).expect("Failed to create vcpu");
44+
let mut vcpu =
45+
VCpu::new(vm.clone(), core_id).expect("Failed to create vcpu");
4546

4647
let vm_id = vm.id;
4748
let is_vm_bsp = vm.config.bsp_id() == core_id;
@@ -102,17 +103,24 @@ impl VCpu {
102103
/// Note that the result must be `Pin`, as the `VCpu` pushes its own
103104
/// address on to the per-core host stack so it can be retrieved on
104105
/// VMEXIT.
105-
pub fn new(vm: Arc<VirtualMachine>) -> Result<Pin<Box<Self>>> {
106+
pub fn new(
107+
vm: Arc<VirtualMachine>,
108+
core_id: percore::CoreId,
109+
) -> Result<Pin<Box<Self>>> {
106110
let vmx = vmx::Vmx::enable()?;
107111
let vmcs = vmcs::Vmcs::new()?.activate(vmx)?;
108112

109113
// Allocate 1MB for host stack space
110114
let stack = vec![0u8; 1024 * 1024];
111115

116+
let virtual_core_id = vm.virtual_ids
117+
.get(&core_id)
118+
.expect("Couldn't find virtual core id. Something is broken when initing virtual_ids");
119+
112120
let mut vcpu = Box::pin(Self {
113121
vm,
114122
vmcs,
115-
local_apic: virtdev::lapic::LocalApic::new(),
123+
local_apic: virtdev::lapic::LocalApic::new(*virtual_core_id),
116124
stack,
117125
pending_interrupts: BTreeMap::new(),
118126
});

mythril/src/virtdev/lapic.rs

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,30 @@ impl TryFrom<u16> for ApicRegisterOffset {
103103
}
104104
}
105105

106-
#[derive(Default)]
106+
/// CPUID only returns APIC ID values up to 8 bits.
107+
/// This does raise the question of what AMD are
108+
/// going to do when they add more cores to threadripper.
109+
/// And also what Xeon Phi does.
110+
/// Apparently it does this:
111+
/// "The local APIC registers have expanded fields for
112+
/// the APIC ID, Logical APIC ID, and APIC Destination ID. "
113+
/// https://www.intel.com/content/dam/www/public/us/en/
114+
/// documents/product-briefs/xeon-phi
115+
/// -coprocessor-system-software-developers-guide.pdf
116+
///
117+
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
118+
pub struct VirtualAPICID(pub u8);
119+
107120
pub struct LocalApic {
108121
icr_destination: Option<u32>,
122+
pub virtual_apic_id: VirtualAPICID,
109123
}
110124

111125
impl LocalApic {
112-
pub fn new() -> Self {
126+
pub fn new(virtual_apic_id: VirtualAPICID) -> Self {
113127
LocalApic {
114128
icr_destination: None,
129+
virtual_apic_id,
115130
}
116131
}
117132

@@ -213,8 +228,7 @@ impl LocalApic {
213228
let offset = ApicRegisterOffset::try_from(offset)?;
214229
match offset {
215230
ApicRegisterOffset::Simple(ApicRegisterSimpleOffset::ApicId) => {
216-
// FIXME(alschwalm): we shouldn't really use the core id for this
217-
Ok(percore::read_core_id().raw)
231+
Ok(self.virtual_apic_id.0 as u32)
218232
}
219233
_ => Ok(0),
220234
}
@@ -248,6 +262,7 @@ impl LocalApic {
248262
}
249263
1 => {
250264
self.icr_destination = Some(value);
265+
todo!("make sure it is known that acr is value")
251266
}
252267
_ => unreachable!(),
253268
}

mythril/src/vm.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ use crate::percore;
1313
use crate::physdev;
1414
use crate::time;
1515
use crate::vcpu;
16+
use crate::virtdev::lapic::VirtualAPICID;
1617
use crate::virtdev::{
1718
self, DeviceEvent, DeviceInteraction, DeviceMap, Event, ResponseEventArray,
1819
};
@@ -324,7 +325,7 @@ impl VirtualMachineConfig {
324325
virtual_devices: DeviceMap::default(),
325326
physical_devices,
326327
memory,
327-
override_cpu_name: todo!(),
328+
override_cpu_name: true,
328329
})
329330
}
330331

@@ -396,6 +397,8 @@ pub struct VirtualMachine {
396397

397398
/// The number of vcpus that are up and waiting to start
398399
cpus_ready: AtomicU32,
400+
401+
pub virtual_ids: BTreeMap<percore::CoreId, VirtualAPICID>,
399402
}
400403

401404
impl VirtualMachine {
@@ -420,13 +423,22 @@ impl VirtualMachine {
420423
);
421424
}
422425

426+
let mut virutal_ids = BTreeMap::new();
427+
428+
let mut virtual_core = 0;
429+
for core in config.cpus.as_slice() {
430+
virutal_ids.insert(*core, VirtualAPICID(virtual_core));
431+
virtual_core += 1;
432+
}
433+
423434
let vm = Arc::new(Self {
424-
id: id,
425-
config: config,
426-
guest_space: guest_space,
435+
id,
436+
config,
437+
guest_space,
427438
apic_access_page: Raw4kPage([0u8; 4096]),
428439
logical_apic_state: logical_apic_states,
429440
cpus_ready: AtomicU32::new(0),
441+
virtual_ids: virutal_ids,
430442
});
431443

432444
// Map the guest local apic addr to the access page. This will be set in each
@@ -527,6 +539,7 @@ impl VirtualMachine {
527539
apic_state
528540
.logical_destination
529541
.store(dest, core::sync::atomic::Ordering::SeqCst);
542+
todo!("need to update to handle new apic ids")
530543
}
531544

532545
/// Resolve a guest GSI to a specific CoreId, vector and interrupt type

0 commit comments

Comments
 (0)