Skip to content

Commit af161a4

Browse files
authored
Merge pull request #114 from mythril-hypervisor/avoid-allocation
Avoid many instances of dynamic allocation
2 parents f2e3436 + 37073c4 commit af161a4

File tree

27 files changed

+443
-488
lines changed

27 files changed

+443
-488
lines changed

mythril/Cargo.lock

Lines changed: 9 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

mythril/Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ test = []
1212

1313
[dependencies]
1414
arraydeque = { version = "0.4.5", default-features = false }
15-
arrayvec = { version = "0.5.1", default-features = false }
1615
bitflags = "1.2.0"
1716
byteorder = { version = "1", default-features = false }
1817
num_enum = { version = "0.5.0", default-features = false }
@@ -21,6 +20,7 @@ linked_list_allocator = "0.8.6"
2120
log = { version = "0.4.8", default-features = false }
2221
multiboot = "0.3.0"
2322
multiboot2 = "0.9.0"
23+
paste = "1.0"
2424
raw-cpuid = "8.1.1"
2525
rlibc = "1.0.0"
2626
serde = {version = "^1", default-features = false, features = ["alloc", "derive"] }
@@ -29,6 +29,11 @@ spin = "0.5"
2929
ux = { version = "0.1.3", default-features = false }
3030
managed = { version = "0.8.0", features = ["map", "alloc"], default-features = false }
3131

32+
[dependencies.arrayvec]
33+
version = "0.5.2"
34+
default-features = false
35+
features = ["unstable-const-fn"]
36+
3237
[dependencies.iced-x86]
3338
version = "1.8.0"
3439
default-features = false

mythril/src/boot.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
%include "paging.mac"
22

3-
%define BSP_STACK_SIZE (PAGE_SIZE*50)
3+
%define BSP_STACK_SIZE (PAGE_SIZE*100)
44
%define PAGE_HIERARCHY_SIZE (PAGE_SIZE*7)
55

66
global PAGE_HIERARCHY

mythril/src/emulate/cpuid.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ pub fn emulate_cpuid(
2323

2424
// Hide TSC deadline timer
2525
res.ecx &= !(1 << 24);
26+
} else if guest_cpu.rax as u32 == 0x0b {
27+
res.edx = crate::percore::read_core_id().raw as u32;
2628
}
2729

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

mythril/src/emulate/memio.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -523,8 +523,7 @@ pub fn handle_apic_access(
523523
_ => return Err(Error::NotSupported),
524524
};
525525

526-
vcpu.local_apic
527-
.register_write(vcpu.vm.clone(), offset, value)
526+
vcpu.local_apic.register_write(vcpu.vm, offset, value)
528527
}
529528

530529
let addr = vm::GUEST_LOCAL_APIC_ADDR

mythril/src/kmain.rs

Lines changed: 38 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use crate::virtdev;
1818
use crate::vm;
1919

