Skip to content

Commit 2599a83

Browse files
ShadowCurseroypat
authored andcommitted
refactor: move initrd code into separate module
Initrd code was spread across multiple modules, move common part of it into one and make freestanding `load_initrd_*` functions into methods for the `InitrdConfig` struct. Also change `initrd_load_addr` method to return an option instead of an error to remove extra error nesting. Signed-off-by: Egor Lazarchuk <[email protected]>
1 parent a6c9559 commit 2599a83

File tree

7 files changed

+165
-169
lines changed

7 files changed

+165
-169
lines changed

src/vmm/src/arch/aarch64/fdt.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ use std::fmt::Debug;
1212
use vm_fdt::{Error as VmFdtError, FdtWriter, FdtWriterNode};
1313
use vm_memory::GuestMemoryError;
1414

15-
use super::super::{DeviceType, InitrdConfig};
15+
use super::super::DeviceType;
1616
use super::cache_info::{CacheEntry, read_cache_config};
1717
use super::gic::GICDevice;
1818
use crate::device_manager::mmio::MMIODeviceInfo;
1919
use crate::devices::acpi::vmgenid::{VMGENID_MEM_SIZE, VmGenId};
20+
use crate::initrd::InitrdConfig;
2021
use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap};
2122

2223
// This is a value for uniquely identifying the FDT node declaring the interrupt controller.

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

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,14 @@ use self::gic::GICDevice;
2727
use crate::arch::DeviceType;
2828
use crate::device_manager::mmio::MMIODeviceInfo;
2929
use crate::devices::acpi::vmgenid::VmGenId;
30+
use crate::initrd::InitrdConfig;
3031
use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap};
3132

