Skip to content

Commit 97f602f

Browse files
ShadowCurseroypat
authored andcommitted
refactor: move load_kernel into arch module
Move `load_kernel` arch specific functions into arch module per architecture. Make the function to accept the kernel `File` instead of the `BootConfig`. Signed-off-by: Egor Lazarchuk <[email protected]>
1 parent 2599a83 commit 97f602f

File tree

6 files changed

+88
-87
lines changed

6 files changed

+88
-87
lines changed

src/vmm/src/arch/aarch64/mod.rs

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,14 @@ use std::cmp::min;
2020
use std::collections::HashMap;
2121
use std::ffi::CString;
2222
use std::fmt::Debug;
23+
use std::fs::File;
2324

25+
use linux_loader::loader::KernelLoader;
26+
use linux_loader::loader::pe::PE as Loader;
2427
use vm_memory::GuestMemoryError;
2528

2629
use self::gic::GICDevice;
27-
use crate::arch::DeviceType;
30+
use crate::arch::{BootProtocol, DeviceType, EntryPoint};
2831
use crate::device_manager::mmio::MMIODeviceInfo;
2932
use crate::devices::acpi::vmgenid::VmGenId;
3033
use crate::initrd::InitrdConfig;
@@ -37,6 +40,10 @@ pub enum ConfigurationError {
3740
SetupFDT(#[from] fdt::FdtError),
3841
/// Failed to write to guest memory.
3942
MemoryError(GuestMemoryError),
43+
/// Cannot copy kernel file fd
44+
KernelFile,
45+
/// Cannot load kernel due to invalid memory configuration or invalid kernel image: {0}
46+
KernelLoader(#[from] linux_loader::loader::Error),
4047
}
4148

4249
/// The start of the memory area reserved for MMIO devices.
@@ -123,6 +130,30 @@ fn get_fdt_addr(mem: &GuestMemoryMmap) -> u64 {
123130
layout::DRAM_MEM_START
124131
}
125132

133+
/// Load linux kernel into guest memory.
134+
pub fn load_kernel(
135+
kernel: &File,
136+
guest_memory: &GuestMemoryMmap,
137+
) -> Result<EntryPoint, ConfigurationError> {
138+
// Need to clone the File because reading from it
139+
// mutates it.
140+
let mut kernel_file = kernel
141+
.try_clone()
142+
.map_err(|_| ConfigurationError::KernelFile)?;
143+
144+
let entry_addr = Loader::load(
145+
guest_memory,
146+
Some(GuestAddress(get_kernel_start())),
147+
&mut kernel_file,
148+
None,
149+
)?;
150+
151+
Ok(EntryPoint {
152+
entry_addr: entry_addr.kernel_load,
153+
protocol: BootProtocol::LinuxBoot,
154+
})
155+
}
156+
126157
#[cfg(test)]
127158
mod tests {
128159
use super::*;

src/vmm/src/arch/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ pub use aarch64::vm::{ArchVm, ArchVmError, VmState};
2222
pub use aarch64::{
2323
ConfigurationError, MMIO_MEM_SIZE, MMIO_MEM_START, arch_memory_regions, configure_system,
2424
get_kernel_start, initrd_load_addr, layout::CMDLINE_MAX_SIZE, layout::IRQ_BASE,
25-
layout::IRQ_MAX, layout::SYSTEM_MEM_SIZE, layout::SYSTEM_MEM_START,
25+
layout::IRQ_MAX, layout::SYSTEM_MEM_SIZE, layout::SYSTEM_MEM_START, load_kernel,
2626
};
2727

2828
/// Module for x86_64 related functionality.
@@ -40,7 +40,7 @@ pub use x86_64::{
4040
ConfigurationError, MMIO_MEM_SIZE, MMIO_MEM_START, arch_memory_regions, configure_system,
4141
get_kernel_start, initrd_load_addr, layout::APIC_ADDR, layout::CMDLINE_MAX_SIZE,
4242
layout::IOAPIC_ADDR, layout::IRQ_BASE, layout::IRQ_MAX, layout::SYSTEM_MEM_SIZE,
43-
layout::SYSTEM_MEM_START,
43+
layout::SYSTEM_MEM_START, load_kernel,
4444
};
4545

4646
/// Types of devices that can get attached to this platform.

src/vmm/src/arch/x86_64/mod.rs

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,20 @@ pub mod xstate;
3131
#[allow(missing_docs)]
3232
pub mod generated;
3333

34+
use std::fs::File;
35+
3436
use linux_loader::configurator::linux::LinuxBootConfigurator;
3537
use linux_loader::configurator::pvh::PvhBootConfigurator;
3638
use linux_loader::configurator::{BootConfigurator, BootParams};
3739
use linux_loader::loader::bootparam::boot_params;
40+
use linux_loader::loader::elf::Elf as Loader;
3841
use linux_loader::loader::elf::start_info::{
3942
hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info,
4043
};
44+
use linux_loader::loader::{KernelLoader, PvhBootCapability};
45+
use log::debug;
4146

47+
use super::EntryPoint;
4248
use crate::arch::{BootProtocol, SYSTEM_MEM_SIZE, SYSTEM_MEM_START};
4349
use crate::device_manager::resources::ResourceAllocator;
4450
use crate::initrd::InitrdConfig;
@@ -70,6 +76,10 @@ pub enum ConfigurationError {
7076
MemmapTableSetup,
7177
/// Error writing hvm_start_info to guest memory.
7278
StartInfoSetup,
79+
/// Cannot copy kernel file fd
80+
KernelFile,
81+
/// Cannot load kernel due to invalid memory configuration or invalid kernel image: {0}
82+
KernelLoader(#[from] linux_loader::loader::Error),
7383
}
7484

7585
/// First address that cannot be addressed using 32 bit anymore.
@@ -354,6 +364,40 @@ fn add_e820_entry(
354364
Ok(())
355365
}
356366

367+
/// Load linux kernel into guest memory.
368+
pub fn load_kernel(
369+
kernel: &File,
370+
guest_memory: &GuestMemoryMmap,
371+
) -> Result<EntryPoint, ConfigurationError> {
372+
// Need to clone the File because reading from it
373+
// mutates it.
374+
let mut kernel_file = kernel
375+
.try_clone()
376+
.map_err(|_| ConfigurationError::KernelFile)?;
377+
378+
let entry_addr = Loader::load(
379+
guest_memory,
380+
None,
381+
&mut kernel_file,
382+
Some(GuestAddress(get_kernel_start())),
383+
)?;
384+
385+
let mut entry_point_addr: GuestAddress = entry_addr.kernel_load;
386+
let mut boot_prot: BootProtocol = BootProtocol::LinuxBoot;
387+
if let PvhBootCapability::PvhEntryPresent(pvh_entry_addr) = entry_addr.pvh_boot_cap {
388+
// Use the PVH kernel entry point to boot the guest
389+
entry_point_addr = pvh_entry_addr;
390+
boot_prot = BootProtocol::PvhBoot;
391+
}
392+
393+
debug!("Kernel loaded using {boot_prot}");
394+
395+
Ok(EntryPoint {
396+
entry_addr: entry_point_addr,
397+
protocol: boot_prot,
398+
})
399+
}
400+
357401
#[cfg(test)]
358402
mod tests {
359403
use linux_loader::loader::bootparam::boot_e820_entry;

src/vmm/src/builder.rs

Lines changed: 7 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,6 @@ use std::sync::{Arc, Mutex};
1414
use event_manager::{MutEventSubscriber, SubscriberOps};
1515
use libc::EFD_NONBLOCK;
1616
use linux_loader::cmdline::Cmdline as LoaderKernelCmdline;
17-
use linux_loader::loader::KernelLoader;
18-
#[cfg(target_arch = "x86_64")]
19-
use linux_loader::loader::elf::Elf as Loader;
20-
#[cfg(target_arch = "x86_64")]
21-
use linux_loader::loader::elf::PvhBootCapability;
22-
#[cfg(target_arch = "aarch64")]
23-
use linux_loader::loader::pe::PE as Loader;
2417
use userfaultfd::Uffd;
2518
use utils::time::TimestampUs;
2619
#[cfg(target_arch = "aarch64")]
@@ -30,7 +23,7 @@ use vmm_sys_util::eventfd::EventFd;
3023

3124
#[cfg(target_arch = "x86_64")]
3225
use crate::acpi;
33-
use crate::arch::{BootProtocol, EntryPoint};
26+
use crate::arch::{ConfigurationError, EntryPoint, load_kernel};
3427
#[cfg(target_arch = "aarch64")]
3528
use crate::construct_kvm_mpidrs;
3629
use crate::cpu_config::templates::{
@@ -66,11 +59,10 @@ use crate::persist::{MicrovmState, MicrovmStateError};
6659
use crate::resources::VmResources;
6760
use crate::seccomp::BpfThreadMap;
6861
use crate::snapshot::Persist;
69-
use crate::vmm_config::boot_source::BootConfig;
7062
use crate::vmm_config::instance_info::InstanceInfo;
7163
use crate::vmm_config::machine_config::{MachineConfig, MachineConfigError};
7264
use crate::vstate::kvm::Kvm;
73-
use crate::vstate::memory::{GuestAddress, GuestMemoryMmap};
65+
use crate::vstate::memory::GuestMemoryMmap;
7466
use crate::vstate::vcpu::{Vcpu, VcpuConfig, VcpuError};
7567
use crate::vstate::vm::Vm;
7668
use crate::{EventManager, Vmm, VmmError, device_manager};
@@ -83,7 +75,7 @@ pub enum StartMicrovmError {
8375
/// Unable to attach the VMGenID device: {0}
8476
AttachVmgenidDevice(kvm_ioctls::Error),
8577
/// System configuration error: {0}
86-
ConfigureSystem(crate::arch::ConfigurationError),
78+
ConfigureSystem(#[from] ConfigurationError),
8779
/// Failed to create guest config: {0}
8880
CreateGuestConfig(#[from] GuestConfigError),
8981
/// Cannot create network device: {0}
@@ -105,8 +97,6 @@ pub enum StartMicrovmError {
10597
GetCpuTemplate(#[from] GetCpuTemplateError),
10698
/// Invalid kernel command line: {0}
10799
KernelCmdline(String),
108-
/// Cannot load kernel due to invalid memory configuration or invalid kernel image: {0}
109-
KernelLoader(linux_loader::loader::Error),
110100
/// Cannot load command line string: {0}
111101
LoadCommandline(linux_loader::loader::Error),
112102
/// Cannot start microvm without kernel configuration.
@@ -236,7 +226,7 @@ pub fn build_microvm_for_boot(
236226
.allocate_guest_memory()
237227
.map_err(StartMicrovmError::GuestMemory)?;
238228

239-
let entry_point = load_kernel(boot_config, &guest_memory)?;
229+
let entry_point = load_kernel(&boot_config.kernel_file, &guest_memory)?;
240230
let initrd = InitrdConfig::from_config(boot_config, &guest_memory)?;
241231
// Clone the command-line so that a failed boot doesn't pollute the original.
242232
#[allow(unused_mut)]
@@ -541,64 +531,6 @@ pub fn build_microvm_from_snapshot(
541531
Ok(vmm)
542532
}
543533

544-
#[cfg(target_arch = "x86_64")]
545-
fn load_kernel(
546-
boot_config: &BootConfig,
547-
guest_memory: &GuestMemoryMmap,
548-
) -> Result<EntryPoint, StartMicrovmError> {
549-
let mut kernel_file = boot_config
550-
.kernel_file
551-
.try_clone()
552-
.map_err(VmmError::KernelFile)?;
553-
554-
let entry_addr = Loader::load::<std::fs::File, GuestMemoryMmap>(
555-
guest_memory,
556-
None,
557-
&mut kernel_file,
558-
Some(GuestAddress(crate::arch::get_kernel_start())),
559-
)
560-
.map_err(StartMicrovmError::KernelLoader)?;
561-
562-
let mut entry_point_addr: GuestAddress = entry_addr.kernel_load;
563-
let mut boot_prot: BootProtocol = BootProtocol::LinuxBoot;
564-
if let PvhBootCapability::PvhEntryPresent(pvh_entry_addr) = entry_addr.pvh_boot_cap {
565-
// Use the PVH kernel entry point to boot the guest
566-
entry_point_addr = pvh_entry_addr;
567-
boot_prot = BootProtocol::PvhBoot;
568-
}
569-
570-
debug!("Kernel loaded using {boot_prot}");
571-
572-
Ok(EntryPoint {
573-
entry_addr: entry_point_addr,
574-
protocol: boot_prot,
575-
})
576-
}
577-
578-
#[cfg(target_arch = "aarch64")]
579-
fn load_kernel(
580-
boot_config: &BootConfig,
581-
guest_memory: &GuestMemoryMmap,
582-
) -> Result<EntryPoint, StartMicrovmError> {
583-
let mut kernel_file = boot_config
584-
.kernel_file
585-
.try_clone()
586-
.map_err(VmmError::KernelFile)?;
587-
588-
let entry_addr = Loader::load::<std::fs::File, GuestMemoryMmap>(
589-
guest_memory,
590-
Some(GuestAddress(crate::arch::get_kernel_start())),
591-
&mut kernel_file,
592-
None,
593-
)
594-
.map_err(StartMicrovmError::KernelLoader)?;
595-
596-
Ok(EntryPoint {
597-
entry_addr: entry_addr.kernel_load,
598-
protocol: BootProtocol::LinuxBoot,
599-
})
600-
}
601-
602534
/// Sets up the serial device.
603535
pub fn setup_serial_device(
604536
event_manager: &mut EventManager,
@@ -725,7 +657,7 @@ pub fn configure_system_for_boot(
725657

726658
linux_loader::loader::load_cmdline::<crate::vstate::memory::GuestMemoryMmap>(
727659
vmm.guest_memory(),
728-
GuestAddress(crate::arch::x86_64::layout::CMDLINE_START),
660+
crate::vstate::memory::GuestAddress(crate::arch::x86_64::layout::CMDLINE_START),
729661
&boot_cmdline,
730662
)
731663
.map_err(LoadCommandline)?;
@@ -737,8 +669,7 @@ pub fn configure_system_for_boot(
737669
initrd,
738670
vcpu_config.vcpu_count,
739671
entry_point.protocol,
740-
)
741-
.map_err(ConfigureSystem)?;
672+
)?;
742673

743674
// Create ACPI tables and write them in guest memory
744675
// For the time being we only support ACPI in x86_64
@@ -777,8 +708,7 @@ pub fn configure_system_for_boot(
777708
vmm.vm.get_irqchip(),
778709
&vmm.acpi_device_manager.vmgenid,
779710
initrd,
780-
)
781-
.map_err(ConfigureSystem)?;
711+
)?;
782712
}
783713
Ok(())
784714
}

src/vmm/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,8 +221,6 @@ pub enum VmmError {
221221
EventFd(io::Error),
222222
/// I8042 error: {0}
223223
I8042Error(devices::legacy::I8042DeviceError),
224-
/// Cannot access kernel file: {0}
225-
KernelFile(io::Error),
226224
#[cfg(target_arch = "x86_64")]
227225
/// Cannot add devices to the legacy I/O Bus. {0}
228226
LegacyIOBus(device_manager::legacy::LegacyDeviceError),

src/vmm/src/vstate/vcpu.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -771,7 +771,6 @@ pub(crate) mod tests {
771771
use super::*;
772772
use crate::RECV_TIMEOUT_SEC;
773773
use crate::arch::{BootProtocol, EntryPoint};
774-
use crate::builder::StartMicrovmError;
775774
use crate::devices::BusDevice;
776775
use crate::devices::bus::DummyDevice;
777776
use crate::seccomp::get_empty_filters;
@@ -952,12 +951,11 @@ pub(crate) mod tests {
952951
&mut kernel_file,
953952
Some(GuestAddress(crate::arch::get_kernel_start())),
954953
)
955-
.map_err(StartMicrovmError::KernelLoader);
954+
.unwrap();
956955
#[cfg(target_arch = "aarch64")]
957956
let entry_addr =
958-
linux_loader::loader::pe::PE::load(vm_memory, None, &mut kernel_file, None)
959-
.map_err(StartMicrovmError::KernelLoader);
960-
entry_addr.unwrap().kernel_load
957+
linux_loader::loader::pe::PE::load(vm_memory, None, &mut kernel_file, None).unwrap();
958+
entry_addr.kernel_load
961959
}
962960

963961
fn vcpu_configured_for_boot() -> (VcpuHandle, EventFd, GuestMemoryMmap) {

0 commit comments

Comments
 (0)