2020
use alloc::collections::BTreeMap;
21-
use alloc::sync::Arc;
2221
use alloc::vec::Vec;
2322
use log::{debug, info};
2423
use managed::ManagedMap;
@@ -40,11 +39,11 @@ fn build_vm(
4039
cfg: &config::UserVmConfig,
4140
info: &BootInfo,
4241
add_uart: bool,
43-
) -> Arc<vm::VirtualMachine> {
42+
) -> vm::VirtualMachine {
4443
let physical_config = if add_uart == false {
45-
vm::PhysicalDeviceConfig::default()
44+
vm::HostPhysicalDevices::default()
4645
} else {
47-
vm::PhysicalDeviceConfig {
46+
vm::HostPhysicalDevices {
4847
serial: RwLock::new(Some(
4948
physdev::com::Uart8250::new(0x3f8)
5049
.expect("Failed to create UART"),
@@ -83,47 +82,18 @@ fn build_vm(
8382

8483
acpi.add_sdt(madt).unwrap();
8584

86-
let device_map = config.virtual_devices_mut();
85+
let virtual_devices = &mut config.virtual_devices;
8786

88-
device_map
89-
.register_device(virtdev::acpi::AcpiRuntime::new(0x600).unwrap())
90-
.unwrap();
91-
device_map
92-
.register_device(virtdev::debug::DebugPort::new(0x402))
93-
.unwrap();
94-
device_map
95-
.register_device(virtdev::com::Uart8250::new(0x3F8))
96-
.unwrap();
97-
device_map
98-
.register_device(virtdev::vga::VgaController::new())
99-
.unwrap();
100-
device_map
101-
.register_device(virtdev::dma::Dma8237::new())
102-
.unwrap();
103-
device_map
104-
.register_device(virtdev::ignore::IgnoredDevice::new())
105-
.unwrap();
106-
device_map
107-
.register_device(virtdev::pci::PciRootComplex::new())
108-
.unwrap();
109-
device_map
110-
.register_device(virtdev::pic::Pic8259::new())
111-
.unwrap();
112-
device_map
113-
.register_device(virtdev::keyboard::Keyboard8042::new())
114-
.unwrap();
115-
device_map
116-
.register_device(virtdev::pit::Pit8254::new())
117-
.unwrap();
118-
device_map
119-
.register_device(virtdev::pos::ProgrammableOptionSelect::new())
120-
.unwrap();
121-
device_map
122-
.register_device(virtdev::rtc::CmosRtc::new(cfg.memory))
123-
.unwrap();
124-
device_map
125-
.register_device(virtdev::ioapic::IoApic::new())
126-
.unwrap();
87+
virtual_devices.push(RwLock::new(
88+
virtdev::DynamicVirtualDevice::DebugPort(
89+
virtdev::debug::DebugPort::new(0x402)
90+
.expect("Failed to make DebugPort"),
91+
),
92+
));
93+
94+
virtual_devices.push(RwLock::new(virtdev::DynamicVirtualDevice::Uart(
95+
virtdev::com::Uart8250::new(0x3F8).expect("Failed to make Uart"),
96+
)));
12797

12898
let mut fw_cfg_builder = virtdev::qemu_fw_cfg::QemuFwCfgBuilder::new();
12999

@@ -155,7 +125,9 @@ fn build_vm(
155125
)
156126
.unwrap();
157127

158-
device_map.register_device(fw_cfg_builder.build()).unwrap();
128+
virtual_devices.push(RwLock::new(virtdev::DynamicVirtualDevice::Qemu(
129+
fw_cfg_builder.build().expect("Failed to build FW Cfg"),
130+
)));
159131

160132
vm::VirtualMachine::new(vm_id, config, info).expect("Failed to create vm")
161133
}
@@ -251,8 +223,6 @@ unsafe fn kmain(mut boot_info: BootInfo) -> ! {
251223
ioapic::map_gsi_vector(interrupt::gsi::UART, interrupt::vector::UART, 0)
252224
.expect("Failed to map com0 gsi");
253225

254-
let mut builder = vm::VirtualMachineSetBuilder::new();
255-
256226
let raw_cfg = boot_info
257227
.find_module("mythril.cfg")
258228
.expect("Failed to find 'mythril.cfg' in boot information")
@@ -263,13 +233,15 @@ unsafe fn kmain(mut boot_info: BootInfo) -> ! {
263233

264234
debug!("mythril.cfg: {:?}", mythril_cfg);
265235

266-
for (num, vm) in mythril_cfg.vms.into_iter().enumerate() {
267-
builder
268-
.insert_machine(build_vm(num as u32, &vm, &boot_info, num == 0))
269-
.expect("Failed to insert new vm");
270-
}
271-
272-
vm::init_virtual_machines(builder.finalize());
236+
let vms = mythril_cfg
237+
.vms
238+
.into_iter()
239+
.enumerate()
240+
.map(|(num, vm_cfg)| {
241+
build_vm(num as u32, &vm_cfg, &boot_info, num == 0)
242+
});
243+
vm::init_virtual_machines(vms)
244+
.expect("Failed to initialize early virtual machine state");
273245

274246
debug!("AP_STARTUP address: 0x{:x}", AP_STARTUP_ADDR);
275247

@@ -332,5 +304,17 @@ unsafe fn kmain(mut boot_info: BootInfo) -> ! {
332304
core::ptr::write_volatile(&mut AP_READY as *mut u8, 0);
333305
}
334306

307+
// Also don't start the bsp core if there is no guest assigned to use it
308+
let bsp_core_id = percore::read_core_id();
309+
if !vm::virtual_machines().is_assigned_core_id(bsp_core_id) {
310+
debug!(
311+
"Not starting core ID '{}' because it is not assigned to a guest",
312+
bsp_core_id
313+
);
314+
loop {
315+
crate::lock::relax_cpu();
316+
}
317+
}
318+
335319
vcpu::mp_entry_point()
336320
}

mythril/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
#![feature(get_mut_unchecked)]
66
#![feature(fixed_size_array)]
77
#![feature(panic_info_message)]
8+
#![feature(pin_static_ref)]
9+
#![feature(array_value_iter)]
810
#![feature(alloc_error_handler)]
911
#![feature(lang_items)]
1012
#![feature(stmt_expr_attributes)]

mythril/src/percore.rs

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -61,20 +61,22 @@ pub unsafe fn init_sections(ncores: usize) -> Result<()> {
6161
Ok(())
6262
}
6363

64+
unsafe fn percore_section_start(core_idx: u64) -> *const u8 {
65+
if core_idx == 0 {
66+
&PER_CORE_START as *const u8
67+
} else {
68+
let section_len = per_core_section_len();
69+
(&AP_PER_CORE_SECTIONS[section_len * (core_idx - 1) as usize])
70+
as *const u8
71+
}
72+
}
73+
6474
/// Initialize this core's per-core data
6575
///
6676
/// This must be called by each AP (and the BSP) before
6777
/// the usage of any per-core variable
6878
pub unsafe fn init_segment_for_core(core_idx: u64) {
69-
let fs = if core_idx == 0 {
70-
&PER_CORE_START as *const u8 as u64
71-
} else {
72-
let section_len = per_core_section_len();
73-
(&AP_PER_CORE_SECTIONS[section_len * (core_idx - 1) as usize])
74-
as *const u8 as u64
75-
};
76-
77-
msr::wrmsr(msr::IA32_FS_BASE, fs);
79+
msr::wrmsr(msr::IA32_FS_BASE, percore_section_start(core_idx) as u64);
7880

7981
RoAfterInit::init(
8082
crate::get_per_core_mut!(CORE_ID),
@@ -125,7 +127,9 @@ macro_rules! get_per_core {
125127
($name:ident) => {
126128
#[allow(unused_unsafe)]
127129
unsafe {
128-
$crate::percore::get_per_core_impl(&$name)
130+
$crate::percore::get_per_core_impl(&paste::paste! {
131+
[<PERCORE_ $name>]
132+
})
129133
}
130134
};
131135
}
@@ -135,7 +139,9 @@ macro_rules! get_per_core_mut {
135139
($name:ident) => {
136140
#[allow(unused_unsafe)]
137141
unsafe {
138-
$crate::percore::get_per_core_mut_impl(&mut $name)
142+
$crate::percore::get_per_core_mut_impl(&mut paste::paste! {
143+
[<PERCORE_ $name>]
144+
})
139145
}
140146
};
141147
}
@@ -145,14 +151,19 @@ macro_rules! get_per_core_mut {
145151
#[doc(hidden)]
146152
macro_rules! __declare_per_core_internal {
147153
($(#[$attr:meta])* ($($vis:tt)*) static mut $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
148-
#[link_section = ".per_core"]
149-
$($vis)* static mut $N: $T = $e;
154+
paste::paste! {
155+
#[link_section = ".per_core"]
156+
$($vis)* static mut [<PERCORE_ $N>]: $T = $e;
157+
}
150158

151159
declare_per_core!($($t)*);
152160
};
153161
($(#[$attr:meta])* ($($vis:tt)*) static $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
154-
#[link_section = ".per_core"]
155-
$($vis)* static $N: $T = $e;
162+
use paste::paste;
163+
paste! {
164+
#[link_section = ".per_core"]
165+
$($vis)* static [<PERCORE_ $N>]: $T = $e;
166+
}
156167

157168
declare_per_core!($($t)*);
158169
};

mythril/src/time.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,7 @@ impl TimerWheel {
289289
/// expired and will reset any periodic timers.
290290
pub fn expire_elapsed_timers(
291291
&mut self,
292-
) -> Result<vec::Vec<TimerInterruptType>> {
292+
) -> Result<impl Iterator<Item = TimerInterruptType>> {
293293
let mut interrupts = vec![];
294294
let elapsed_oneshots = self
295295
.timers
@@ -318,7 +318,7 @@ impl TimerWheel {
318318
}
319319

320320
self.update_interrupt_timer();
321-
Ok(interrupts)
321+
Ok(interrupts.into_iter())
322322
}
323323

324324
fn update_interrupt_timer(&mut self) {

0 commit comments

Comments
 (0)