|
| 1 | +From e0b0f71e3f3b6fcd53c49875b18d0d5dbdd53e88 Mon Sep 17 00:00:00 2001 |
| 2 | +From: Colin Percival <cperciva@freebsd.org> |
| 3 | +Date: Sun, 2 Oct 2022 10:42:24 -0700 |
| 4 | +Subject: [PATCH 1/3] pvh/arch: Introduce EntryPoint struct |
| 5 | + |
| 6 | +In order to properly configure the initial vCPU register state |
| 7 | +and boot parameters in guest memory, we must specify which |
| 8 | +boot protocol to use with the kernel entry point address. |
| 9 | + |
| 10 | +Create an EntryPoint struct that contains the required |
| 11 | +information. This structure will later be used in the vCPU |
| 12 | +configuration methods to set the appropriate initial |
| 13 | +conditions for the guest. |
| 14 | + |
| 15 | +Signed-off-by: Colin Percival <cperciva@freebsd.org> |
| 16 | +Co-authored-by: Alejandro Jimenez <alejandro.j.jimenez@oracle.com> |
| 17 | +--- |
| 18 | + src/arch/src/lib.rs | 29 +++++++++++++++++++++++++++++ |
| 19 | + src/vmm/src/builder.rs | 25 ++++++++++++++++++++----- |
| 20 | + 2 files changed, 49 insertions(+), 5 deletions(-) |
| 21 | + |
| 22 | +diff --git a/src/arch/src/lib.rs b/src/arch/src/lib.rs |
| 23 | +index 7d025f39..950676cf 100644 |
| 24 | +--- a/src/arch/src/lib.rs |
| 25 | ++++ b/src/arch/src/lib.rs |
| 26 | +@@ -65,3 +65,32 @@ impl fmt::Display for DeviceType { |
| 27 | + write!(f, "{:?}", self) |
| 28 | + } |
| 29 | + } |
| 30 | ++ |
| 31 | ++/// Suported boot protocols for |
| 32 | ++#[derive(Debug, Copy, Clone)] |
| 33 | ++pub enum BootProtocol { |
| 34 | ++ /// Linux 64-bit boot protocol |
| 35 | ++ LinuxBoot, |
| 36 | ++ /// PVH boot protocol (x86/HVM direct boot ABI) |
| 37 | ++ PvhBoot, |
| 38 | ++} |
| 39 | ++ |
| 40 | ++impl fmt::Display for BootProtocol { |
| 41 | ++ fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { |
| 42 | ++ match self { |
| 43 | ++ BootProtocol::LinuxBoot => write!(f, "Linux 64-bit boot protocol"), |
| 44 | ++ BootProtocol::PvhBoot => write!(f, "PVH boot protocol"), |
| 45 | ++ } |
| 46 | ++ } |
| 47 | ++} |
| 48 | ++ |
| 49 | ++#[derive(Debug, Copy, Clone)] |
| 50 | ++/// Specifies the entry point address where the guest must start |
| 51 | ++/// executing code, as well as which boot protocol is to be used |
| 52 | ++/// to configure the guest initial state. |
| 53 | ++pub struct EntryPoint { |
| 54 | ++ /// Address in guest memory where the guest must start execution |
| 55 | ++ pub entry_addr: vm_memory::GuestAddress, |
| 56 | ++ /// Specifies which boot protocol to use |
| 57 | ++ pub protocol: BootProtocol, |
| 58 | ++} |
| 59 | +diff --git a/src/vmm/src/builder.rs b/src/vmm/src/builder.rs |
| 60 | +index 09506087..5c2828bc 100644 |
| 61 | +--- a/src/vmm/src/builder.rs |
| 62 | ++++ b/src/vmm/src/builder.rs |
| 63 | +@@ -9,7 +9,7 @@ use std::io::{self, Read, Seek, SeekFrom}; |
| 64 | + use std::os::unix::io::{AsRawFd, RawFd}; |
| 65 | + use std::sync::{Arc, Mutex}; |
| 66 | + |
| 67 | +-use arch::InitrdConfig; |
| 68 | ++use arch::{BootProtocol, EntryPoint, InitrdConfig}; |
| 69 | + #[cfg(target_arch = "x86_64")] |
| 70 | + use cpuid::common::is_same_model; |
| 71 | + use devices::legacy::serial::ReadableFd; |
| 72 | +@@ -22,6 +22,7 @@ use libc::EFD_NONBLOCK; |
| 73 | + use linux_loader::cmdline::Cmdline as LoaderKernelCmdline; |
| 74 | + #[cfg(target_arch = "x86_64")] |
| 75 | + use linux_loader::loader::elf::Elf as Loader; |
| 76 | ++use linux_loader::loader::elf::PvhBootCapability; |
| 77 | + #[cfg(target_arch = "aarch64")] |
| 78 | + use linux_loader::loader::pe::PE as Loader; |
| 79 | + use linux_loader::loader::KernelLoader; |
| 80 | +@@ -334,7 +335,7 @@ pub fn build_microvm_for_boot( |
| 81 | + let guest_memory = |
| 82 | + create_guest_memory(vm_resources.vm_config().mem_size_mib, track_dirty_pages)?; |
| 83 | + let vcpu_config = vm_resources.vcpu_config(); |
| 84 | +- let entry_addr = load_kernel(boot_config, &guest_memory)?; |
| 85 | ++ let entry_point = load_kernel(boot_config, &guest_memory)?; |
| 86 | + let initrd = load_initrd_from_config(boot_config, &guest_memory)?; |
| 87 | + // Clone the command-line so that a failed boot doesn't pollute the original. |
| 88 | + #[allow(unused_mut)] |
| 89 | +@@ -407,7 +408,7 @@ pub fn build_microvm_for_boot( |
| 90 | + &vmm, |
| 91 | + vcpus.as_mut(), |
| 92 | + vcpu_config, |
| 93 | +- entry_addr, |
| 94 | ++ entry_point.entry_addr, |
| 95 | + &initrd, |
| 96 | + boot_cmdline, |
| 97 | + )?; |
| 98 | +@@ -636,7 +637,7 @@ pub fn create_guest_memory( |
| 99 | + fn load_kernel( |
| 100 | + boot_config: &BootConfig, |
| 101 | + guest_memory: &GuestMemoryMmap, |
| 102 | +-) -> std::result::Result<GuestAddress, StartMicrovmError> { |
| 103 | ++) -> std::result::Result<EntryPoint, StartMicrovmError> { |
| 104 | + let mut kernel_file = boot_config |
| 105 | + .kernel_file |
| 106 | + .try_clone() |
| 107 | +@@ -660,7 +661,21 @@ fn load_kernel( |
| 108 | + ) |
| 109 | + .map_err(StartMicrovmError::KernelLoader)?; |
| 110 | + |
| 111 | +- Ok(entry_addr.kernel_load) |
| 112 | ++ let mut entry_point_addr: GuestAddress = entry_addr.kernel_load; |
| 113 | ++ let mut boot_prot: BootProtocol = BootProtocol::LinuxBoot; |
| 114 | ++ |
| 115 | ++ if cfg!(target_arch = "x86_64") { |
| 116 | ++ if let PvhBootCapability::PvhEntryPresent(pvh_entry_addr) = entry_addr.pvh_boot_cap { |
| 117 | ++ // Use the PVH kernel entry point to boot the guest |
| 118 | ++ entry_point_addr = pvh_entry_addr; |
| 119 | ++ boot_prot = BootProtocol::PvhBoot; |
| 120 | ++ } |
| 121 | ++ } |
| 122 | ++ |
| 123 | ++ Ok(EntryPoint { |
| 124 | ++ entry_addr: entry_point_addr, |
| 125 | ++ protocol: boot_prot, |
| 126 | ++ }) |
| 127 | + } |
| 128 | + |
| 129 | + fn load_initrd_from_config( |
| 130 | +-- |
| 131 | +2.38.1 |
| 132 | + |
0 commit comments