3233
/// Errors thrown while configuring aarch64 system.
3334
#[derive(Debug, thiserror::Error, displaydoc::Display)]
3435
pub enum ConfigurationError {
3536
/// Failed to create a Flattened Device Tree for this aarch64 microVM: {0}
3637
SetupFDT(#[from] fdt::FdtError),
37-
/// Failed to compute the initrd address.
38-
InitrdAddress,
3938
/// Failed to write to guest memory.
4039
MemoryError(GuestMemoryError),
4140
}
@@ -70,7 +69,7 @@ pub fn configure_system(
7069
device_info: &HashMap<(DeviceType, String), MMIODeviceInfo>,
7170
gic_device: &GICDevice,
7271
vmgenid: &Option<VmGenId>,
73-
initrd: &Option<super::InitrdConfig>,
72+
initrd: &Option<InitrdConfig>,
7473
) -> Result<(), ConfigurationError> {
7574
let fdt = fdt::create_fdt(
7675
guest_mem,
@@ -94,21 +93,18 @@ pub fn get_kernel_start() -> u64 {
9493
}
9594

9695
/// Returns the memory address where the initrd could be loaded.
97-
pub fn initrd_load_addr(
98-
guest_mem: &GuestMemoryMmap,
99-
initrd_size: usize,
100-
) -> Result<u64, ConfigurationError> {
96+
pub fn initrd_load_addr(guest_mem: &GuestMemoryMmap, initrd_size: usize) -> Option<u64> {
10197
let round_to_pagesize =
10298
|size| (size + (super::GUEST_PAGE_SIZE - 1)) & !(super::GUEST_PAGE_SIZE - 1);
10399
match GuestAddress(get_fdt_addr(guest_mem)).checked_sub(round_to_pagesize(initrd_size) as u64) {
104100
Some(offset) => {
105101
if guest_mem.address_in_range(offset) {
106-
Ok(offset.raw_value())
102+
Some(offset.raw_value())
107103
} else {
108-
Err(ConfigurationError::InitrdAddress)
104+
None
109105
}
110106
}
111-
None => Err(ConfigurationError::InitrdAddress),
107+
None => None,
112108
}
113109
}
114110

src/vmm/src/arch/mod.rs

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -58,15 +58,6 @@ pub enum DeviceType {
5858
BootTimer,
5959
}
6060

61-
/// Type for passing information about the initrd in the guest memory.
62-
#[derive(Debug)]
63-
pub struct InitrdConfig {
64-
/// Load address of initrd in guest memory
65-
pub address: crate::vstate::memory::GuestAddress,
66-
/// Size of initrd in guest memory
67-
pub size: usize,
68-
}
69-
7061
/// Default page size for the guest OS.
7162
pub const GUEST_PAGE_SIZE: usize = 4096;
7263

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

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,9 @@ use linux_loader::loader::elf::start_info::{
3939
hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info,
4040
};
4141

42-
use crate::arch::{BootProtocol, InitrdConfig, SYSTEM_MEM_SIZE, SYSTEM_MEM_START};
42+
use crate::arch::{BootProtocol, SYSTEM_MEM_SIZE, SYSTEM_MEM_START};
4343
use crate::device_manager::resources::ResourceAllocator;
44+
use crate::initrd::InitrdConfig;
4445
use crate::utils::{mib_to_bytes, u64_to_usize};
4546
use crate::vstate::memory::{
4647
Address, GuestAddress, GuestMemory, GuestMemoryMmap, GuestMemoryRegion,
@@ -63,8 +64,6 @@ pub enum ConfigurationError {
6364
MpTableSetup(#[from] mptable::MptableError),
6465
/// Error writing the zero page of guest memory.
6566
ZeroPageSetup,
66-
/// Failed to compute initrd address.
67-
InitrdAddress,
6867
/// Error writing module entry to guest memory.
6968
ModlistSetup,
7069
/// Error writing memory map table to guest memory.
@@ -107,21 +106,16 @@ pub fn get_kernel_start() -> u64 {
107106
}
108107

109108
/// Returns the memory address where the initrd could be loaded.
110-
pub fn initrd_load_addr(
111-
guest_mem: &GuestMemoryMmap,
112-
initrd_size: usize,
113-
) -> Result<u64, ConfigurationError> {
114-
let first_region = guest_mem
115-
.find_region(GuestAddress::new(0))
116-
.ok_or(ConfigurationError::InitrdAddress)?;
109+
pub fn initrd_load_addr(guest_mem: &GuestMemoryMmap, initrd_size: usize) -> Option<u64> {
110+
let first_region = guest_mem.find_region(GuestAddress::new(0))?;
117111
let lowmem_size = u64_to_usize(first_region.len());
118112

119113
if lowmem_size < initrd_size {
120-
return Err(ConfigurationError::InitrdAddress);
114+
return None;
121115
}
122116

123117
let align_to_pagesize = |address| address & !(super::GUEST_PAGE_SIZE - 1);
124-
Ok(align_to_pagesize(lowmem_size - initrd_size) as u64)
118+
Some(align_to_pagesize(lowmem_size - initrd_size) as u64)
125119
}
126120

127121
/// Configures the system and should be called once per vm before starting vcpu threads.

src/vmm/src/builder.rs

Lines changed: 8 additions & 137 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#[cfg(target_arch = "x86_64")]
77
use std::convert::TryFrom;
88
use std::fmt::Debug;
9-
use std::io::{self, Seek, SeekFrom};
9+
use std::io;
1010
#[cfg(feature = "gdb")]
1111
use std::sync::mpsc;
1212
use std::sync::{Arc, Mutex};
@@ -23,16 +23,14 @@ use linux_loader::loader::elf::PvhBootCapability;
2323
use linux_loader::loader::pe::PE as Loader;
2424
use userfaultfd::Uffd;
2525
use utils::time::TimestampUs;
26-
use vm_memory::ReadVolatile;
2726
#[cfg(target_arch = "aarch64")]
2827
use vm_superio::Rtc;
2928
use vm_superio::Serial;
3029
use vmm_sys_util::eventfd::EventFd;
3130

3231
#[cfg(target_arch = "x86_64")]
3332
use crate::acpi;
34-
use crate::arch::{BootProtocol, EntryPoint, InitrdConfig};
35-
use crate::builder::StartMicrovmError::Internal;
33+
use crate::arch::{BootProtocol, EntryPoint};
3634
#[cfg(target_arch = "aarch64")]
3735
use crate::construct_kvm_mpidrs;
3836
use crate::cpu_config::templates::{
@@ -62,17 +60,17 @@ use crate::devices::virtio::rng::Entropy;
6260
use crate::devices::virtio::vsock::{Vsock, VsockUnixBackend};
6361
#[cfg(feature = "gdb")]
6462
use crate::gdb;
63+
use crate::initrd::{InitrdConfig, InitrdError};
6564
use crate::logger::{debug, error};
6665
use crate::persist::{MicrovmState, MicrovmStateError};
6766
use crate::resources::VmResources;
6867
use crate::seccomp::BpfThreadMap;
6968
use crate::snapshot::Persist;
70-
use crate::utils::u64_to_usize;
7169
use crate::vmm_config::boot_source::BootConfig;
7270
use crate::vmm_config::instance_info::InstanceInfo;
7371
use crate::vmm_config::machine_config::{MachineConfig, MachineConfigError};
7472
use crate::vstate::kvm::Kvm;
75-
use crate::vstate::memory::{GuestAddress, GuestMemory, GuestMemoryMmap};
73+
use crate::vstate::memory::{GuestAddress, GuestMemoryMmap};
7674
use crate::vstate::vcpu::{Vcpu, VcpuConfig, VcpuError};
7775
use crate::vstate::vm::Vm;
7876
use crate::{EventManager, Vmm, VmmError, device_manager};
@@ -99,10 +97,8 @@ pub enum StartMicrovmError {
9997
CreateVMGenID(VmGenIdError),
10098
/// Invalid Memory Configuration: {0}
10199
GuestMemory(crate::vstate::memory::MemoryError),
102-
/// Cannot load initrd due to an invalid memory configuration.
103-
InitrdLoad,
104-
/// Cannot load initrd due to an invalid image: {0}
105-
InitrdRead(io::Error),
100+
/// Error with initrd initialization: {0}.
101+
Initrd(#[from] InitrdError),
106102
/// Internal error while starting microVM: {0}
107103
Internal(#[from] VmmError),
108104
/// Failed to get CPU template: {0}
@@ -241,7 +237,7 @@ pub fn build_microvm_for_boot(
241237
.map_err(StartMicrovmError::GuestMemory)?;
242238

243239
let entry_point = load_kernel(boot_config, &guest_memory)?;
244-
let initrd = load_initrd_from_config(boot_config, &guest_memory)?;
240+
let initrd = InitrdConfig::from_config(boot_config, &guest_memory)?;
245241
// Clone the command-line so that a failed boot doesn't pollute the original.
246242
#[allow(unused_mut)]
247243
let mut boot_cmdline = boot_config.cmdline.clone();
@@ -449,7 +445,7 @@ pub fn build_microvm_from_snapshot(
449445
vm_resources.machine_config.vcpu_count,
450446
microvm_state.kvm_state.kvm_cap_modifiers.clone(),
451447
)
452-
.map_err(Internal)?;
448+
.map_err(StartMicrovmError::Internal)?;
453449

454450
#[cfg(target_arch = "x86_64")]
455451
{
@@ -603,68 +599,6 @@ fn load_kernel(
603599
})
604600
}
605601

606-
fn load_initrd_from_config(
607-
boot_cfg: &BootConfig,
608-
vm_memory: &GuestMemoryMmap,
609-
) -> Result<Option<InitrdConfig>, StartMicrovmError> {
610-
use self::StartMicrovmError::InitrdRead;
611-
612-
Ok(match &boot_cfg.initrd_file {
613-
Some(f) => Some(load_initrd(
614-
vm_memory,
615-
&mut f.try_clone().map_err(InitrdRead)?,
616-
)?),
617-
None => None,
618-
})
619-
}
620-
621-
/// Loads the initrd from a file into the given memory slice.
622-
///
623-
/// * `vm_memory` - The guest memory the initrd is written to.
624-
/// * `image` - The initrd image.
625-
///
626-
/// Returns the result of initrd loading
627-
fn load_initrd<F>(
628-
vm_memory: &GuestMemoryMmap,
629-
image: &mut F,
630-
) -> Result<InitrdConfig, StartMicrovmError>
631-
where
632-
F: ReadVolatile + Seek + Debug,
633-
{
634-
use self::StartMicrovmError::{InitrdLoad, InitrdRead};
635-
636-
// Get the image size
637-
let size = match image.seek(SeekFrom::End(0)) {
638-
Err(err) => return Err(InitrdRead(err)),
639-
Ok(0) => {
640-
return Err(InitrdRead(io::Error::new(
641-
io::ErrorKind::InvalidData,
642-
"Initrd image seek returned a size of zero",
643-
)));
644-
}
645-
Ok(s) => u64_to_usize(s),
646-
};
647-
// Go back to the image start
648-
image.seek(SeekFrom::Start(0)).map_err(InitrdRead)?;
649-
650-
// Get the target address
651-
let address = crate::arch::initrd_load_addr(vm_memory, size).map_err(|_| InitrdLoad)?;
652-
653-
// Load the image into memory
654-
let mut slice = vm_memory
655-
.get_slice(GuestAddress(address), size)
656-
.map_err(|_| InitrdLoad)?;
657-
658-
image
659-
.read_exact_volatile(&mut slice)
660-
.map_err(|_| InitrdLoad)?;
661-
662-
Ok(InitrdConfig {
663-
address: GuestAddress(address),
664-
size,
665-
})
666-
}
667-
668602
/// Sets up the serial device.
669603
pub fn setup_serial_device(
670604
event_manager: &mut EventManager,
@@ -1010,7 +944,6 @@ pub(crate) fn set_stdout_nonblocking() {
1010944

1011945
#[cfg(test)]
1012946
pub(crate) mod tests {
1013-
use std::io::Write;
1014947

1015948
use linux_loader::cmdline::Cmdline;
1016949
use vmm_sys_util::tempfile::TempFile;
@@ -1024,7 +957,6 @@ pub(crate) mod tests {
1024957
use crate::devices::virtio::{TYPE_BALLOON, TYPE_BLOCK, TYPE_RNG};
1025958
use crate::mmds::data_store::{Mmds, MmdsVersion};
1026959
use crate::mmds::ns::MmdsNetworkStack;
1027-
use crate::test_utils::{single_region_mem, single_region_mem_at};
1028960
use crate::utils::mib_to_bytes;
1029961
use crate::vmm_config::balloon::{BALLOON_DEV_ID, BalloonBuilder, BalloonDeviceConfig};
1030962
use crate::vmm_config::boot_source::DEFAULT_KERNEL_CMDLINE;
@@ -1270,67 +1202,6 @@ pub(crate) mod tests {
12701202
);
12711203
}
12721204

1273-
fn make_test_bin() -> Vec<u8> {
1274-
let mut fake_bin = Vec::new();
1275-
fake_bin.resize(1_000_000, 0xAA);
1276-
fake_bin
1277-
}
1278-
1279-
#[test]
1280-
// Test that loading the initrd is successful on different archs.
1281-
fn test_load_initrd() {
1282-
use crate::vstate::memory::GuestMemory;
1283-
let image = make_test_bin();
1284-
1285-
let mem_size: usize = image.len() * 2 + crate::arch::GUEST_PAGE_SIZE;
1286-
1287-
let tempfile = TempFile::new().unwrap();
1288-
let mut tempfile = tempfile.into_file();
1289-
tempfile.write_all(&image).unwrap();
1290-
1291-
#[cfg(target_arch = "x86_64")]
1292-
let gm = single_region_mem(mem_size);
1293-
1294-
#[cfg(target_arch = "aarch64")]
1295-
let gm = single_region_mem(mem_size + crate::arch::aarch64::layout::FDT_MAX_SIZE);
1296-
1297-
let res = load_initrd(&gm, &mut tempfile);
1298-
let initrd = res.unwrap();
1299-
assert!(gm.address_in_range(initrd.address));
1300-
assert_eq!(initrd.size, image.len());
1301-
}
1302-
1303-
#[test]
1304-
fn test_load_initrd_no_memory() {
1305-
let gm = single_region_mem(79);
1306-
let image = make_test_bin();
1307-
let tempfile = TempFile::new().unwrap();
1308-
let mut tempfile = tempfile.into_file();
1309-
tempfile.write_all(&image).unwrap();
1310-
let res = load_initrd(&gm, &mut tempfile);
1311-
assert!(
1312-
matches!(res, Err(StartMicrovmError::InitrdLoad)),
1313-
"{:?}",
1314-
res
1315-
);
1316-
}
1317-
1318-
#[test]
1319-
fn test_load_initrd_unaligned() {
1320-
let image = vec![1, 2, 3, 4];
1321-
let tempfile = TempFile::new().unwrap();
1322-
let mut tempfile = tempfile.into_file();
1323-
tempfile.write_all(&image).unwrap();
1324-
let gm = single_region_mem_at(crate::arch::GUEST_PAGE_SIZE as u64 + 1, image.len() * 2);
1325-
1326-
let res = load_initrd(&gm, &mut tempfile);
1327-
assert!(
1328-
matches!(res, Err(StartMicrovmError::InitrdLoad)),
1329-
"{:?}",
1330-
res
1331-
);
1332-
}
1333-
13341205
#[test]
13351206
fn test_attach_net_devices() {
13361207
let mut event_manager = EventManager::new().expect("Unable to create EventManager");

0 commit comments

Comments
 (0)