Skip to content

Commit

Permalink
pvh/arch: Introduce EntryPoint struct
Browse files Browse the repository at this point in the history
In order to properly configure the initial vCPU register state
and boot parameters in guest memory, we must specify which
boot protocol to use with the kernel entry point address.

Create an EntryPoint struct that contains the required
information. This structure will later be used in the vCPU
configuration methods to set the appropriate initial
conditions for the guest.

Signed-off-by: Colin Percival <[email protected]>
Co-authored-by: Alejandro Jimenez <[email protected]>
  • Loading branch information
cperciva and aljimenezb committed Dec 29, 2022
1 parent cdf4fef commit b389e5f
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 5 deletions.
29 changes: 29 additions & 0 deletions src/arch/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,32 @@ impl fmt::Display for DeviceType {
write!(f, "{:?}", self)
}
}

/// Suported boot protocols for
#[derive(Debug, Copy, Clone)]
pub enum BootProtocol {
/// Linux 64-bit boot protocol
LinuxBoot,
/// PVH boot protocol (x86/HVM direct boot ABI)
PvhBoot,
}

impl fmt::Display for BootProtocol {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
match self {
BootProtocol::LinuxBoot => write!(f, "Linux 64-bit boot protocol"),
BootProtocol::PvhBoot => write!(f, "PVH boot protocol"),
}
}
}

#[derive(Debug, Copy, Clone)]
/// Specifies the entry point address where the guest must start
/// executing code, as well as which boot protocol is to be used
/// to configure the guest initial state.
pub struct EntryPoint {
/// Address in guest memory where the guest must start execution
pub entry_addr: vm_memory::GuestAddress,
/// Specifies which boot protocol to use
pub protocol: BootProtocol,
}
25 changes: 20 additions & 5 deletions src/vmm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use std::io::{self, Read, Seek, SeekFrom};
use std::os::unix::io::{AsRawFd, RawFd};
use std::sync::{Arc, Mutex};

use arch::InitrdConfig;
use arch::{BootProtocol, EntryPoint, InitrdConfig};
#[cfg(target_arch = "x86_64")]
use cpuid::common::is_same_model;
#[cfg(target_arch = "aarch64")]
Expand All @@ -23,6 +23,7 @@ use libc::EFD_NONBLOCK;
use linux_loader::cmdline::Cmdline as LoaderKernelCmdline;
#[cfg(target_arch = "x86_64")]
use linux_loader::loader::elf::Elf as Loader;
use linux_loader::loader::elf::PvhBootCapability;
#[cfg(target_arch = "aarch64")]
use linux_loader::loader::pe::PE as Loader;
use linux_loader::loader::KernelLoader;
Expand Down Expand Up @@ -335,7 +336,7 @@ pub fn build_microvm_for_boot(
let guest_memory =
create_guest_memory(vm_resources.vm_config().mem_size_mib, track_dirty_pages)?;
let vcpu_config = vm_resources.vcpu_config();
let entry_addr = load_kernel(boot_config, &guest_memory)?;
let entry_point = load_kernel(boot_config, &guest_memory)?;
let initrd = load_initrd_from_config(boot_config, &guest_memory)?;
// Clone the command-line so that a failed boot doesn't pollute the original.
#[allow(unused_mut)]
Expand Down Expand Up @@ -384,7 +385,7 @@ pub fn build_microvm_for_boot(
&vmm,
vcpus.as_mut(),
vcpu_config,
entry_addr,
entry_point.entry_addr,
&initrd,
boot_cmdline,
)?;
Expand Down Expand Up @@ -613,7 +614,7 @@ pub fn create_guest_memory(
fn load_kernel(
boot_config: &BootConfig,
guest_memory: &GuestMemoryMmap,
) -> std::result::Result<GuestAddress, StartMicrovmError> {
) -> std::result::Result<EntryPoint, StartMicrovmError> {
let mut kernel_file = boot_config
.kernel_file
.try_clone()
Expand All @@ -637,7 +638,21 @@ fn load_kernel(
)
.map_err(StartMicrovmError::KernelLoader)?;

Ok(entry_addr.kernel_load)
let mut entry_point_addr: GuestAddress = entry_addr.kernel_load;
let mut boot_prot: BootProtocol = BootProtocol::LinuxBoot;

if cfg!(target_arch = "x86_64") {
if let PvhBootCapability::PvhEntryPresent(pvh_entry_addr) = entry_addr.pvh_boot_cap {
// Use the PVH kernel entry point to boot the guest
entry_point_addr = pvh_entry_addr;
boot_prot = BootProtocol::PvhBoot;
}
}

Ok(EntryPoint {
entry_addr: entry_point_addr,
protocol: boot_prot,
})
}

fn load_initrd_from_config(
Expand Down

0 comments on commit b389e5f

Please sign in to comment.