Skip to content

Commit

Permalink
Merge pull request #114 from mythril-hypervisor/avoid-allocation
Browse files Browse the repository at this point in the history
Avoid many instances of dynamic allocation
  • Loading branch information
ALSchwalm authored Feb 26, 2021
2 parents f2e3436 + 37073c4 commit af161a4
Show file tree
Hide file tree
Showing 27 changed files with 443 additions and 488 deletions.
11 changes: 9 additions & 2 deletions mythril/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion mythril/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ test = []

[dependencies]
arraydeque = { version = "0.4.5", default-features = false }
arrayvec = { version = "0.5.1", default-features = false }
bitflags = "1.2.0"
byteorder = { version = "1", default-features = false }
num_enum = { version = "0.5.0", default-features = false }
Expand All @@ -21,6 +20,7 @@ linked_list_allocator = "0.8.6"
log = { version = "0.4.8", default-features = false }
multiboot = "0.3.0"
multiboot2 = "0.9.0"
paste = "1.0"
raw-cpuid = "8.1.1"
rlibc = "1.0.0"
serde = {version = "^1", default-features = false, features = ["alloc", "derive"] }
Expand All @@ -29,6 +29,11 @@ spin = "0.5"
ux = { version = "0.1.3", default-features = false }
managed = { version = "0.8.0", features = ["map", "alloc"], default-features = false }

[dependencies.arrayvec]
version = "0.5.2"
default-features = false
features = ["unstable-const-fn"]

[dependencies.iced-x86]
version = "1.8.0"
default-features = false
Expand Down
2 changes: 1 addition & 1 deletion mythril/src/boot.S
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
%include "paging.mac"

%define BSP_STACK_SIZE (PAGE_SIZE*50)
%define BSP_STACK_SIZE (PAGE_SIZE*100)
%define PAGE_HIERARCHY_SIZE (PAGE_SIZE*7)

global PAGE_HIERARCHY
Expand Down
2 changes: 2 additions & 0 deletions mythril/src/emulate/cpuid.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ pub fn emulate_cpuid(

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

guest_cpu.rax = res.eax as u64 | (guest_cpu.rax & 0xffffffff00000000);
Expand Down
3 changes: 1 addition & 2 deletions mythril/src/emulate/memio.rs
Original file line number Diff line number Diff line change
Expand Up @@ -523,8 +523,7 @@ pub fn handle_apic_access(
_ => return Err(Error::NotSupported),
};

vcpu.local_apic
.register_write(vcpu.vm.clone(), offset, value)
vcpu.local_apic.register_write(vcpu.vm, offset, value)
}

let addr = vm::GUEST_LOCAL_APIC_ADDR
Expand Down
92 changes: 38 additions & 54 deletions mythril/src/kmain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ use crate::virtdev;
use crate::vm;

