mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
arch: Support loading initramfs with PVH boot protocol
Fill and write to guest memory the necessary boot module structure to allow a guest using the PVH boot protocol to load an initramfs image. Signed-off-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com>
This commit is contained in:
committed by
Sebastien Boeuf
parent
b9f193703a
commit
0fc3936448
@@ -43,6 +43,8 @@ pub enum Error {
|
|||||||
StartInfoSetup,
|
StartInfoSetup,
|
||||||
/// Failed to compute initramfs address.
|
/// Failed to compute initramfs address.
|
||||||
InitramfsAddress,
|
InitramfsAddress,
|
||||||
|
/// Error writing module entry to guest memory.
|
||||||
|
ModlistSetup(vm_memory::GuestMemoryError),
|
||||||
}
|
}
|
||||||
pub type Result<T> = result::Result<T, Error>;
|
pub type Result<T> = result::Result<T, Error>;
|
||||||
|
|
||||||
|
|||||||
@@ -31,6 +31,10 @@ pub const BOOT_IDT_START: GuestAddress = GuestAddress(0x520);
|
|||||||
/// Address for the hvm_start_info struct used in PVH boot
|
/// Address for the hvm_start_info struct used in PVH boot
|
||||||
pub const PVH_INFO_START: GuestAddress = GuestAddress(0x6000);
|
pub const PVH_INFO_START: GuestAddress = GuestAddress(0x6000);
|
||||||
|
|
||||||
|
/// Starting address of array of modules of hvm_modlist_entry type.
|
||||||
|
/// Used to enable initrd support using the PVH boot ABI.
|
||||||
|
pub const MODLIST_START: GuestAddress = GuestAddress(0x6040);
|
||||||
|
|
||||||
/// Address of memory map table used in PVH boot. Can overlap
|
/// Address of memory map table used in PVH boot. Can overlap
|
||||||
/// with the zero page address since they are mutually exclusive.
|
/// with the zero page address since they are mutually exclusive.
|
||||||
pub const MEMMAP_START: GuestAddress = GuestAddress(0x7000);
|
pub const MEMMAP_START: GuestAddress = GuestAddress(0x7000);
|
||||||
|
|||||||
+28
-2
@@ -16,7 +16,9 @@ pub mod regs;
|
|||||||
use crate::InitramfsConfig;
|
use crate::InitramfsConfig;
|
||||||
use crate::RegionType;
|
use crate::RegionType;
|
||||||
use linux_loader::loader::bootparam::{boot_params, setup_header};
|
use linux_loader::loader::bootparam::{boot_params, setup_header};
|
||||||
use linux_loader::loader::elf::start_info::{hvm_memmap_table_entry, hvm_start_info};
|
use linux_loader::loader::elf::start_info::{
|
||||||
|
hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info,
|
||||||
|
};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use vm_memory::{
|
use vm_memory::{
|
||||||
Address, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap, GuestMemoryRegion,
|
Address, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap, GuestMemoryRegion,
|
||||||
@@ -68,6 +70,11 @@ struct MemmapTableEntryWrapper(hvm_memmap_table_entry);
|
|||||||
|
|
||||||
unsafe impl ByteValued for MemmapTableEntryWrapper {}
|
unsafe impl ByteValued for MemmapTableEntryWrapper {}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Default)]
|
||||||
|
struct ModlistEntryWrapper(hvm_modlist_entry);
|
||||||
|
|
||||||
|
unsafe impl ByteValued for ModlistEntryWrapper {}
|
||||||
|
|
||||||
// This is a workaround to the Rust enforcement specifying that any implementation of a foreign
|
// This is a workaround to the Rust enforcement specifying that any implementation of a foreign
|
||||||
// trait (in this case `DataInit`) where:
|
// trait (in this case `DataInit`) where:
|
||||||
// * the type that is implementing the trait is foreign or
|
// * the type that is implementing the trait is foreign or
|
||||||
@@ -164,7 +171,7 @@ pub fn configure_system(
|
|||||||
|
|
||||||
match boot_prot {
|
match boot_prot {
|
||||||
BootProtocol::PvhBoot => {
|
BootProtocol::PvhBoot => {
|
||||||
configure_pvh(guest_mem, cmdline_addr, rsdp_addr)?;
|
configure_pvh(guest_mem, cmdline_addr, initramfs, rsdp_addr)?;
|
||||||
}
|
}
|
||||||
BootProtocol::LinuxBoot => {
|
BootProtocol::LinuxBoot => {
|
||||||
configure_64bit_boot(
|
configure_64bit_boot(
|
||||||
@@ -184,6 +191,7 @@ pub fn configure_system(
|
|||||||
fn configure_pvh(
|
fn configure_pvh(
|
||||||
guest_mem: &GuestMemoryMmap,
|
guest_mem: &GuestMemoryMmap,
|
||||||
cmdline_addr: GuestAddress,
|
cmdline_addr: GuestAddress,
|
||||||
|
initramfs: &Option<InitramfsConfig>,
|
||||||
rsdp_addr: Option<GuestAddress>,
|
rsdp_addr: Option<GuestAddress>,
|
||||||
) -> super::Result<()> {
|
) -> super::Result<()> {
|
||||||
const XEN_HVM_START_MAGIC_VALUE: u32 = 0x336ec578;
|
const XEN_HVM_START_MAGIC_VALUE: u32 = 0x336ec578;
|
||||||
@@ -200,6 +208,24 @@ fn configure_pvh(
|
|||||||
start_info.0.rsdp_paddr = rsdp_addr.0;
|
start_info.0.rsdp_paddr = rsdp_addr.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(initramfs_config) = initramfs {
|
||||||
|
// The initramfs has been written to guest memory already, here we just need to
|
||||||
|
// create the module structure that describes it.
|
||||||
|
let ramdisk_mod: ModlistEntryWrapper = ModlistEntryWrapper(hvm_modlist_entry {
|
||||||
|
paddr: initramfs_config.address.raw_value(),
|
||||||
|
size: initramfs_config.size as u64,
|
||||||
|
..Default::default()
|
||||||
|
});
|
||||||
|
|
||||||
|
start_info.0.nr_modules += 1;
|
||||||
|
start_info.0.modlist_paddr = layout::MODLIST_START.raw_value();
|
||||||
|
|
||||||
|
// Write the modlist struct to guest memory.
|
||||||
|
guest_mem
|
||||||
|
.write_obj(ramdisk_mod, layout::MODLIST_START)
|
||||||
|
.map_err(super::Error::ModlistSetup)?;
|
||||||
|
}
|
||||||
|
|
||||||
// Vector to hold the memory maps which needs to be written to guest memory
|
// Vector to hold the memory maps which needs to be written to guest memory
|
||||||
// at MEMMAP_START after all of the mappings are recorded.
|
// at MEMMAP_START after all of the mappings are recorded.
|
||||||
let mut memmap: Vec<hvm_memmap_table_entry> = Vec::new();
|
let mut memmap: Vec<hvm_memmap_table_entry> = Vec::new();
|
||||||
|
|||||||
Reference in New Issue
Block a user