use alloc::collections::BTreeMap;
use alloc::sync::Arc;
use alloc::vec::Vec;
use log::{debug, info};
use managed::ManagedMap;
Expand All @@ -40,11 +39,11 @@ fn build_vm(
cfg: &config::UserVmConfig,
info: &BootInfo,
add_uart: bool,
) -> Arc<vm::VirtualMachine> {
) -> vm::VirtualMachine {
let physical_config = if add_uart == false {
vm::PhysicalDeviceConfig::default()
vm::HostPhysicalDevices::default()
} else {
vm::PhysicalDeviceConfig {
vm::HostPhysicalDevices {
serial: RwLock::new(Some(
physdev::com::Uart8250::new(0x3f8)
.expect("Failed to create UART"),
Expand Down Expand Up @@ -83,47 +82,18 @@ fn build_vm(

acpi.add_sdt(madt).unwrap();

let device_map = config.virtual_devices_mut();
let virtual_devices = &mut config.virtual_devices;

device_map
.register_device(virtdev::acpi::AcpiRuntime::new(0x600).unwrap())
.unwrap();
device_map
.register_device(virtdev::debug::DebugPort::new(0x402))
.unwrap();
device_map
.register_device(virtdev::com::Uart8250::new(0x3F8))
.unwrap();
device_map
.register_device(virtdev::vga::VgaController::new())
.unwrap();
device_map
.register_device(virtdev::dma::Dma8237::new())
.unwrap();
device_map
.register_device(virtdev::ignore::IgnoredDevice::new())
.unwrap();
device_map
.register_device(virtdev::pci::PciRootComplex::new())
.unwrap();
device_map
.register_device(virtdev::pic::Pic8259::new())
.unwrap();
device_map
.register_device(virtdev::keyboard::Keyboard8042::new())
.unwrap();
device_map
.register_device(virtdev::pit::Pit8254::new())
.unwrap();
device_map
.register_device(virtdev::pos::ProgrammableOptionSelect::new())
.unwrap();
device_map
.register_device(virtdev::rtc::CmosRtc::new(cfg.memory))
.unwrap();
device_map
.register_device(virtdev::ioapic::IoApic::new())
.unwrap();
virtual_devices.push(RwLock::new(
virtdev::DynamicVirtualDevice::DebugPort(
virtdev::debug::DebugPort::new(0x402)
.expect("Failed to make DebugPort"),
),
));

virtual_devices.push(RwLock::new(virtdev::DynamicVirtualDevice::Uart(
virtdev::com::Uart8250::new(0x3F8).expect("Failed to make Uart"),
)));

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

Expand Down Expand Up @@ -155,7 +125,9 @@ fn build_vm(
)
.unwrap();

device_map.register_device(fw_cfg_builder.build()).unwrap();
virtual_devices.push(RwLock::new(virtdev::DynamicVirtualDevice::Qemu(
fw_cfg_builder.build().expect("Failed to build FW Cfg"),
)));

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

let mut builder = vm::VirtualMachineSetBuilder::new();

let raw_cfg = boot_info
.find_module("mythril.cfg")
.expect("Failed to find 'mythril.cfg' in boot information")
Expand All @@ -263,13 +233,15 @@ unsafe fn kmain(mut boot_info: BootInfo) -> ! {

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

for (num, vm) in mythril_cfg.vms.into_iter().enumerate() {
builder
.insert_machine(build_vm(num as u32, &vm, &boot_info, num == 0))
.expect("Failed to insert new vm");
}

vm::init_virtual_machines(builder.finalize());
let vms = mythril_cfg
.vms
.into_iter()
.enumerate()
.map(|(num, vm_cfg)| {
build_vm(num as u32, &vm_cfg, &boot_info, num == 0)
});
vm::init_virtual_machines(vms)
.expect("Failed to initialize early virtual machine state");

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

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

// Also don't start the bsp core if there is no guest assigned to use it
let bsp_core_id = percore::read_core_id();
if !vm::virtual_machines().is_assigned_core_id(bsp_core_id) {
debug!(
"Not starting core ID '{}' because it is not assigned to a guest",
bsp_core_id
);
loop {
crate::lock::relax_cpu();
}
}

vcpu::mp_entry_point()
}
2 changes: 2 additions & 0 deletions mythril/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#![feature(get_mut_unchecked)]
#![feature(fixed_size_array)]
#![feature(panic_info_message)]
#![feature(pin_static_ref)]
#![feature(array_value_iter)]
#![feature(alloc_error_handler)]
#![feature(lang_items)]
#![feature(stmt_expr_attributes)]
Expand Down
41 changes: 26 additions & 15 deletions mythril/src/percore.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,20 +61,22 @@ pub unsafe fn init_sections(ncores: usize) -> Result<()> {
Ok(())
}

unsafe fn percore_section_start(core_idx: u64) -> *const u8 {
if core_idx == 0 {
&PER_CORE_START as *const u8
} else {
let section_len = per_core_section_len();
(&AP_PER_CORE_SECTIONS[section_len * (core_idx - 1) as usize])
as *const u8
}
}

/// Initialize this core's per-core data
///
/// This must be called by each AP (and the BSP) before
/// the usage of any per-core variable
pub unsafe fn init_segment_for_core(core_idx: u64) {
let fs = if core_idx == 0 {
&PER_CORE_START as *const u8 as u64
} else {
let section_len = per_core_section_len();
(&AP_PER_CORE_SECTIONS[section_len * (core_idx - 1) as usize])
as *const u8 as u64
};

msr::wrmsr(msr::IA32_FS_BASE, fs);
msr::wrmsr(msr::IA32_FS_BASE, percore_section_start(core_idx) as u64);

RoAfterInit::init(
crate::get_per_core_mut!(CORE_ID),
Expand Down Expand Up @@ -125,7 +127,9 @@ macro_rules! get_per_core {
($name:ident) => {
#[allow(unused_unsafe)]
unsafe {
$crate::percore::get_per_core_impl(&$name)
$crate::percore::get_per_core_impl(&paste::paste! {
[<PERCORE_ $name>]
})
}
};
}
Expand All @@ -135,7 +139,9 @@ macro_rules! get_per_core_mut {
($name:ident) => {
#[allow(unused_unsafe)]
unsafe {
$crate::percore::get_per_core_mut_impl(&mut $name)
$crate::percore::get_per_core_mut_impl(&mut paste::paste! {
[<PERCORE_ $name>]
})
}
};
}
Expand All @@ -145,14 +151,19 @@ macro_rules! get_per_core_mut {
#[doc(hidden)]
macro_rules! __declare_per_core_internal {
($(#[$attr:meta])* ($($vis:tt)*) static mut $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
#[link_section = ".per_core"]
$($vis)* static mut $N: $T = $e;
paste::paste! {
#[link_section = ".per_core"]
$($vis)* static mut [<PERCORE_ $N>]: $T = $e;
}

declare_per_core!($($t)*);
};
($(#[$attr:meta])* ($($vis:tt)*) static $N:ident : $T:ty = $e:expr; $($t:tt)*) => {
#[link_section = ".per_core"]
$($vis)* static $N: $T = $e;
use paste::paste;
paste! {
#[link_section = ".per_core"]
$($vis)* static [<PERCORE_ $N>]: $T = $e;
}

declare_per_core!($($t)*);
};
Expand Down
4 changes: 2 additions & 2 deletions mythril/src/time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -289,7 +289,7 @@ impl TimerWheel {
/// expired and will reset any periodic timers.
pub fn expire_elapsed_timers(
&mut self,
) -> Result<vec::Vec<TimerInterruptType>> {
) -> Result<impl Iterator<Item = TimerInterruptType>> {
let mut interrupts = vec![];
let elapsed_oneshots = self
.timers
Expand Down Expand Up @@ -318,7 +318,7 @@ impl TimerWheel {
}

self.update_interrupt_timer();
Ok(interrupts)
Ok(interrupts.into_iter())
}

fn update_interrupt_timer(&mut self) {
Expand Down
Loading

0 comments on commit af161a4

Please sign in to comment.