mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2024-10-01 11:05:46 +00:00
arch, vmm: Remove support for LinuxBoot
By supporting just PVH boot on x86-64 we simplify our boot path substatially. Fixes: #2231 Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
1f4a34ffc8
commit
da8136e49d
@ -98,8 +98,8 @@ pub mod x86_64;
|
|||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
pub use x86_64::{
|
pub use x86_64::{
|
||||||
arch_memory_regions, configure_system, configure_vcpu, get_host_cpu_phys_bits,
|
arch_memory_regions, configure_system, configure_vcpu, get_host_cpu_phys_bits,
|
||||||
initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, regs,
|
initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, regs, CpuidPatch,
|
||||||
BootProtocol, CpuidPatch, CpuidReg, EntryPoint,
|
CpuidReg, EntryPoint,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
|
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`.
|
||||||
|
@ -14,7 +14,7 @@ pub mod regs;
|
|||||||
use crate::InitramfsConfig;
|
use crate::InitramfsConfig;
|
||||||
use crate::RegionType;
|
use crate::RegionType;
|
||||||
use hypervisor::{CpuId, CpuIdEntry, CPUID_FLAG_VALID_INDEX};
|
use hypervisor::{CpuId, CpuIdEntry, CPUID_FLAG_VALID_INDEX};
|
||||||
use linux_loader::loader::bootparam::{boot_params, setup_header};
|
use linux_loader::loader::bootparam::boot_params;
|
||||||
use linux_loader::loader::elf::start_info::{
|
use linux_loader::loader::elf::start_info::{
|
||||||
hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info,
|
hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info,
|
||||||
};
|
};
|
||||||
@ -28,21 +28,6 @@ use std::arch::x86_64;
|
|||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
pub mod tdx;
|
pub mod tdx;
|
||||||
|
|
||||||
#[derive(Debug, Copy, Clone)]
|
|
||||||
pub enum BootProtocol {
|
|
||||||
LinuxBoot,
|
|
||||||
PvhBoot,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ::std::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)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
/// Specifies the entry point address where the guest must start
|
/// Specifies the entry point address where the guest must start
|
||||||
/// executing code, as well as which of the supported boot protocols
|
/// executing code, as well as which of the supported boot protocols
|
||||||
@ -50,10 +35,6 @@ impl ::std::fmt::Display for BootProtocol {
|
|||||||
pub struct EntryPoint {
|
pub struct EntryPoint {
|
||||||
/// Address in guest memory where the guest must start execution
|
/// Address in guest memory where the guest must start execution
|
||||||
pub entry_addr: GuestAddress,
|
pub entry_addr: GuestAddress,
|
||||||
/// Specifies which boot protocol to use
|
|
||||||
pub protocol: BootProtocol,
|
|
||||||
/// This field is used for bzImage to fill zero page
|
|
||||||
pub setup_header: Option<setup_header>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const E820_RAM: u32 = 1;
|
const E820_RAM: u32 = 1;
|
||||||
@ -351,17 +332,10 @@ pub fn configure_vcpu(
|
|||||||
regs::setup_msrs(fd).map_err(Error::MsrsConfiguration)?;
|
regs::setup_msrs(fd).map_err(Error::MsrsConfiguration)?;
|
||||||
if let Some(kernel_entry_point) = kernel_entry_point {
|
if let Some(kernel_entry_point) = kernel_entry_point {
|
||||||
// Safe to unwrap because this method is called after the VM is configured
|
// Safe to unwrap because this method is called after the VM is configured
|
||||||
regs::setup_regs(
|
regs::setup_regs(fd, kernel_entry_point.entry_addr.raw_value())
|
||||||
fd,
|
|
||||||
kernel_entry_point.entry_addr.raw_value(),
|
|
||||||
layout::BOOT_STACK_POINTER.raw_value(),
|
|
||||||
layout::ZERO_PAGE_START.raw_value(),
|
|
||||||
kernel_entry_point.protocol,
|
|
||||||
)
|
|
||||||
.map_err(Error::RegsConfiguration)?;
|
.map_err(Error::RegsConfiguration)?;
|
||||||
regs::setup_fpu(fd).map_err(Error::FpuConfiguration)?;
|
regs::setup_fpu(fd).map_err(Error::FpuConfiguration)?;
|
||||||
regs::setup_sregs(&vm_memory.memory(), fd, kernel_entry_point.protocol)
|
regs::setup_sregs(&vm_memory.memory(), fd).map_err(Error::SregsConfiguration)?;
|
||||||
.map_err(Error::SregsConfiguration)?;
|
|
||||||
}
|
}
|
||||||
interrupts::set_lint(fd).map_err(|e| Error::LocalIntConfiguration(e.into()))?;
|
interrupts::set_lint(fd).map_err(|e| Error::LocalIntConfiguration(e.into()))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
@ -426,12 +400,9 @@ pub fn arch_memory_regions(size: GuestUsize) -> Vec<(GuestAddress, usize, Region
|
|||||||
pub fn configure_system(
|
pub fn configure_system(
|
||||||
guest_mem: &GuestMemoryMmap,
|
guest_mem: &GuestMemoryMmap,
|
||||||
cmdline_addr: GuestAddress,
|
cmdline_addr: GuestAddress,
|
||||||
cmdline_size: usize,
|
|
||||||
initramfs: &Option<InitramfsConfig>,
|
initramfs: &Option<InitramfsConfig>,
|
||||||
_num_cpus: u8,
|
_num_cpus: u8,
|
||||||
setup_hdr: Option<setup_header>,
|
|
||||||
rsdp_addr: Option<GuestAddress>,
|
rsdp_addr: Option<GuestAddress>,
|
||||||
boot_prot: BootProtocol,
|
|
||||||
sgx_epc_region: Option<SgxEpcRegion>,
|
sgx_epc_region: Option<SgxEpcRegion>,
|
||||||
) -> super::Result<()> {
|
) -> super::Result<()> {
|
||||||
let size = smbios::setup_smbios(guest_mem).map_err(Error::SmbiosSetup)?;
|
let size = smbios::setup_smbios(guest_mem).map_err(Error::SmbiosSetup)?;
|
||||||
@ -448,31 +419,13 @@ pub fn configure_system(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match boot_prot {
|
|
||||||
BootProtocol::PvhBoot => {
|
|
||||||
configure_pvh(
|
configure_pvh(
|
||||||
guest_mem,
|
guest_mem,
|
||||||
cmdline_addr,
|
cmdline_addr,
|
||||||
initramfs,
|
initramfs,
|
||||||
rsdp_addr,
|
rsdp_addr,
|
||||||
sgx_epc_region,
|
sgx_epc_region,
|
||||||
)?;
|
)
|
||||||
}
|
|
||||||
BootProtocol::LinuxBoot => {
|
|
||||||
error!("Using deprecated LinuxBoot protocol: Please configure your kernel with CONFIG_PVH=y and supply the `vmlinux` file to `--kernel`");
|
|
||||||
configure_64bit_boot(
|
|
||||||
guest_mem,
|
|
||||||
cmdline_addr,
|
|
||||||
cmdline_size,
|
|
||||||
initramfs,
|
|
||||||
setup_hdr,
|
|
||||||
rsdp_addr,
|
|
||||||
sgx_epc_region,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure_pvh(
|
fn configure_pvh(
|
||||||
@ -615,121 +568,6 @@ fn add_memmap_entry(memmap: &mut Vec<hvm_memmap_table_entry>, addr: u64, size: u
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn configure_64bit_boot(
|
|
||||||
guest_mem: &GuestMemoryMmap,
|
|
||||||
cmdline_addr: GuestAddress,
|
|
||||||
cmdline_size: usize,
|
|
||||||
initramfs: &Option<InitramfsConfig>,
|
|
||||||
setup_hdr: Option<setup_header>,
|
|
||||||
rsdp_addr: Option<GuestAddress>,
|
|
||||||
sgx_epc_region: Option<SgxEpcRegion>,
|
|
||||||
) -> super::Result<()> {
|
|
||||||
const KERNEL_BOOT_FLAG_MAGIC: u16 = 0xaa55;
|
|
||||||
const KERNEL_HDR_MAGIC: u32 = 0x53726448;
|
|
||||||
const KERNEL_LOADER_OTHER: u8 = 0xff;
|
|
||||||
const KERNEL_MIN_ALIGNMENT_BYTES: u32 = 0x1000000; // Must be non-zero.
|
|
||||||
|
|
||||||
let mut params: BootParamsWrapper = BootParamsWrapper(boot_params::default());
|
|
||||||
|
|
||||||
if let Some(hdr) = setup_hdr {
|
|
||||||
// We should use the header if the loader provides one (e.g. from a bzImage).
|
|
||||||
params.0.hdr = hdr;
|
|
||||||
} else {
|
|
||||||
params.0.hdr.boot_flag = KERNEL_BOOT_FLAG_MAGIC;
|
|
||||||
params.0.hdr.header = KERNEL_HDR_MAGIC;
|
|
||||||
params.0.hdr.kernel_alignment = KERNEL_MIN_ALIGNMENT_BYTES;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Common bootparams settings
|
|
||||||
if params.0.hdr.type_of_loader == 0 {
|
|
||||||
params.0.hdr.type_of_loader = KERNEL_LOADER_OTHER;
|
|
||||||
}
|
|
||||||
params.0.hdr.cmd_line_ptr = cmdline_addr.raw_value() as u32;
|
|
||||||
params.0.hdr.cmdline_size = cmdline_size as u32;
|
|
||||||
|
|
||||||
if let Some(initramfs_config) = initramfs {
|
|
||||||
params.0.hdr.ramdisk_image = initramfs_config.address.raw_value() as u32;
|
|
||||||
params.0.hdr.ramdisk_size = initramfs_config.size as u32;
|
|
||||||
}
|
|
||||||
|
|
||||||
add_e820_entry(&mut params.0, 0, layout::EBDA_START.raw_value(), E820_RAM)?;
|
|
||||||
|
|
||||||
let mem_end = guest_mem.last_addr();
|
|
||||||
if mem_end < layout::MEM_32BIT_RESERVED_START {
|
|
||||||
add_e820_entry(
|
|
||||||
&mut params.0,
|
|
||||||
layout::HIGH_RAM_START.raw_value(),
|
|
||||||
mem_end.unchecked_offset_from(layout::HIGH_RAM_START) + 1,
|
|
||||||
E820_RAM,
|
|
||||||
)?;
|
|
||||||
} else {
|
|
||||||
add_e820_entry(
|
|
||||||
&mut params.0,
|
|
||||||
layout::HIGH_RAM_START.raw_value(),
|
|
||||||
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::HIGH_RAM_START),
|
|
||||||
E820_RAM,
|
|
||||||
)?;
|
|
||||||
if mem_end > layout::RAM_64BIT_START {
|
|
||||||
add_e820_entry(
|
|
||||||
&mut params.0,
|
|
||||||
layout::RAM_64BIT_START.raw_value(),
|
|
||||||
mem_end.unchecked_offset_from(layout::RAM_64BIT_START) + 1,
|
|
||||||
E820_RAM,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
add_e820_entry(
|
|
||||||
&mut params.0,
|
|
||||||
layout::PCI_MMCONFIG_START.0,
|
|
||||||
layout::PCI_MMCONFIG_SIZE,
|
|
||||||
E820_RESERVED,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
if let Some(sgx_epc_region) = sgx_epc_region {
|
|
||||||
add_e820_entry(
|
|
||||||
&mut params.0,
|
|
||||||
sgx_epc_region.start().raw_value(),
|
|
||||||
sgx_epc_region.size() as u64,
|
|
||||||
E820_RESERVED,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(rsdp_addr) = rsdp_addr {
|
|
||||||
params.0.acpi_rsdp_addr = rsdp_addr.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let zero_page_addr = layout::ZERO_PAGE_START;
|
|
||||||
guest_mem
|
|
||||||
.checked_offset(zero_page_addr, mem::size_of::<boot_params>())
|
|
||||||
.ok_or(super::Error::ZeroPagePastRamEnd)?;
|
|
||||||
guest_mem
|
|
||||||
.write_obj(params, zero_page_addr)
|
|
||||||
.map_err(super::Error::ZeroPageSetup)?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Add an e820 region to the e820 map.
|
|
||||||
/// Returns Ok(()) if successful, or an error if there is no space left in the map.
|
|
||||||
fn add_e820_entry(
|
|
||||||
params: &mut boot_params,
|
|
||||||
addr: u64,
|
|
||||||
size: u64,
|
|
||||||
mem_type: u32,
|
|
||||||
) -> Result<(), Error> {
|
|
||||||
if params.e820_entries >= params.e820_table.len() as u8 {
|
|
||||||
return Err(Error::E820Configuration);
|
|
||||||
}
|
|
||||||
|
|
||||||
params.e820_table[params.e820_entries as usize].addr = addr;
|
|
||||||
params.e820_table[params.e820_entries as usize].size = size;
|
|
||||||
params.e820_table[params.e820_entries as usize].type_ = mem_type;
|
|
||||||
params.e820_entries += 1;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the memory address where the initramfs could be loaded.
|
/// Returns the memory address where the initramfs could be loaded.
|
||||||
pub fn initramfs_load_addr(
|
pub fn initramfs_load_addr(
|
||||||
guest_mem: &GuestMemoryMmap,
|
guest_mem: &GuestMemoryMmap,
|
||||||
@ -888,7 +726,6 @@ pub fn update_cpuid_sgx(cpuid: &mut CpuId, epc_sections: Vec<SgxEpcSection>) ->
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use linux_loader::loader::bootparam::boot_e820_entry;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn regions_lt_4gb() {
|
fn regions_lt_4gb() {
|
||||||
@ -913,12 +750,9 @@ mod tests {
|
|||||||
let config_err = configure_system(
|
let config_err = configure_system(
|
||||||
&gm,
|
&gm,
|
||||||
GuestAddress(0),
|
GuestAddress(0),
|
||||||
0,
|
|
||||||
&None,
|
&None,
|
||||||
1,
|
1,
|
||||||
None,
|
|
||||||
Some(layout::RSDP_POINTER),
|
Some(layout::RSDP_POINTER),
|
||||||
BootProtocol::LinuxBoot,
|
|
||||||
None,
|
None,
|
||||||
);
|
);
|
||||||
assert!(config_err.is_err());
|
assert!(config_err.is_err());
|
||||||
@ -932,31 +766,8 @@ mod tests {
|
|||||||
.map(|r| (r.0, r.1))
|
.map(|r| (r.0, r.1))
|
||||||
.collect();
|
.collect();
|
||||||
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
||||||
configure_system(
|
|
||||||
&gm,
|
|
||||||
GuestAddress(0),
|
|
||||||
0,
|
|
||||||
&None,
|
|
||||||
no_vcpus,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
BootProtocol::LinuxBoot,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
configure_system(
|
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
|
||||||
&gm,
|
|
||||||
GuestAddress(0),
|
|
||||||
0,
|
|
||||||
&None,
|
|
||||||
no_vcpus,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
BootProtocol::PvhBoot,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Now assigning some memory that is equal to the start of the 32bit memory hole.
|
// Now assigning some memory that is equal to the start of the 32bit memory hole.
|
||||||
let mem_size = 3328 << 20;
|
let mem_size = 3328 << 20;
|
||||||
@ -967,31 +778,9 @@ mod tests {
|
|||||||
.map(|r| (r.0, r.1))
|
.map(|r| (r.0, r.1))
|
||||||
.collect();
|
.collect();
|
||||||
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
||||||
configure_system(
|
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
|
||||||
&gm,
|
|
||||||
GuestAddress(0),
|
|
||||||
0,
|
|
||||||
&None,
|
|
||||||
no_vcpus,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
BootProtocol::LinuxBoot,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
configure_system(
|
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
|
||||||
&gm,
|
|
||||||
GuestAddress(0),
|
|
||||||
0,
|
|
||||||
&None,
|
|
||||||
no_vcpus,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
BootProtocol::PvhBoot,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
// Now assigning some memory that falls after the 32bit memory hole.
|
// Now assigning some memory that falls after the 32bit memory hole.
|
||||||
let mem_size = 3330 << 20;
|
let mem_size = 3330 << 20;
|
||||||
@ -1002,71 +791,9 @@ mod tests {
|
|||||||
.map(|r| (r.0, r.1))
|
.map(|r| (r.0, r.1))
|
||||||
.collect();
|
.collect();
|
||||||
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
let gm = GuestMemoryMmap::from_ranges(&ram_regions).unwrap();
|
||||||
configure_system(
|
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
|
||||||
&gm,
|
|
||||||
GuestAddress(0),
|
|
||||||
0,
|
|
||||||
&None,
|
|
||||||
no_vcpus,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
BootProtocol::LinuxBoot,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
configure_system(
|
configure_system(&gm, GuestAddress(0), &None, no_vcpus, None, None).unwrap();
|
||||||
&gm,
|
|
||||||
GuestAddress(0),
|
|
||||||
0,
|
|
||||||
&None,
|
|
||||||
no_vcpus,
|
|
||||||
None,
|
|
||||||
None,
|
|
||||||
BootProtocol::PvhBoot,
|
|
||||||
None,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_add_e820_entry() {
|
|
||||||
let e820_table = [(boot_e820_entry {
|
|
||||||
addr: 0x1,
|
|
||||||
size: 4,
|
|
||||||
type_: 1,
|
|
||||||
}); 128];
|
|
||||||
|
|
||||||
let expected_params = boot_params {
|
|
||||||
e820_table,
|
|
||||||
e820_entries: 1,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let mut params: boot_params = Default::default();
|
|
||||||
add_e820_entry(
|
|
||||||
&mut params,
|
|
||||||
e820_table[0].addr,
|
|
||||||
e820_table[0].size,
|
|
||||||
e820_table[0].type_,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(
|
|
||||||
format!("{:?}", params.e820_table[0]),
|
|
||||||
format!("{:?}", expected_params.e820_table[0])
|
|
||||||
);
|
|
||||||
assert_eq!(params.e820_entries, expected_params.e820_entries);
|
|
||||||
|
|
||||||
// Exercise the scenario where the field storing the length of the e820 entry table is
|
|
||||||
// is bigger than the allocated memory.
|
|
||||||
params.e820_entries = params.e820_table.len() as u8 + 1;
|
|
||||||
assert!(add_e820_entry(
|
|
||||||
&mut params,
|
|
||||||
e820_table[0].addr,
|
|
||||||
e820_table[0].size,
|
|
||||||
e820_table[0].type_
|
|
||||||
)
|
|
||||||
.is_err());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
@ -9,13 +9,10 @@
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::{mem, result};
|
use std::{mem, result};
|
||||||
|
|
||||||
use super::BootProtocol;
|
|
||||||
use hypervisor::arch::x86::gdt::{gdt_entry, segment_from_gdt};
|
use hypervisor::arch::x86::gdt::{gdt_entry, segment_from_gdt};
|
||||||
use hypervisor::arch::x86::regs::*;
|
use hypervisor::arch::x86::regs::*;
|
||||||
use hypervisor::x86_64::{FpuState, SpecialRegisters, StandardRegisters};
|
use hypervisor::x86_64::{FpuState, SpecialRegisters, StandardRegisters};
|
||||||
use layout::{
|
use layout::{BOOT_GDT_START, BOOT_IDT_START, PVH_INFO_START};
|
||||||
BOOT_GDT_START, BOOT_IDT_START, PDE_START, PDPTE_START, PML4_START, PML5_START, PVH_INFO_START,
|
|
||||||
};
|
|
||||||
use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError, GuestMemoryMmap};
|
use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError, GuestMemoryMmap};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@ -81,32 +78,12 @@ pub fn setup_msrs(vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
|
|||||||
///
|
///
|
||||||
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
|
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
|
||||||
/// * `boot_ip` - Starting instruction pointer.
|
/// * `boot_ip` - Starting instruction pointer.
|
||||||
/// * `boot_sp` - Starting stack pointer.
|
pub fn setup_regs(vcpu: &Arc<dyn hypervisor::Vcpu>, boot_ip: u64) -> Result<()> {
|
||||||
/// * `boot_si` - Must point to zero page address per Linux ABI.
|
let regs = StandardRegisters {
|
||||||
pub fn setup_regs(
|
|
||||||
vcpu: &Arc<dyn hypervisor::Vcpu>,
|
|
||||||
boot_ip: u64,
|
|
||||||
boot_sp: u64,
|
|
||||||
boot_si: u64,
|
|
||||||
boot_prot: BootProtocol,
|
|
||||||
) -> Result<()> {
|
|
||||||
let regs: StandardRegisters = match boot_prot {
|
|
||||||
// Configure regs as required by PVH boot protocol.
|
|
||||||
BootProtocol::PvhBoot => StandardRegisters {
|
|
||||||
rflags: 0x0000000000000002u64,
|
rflags: 0x0000000000000002u64,
|
||||||
rbx: PVH_INFO_START.raw_value(),
|
rbx: PVH_INFO_START.raw_value(),
|
||||||
rip: boot_ip,
|
rip: boot_ip,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
|
||||||
// Configure regs as required by Linux 64-bit boot protocol.
|
|
||||||
BootProtocol::LinuxBoot => StandardRegisters {
|
|
||||||
rflags: 0x0000000000000002u64,
|
|
||||||
rip: boot_ip,
|
|
||||||
rsp: boot_sp,
|
|
||||||
rbp: boot_sp,
|
|
||||||
rsi: boot_si,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
vcpu.set_regs(®s).map_err(Error::SetBaseRegisters)
|
vcpu.set_regs(®s).map_err(Error::SetBaseRegisters)
|
||||||
}
|
}
|
||||||
@ -117,19 +94,9 @@ pub fn setup_regs(
|
|||||||
///
|
///
|
||||||
/// * `mem` - The memory that will be passed to the guest.
|
/// * `mem` - The memory that will be passed to the guest.
|
||||||
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
|
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
|
||||||
pub fn setup_sregs(
|
pub fn setup_sregs(mem: &GuestMemoryMmap, vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
|
||||||
mem: &GuestMemoryMmap,
|
|
||||||
vcpu: &Arc<dyn hypervisor::Vcpu>,
|
|
||||||
boot_prot: BootProtocol,
|
|
||||||
) -> Result<()> {
|
|
||||||
let mut sregs: SpecialRegisters = vcpu.get_sregs().map_err(Error::GetStatusRegisters)?;
|
let mut sregs: SpecialRegisters = vcpu.get_sregs().map_err(Error::GetStatusRegisters)?;
|
||||||
|
configure_segments_and_sregs(mem, &mut sregs)?;
|
||||||
configure_segments_and_sregs(mem, &mut sregs, boot_prot)?;
|
|
||||||
|
|
||||||
if let BootProtocol::LinuxBoot = boot_prot {
|
|
||||||
setup_page_tables(mem, &mut sregs)?; // TODO(dgreid) - Can this be done once per system instead?
|
|
||||||
}
|
|
||||||
|
|
||||||
vcpu.set_sregs(&sregs).map_err(Error::SetStatusRegisters)
|
vcpu.set_sregs(&sregs).map_err(Error::SetStatusRegisters)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,10 +123,8 @@ fn write_idt_value(val: u64, guest_mem: &GuestMemoryMmap) -> Result<()> {
|
|||||||
pub fn configure_segments_and_sregs(
|
pub fn configure_segments_and_sregs(
|
||||||
mem: &GuestMemoryMmap,
|
mem: &GuestMemoryMmap,
|
||||||
sregs: &mut SpecialRegisters,
|
sregs: &mut SpecialRegisters,
|
||||||
boot_prot: BootProtocol,
|
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
let gdt_table: [u64; BOOT_GDT_MAX as usize] = match boot_prot {
|
let gdt_table: [u64; BOOT_GDT_MAX as usize] = {
|
||||||
BootProtocol::PvhBoot => {
|
|
||||||
// Configure GDT entries as specified by PVH boot protocol
|
// Configure GDT entries as specified by PVH boot protocol
|
||||||
[
|
[
|
||||||
gdt_entry(0, 0, 0), // NULL
|
gdt_entry(0, 0, 0), // NULL
|
||||||
@ -167,16 +132,6 @@ pub fn configure_segments_and_sregs(
|
|||||||
gdt_entry(0xc093, 0, 0xffffffff), // DATA
|
gdt_entry(0xc093, 0, 0xffffffff), // DATA
|
||||||
gdt_entry(0x008b, 0, 0x67), // TSS
|
gdt_entry(0x008b, 0, 0x67), // TSS
|
||||||
]
|
]
|
||||||
}
|
|
||||||
BootProtocol::LinuxBoot => {
|
|
||||||
// Configure GDT entries as specified by Linux 64bit boot protocol
|
|
||||||
[
|
|
||||||
gdt_entry(0, 0, 0), // NULL
|
|
||||||
gdt_entry(0xa09b, 0, 0xfffff), // CODE
|
|
||||||
gdt_entry(0xc093, 0, 0xfffff), // DATA
|
|
||||||
gdt_entry(0x808b, 0, 0xfffff), // TSS
|
|
||||||
]
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let code_seg = segment_from_gdt(gdt_table[1], 1);
|
let code_seg = segment_from_gdt(gdt_table[1], 1);
|
||||||
@ -200,51 +155,8 @@ pub fn configure_segments_and_sregs(
|
|||||||
sregs.ss = data_seg;
|
sregs.ss = data_seg;
|
||||||
sregs.tr = tss_seg;
|
sregs.tr = tss_seg;
|
||||||
|
|
||||||
match boot_prot {
|
|
||||||
BootProtocol::PvhBoot => {
|
|
||||||
sregs.cr0 = CR0_PE;
|
sregs.cr0 = CR0_PE;
|
||||||
sregs.cr4 = 0;
|
sregs.cr4 = 0;
|
||||||
}
|
|
||||||
BootProtocol::LinuxBoot => {
|
|
||||||
/* 64-bit protected mode */
|
|
||||||
sregs.cr0 |= CR0_PE;
|
|
||||||
sregs.efer |= EFER_LME | EFER_LMA;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn setup_page_tables(mem: &GuestMemoryMmap, sregs: &mut SpecialRegisters) -> Result<()> {
|
|
||||||
// Puts PML5 or PML4 right after zero page but aligned to 4k.
|
|
||||||
if unsafe { std::arch::x86_64::__cpuid(7).ecx } & (1 << 16) != 0 {
|
|
||||||
// Entry covering VA [0..256TB)
|
|
||||||
mem.write_obj(PML4_START.raw_value() | 0x03, PML5_START)
|
|
||||||
.map_err(Error::WritePml5Address)?;
|
|
||||||
|
|
||||||
sregs.cr3 = PML5_START.raw_value();
|
|
||||||
sregs.cr4 |= CR4_LA57;
|
|
||||||
} else {
|
|
||||||
sregs.cr3 = PML4_START.raw_value();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Entry covering VA [0..512GB)
|
|
||||||
mem.write_obj(PDPTE_START.raw_value() | 0x03, PML4_START)
|
|
||||||
.map_err(Error::WritePml4Address)?;
|
|
||||||
|
|
||||||
// Entry covering VA [0..1GB)
|
|
||||||
mem.write_obj(PDE_START.raw_value() | 0x03, PDPTE_START)
|
|
||||||
.map_err(Error::WritePdpteAddress)?;
|
|
||||||
|
|
||||||
// 512 2MB entries together covering VA [0..1GB). Note we are assuming
|
|
||||||
// CPU supports 2MB pages (/proc/cpuinfo has 'pse'). All modern CPUs do.
|
|
||||||
for i in 0..512 {
|
|
||||||
mem.write_obj((i << 21) + 0x83u64, PDE_START.unchecked_add(i * 8))
|
|
||||||
.map_err(Error::WritePdeAddress)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
sregs.cr4 |= CR4_PAE;
|
|
||||||
sregs.cr0 |= CR0_PG;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -268,36 +180,7 @@ mod tests {
|
|||||||
fn segments_and_sregs() {
|
fn segments_and_sregs() {
|
||||||
let mut sregs: SpecialRegisters = Default::default();
|
let mut sregs: SpecialRegisters = Default::default();
|
||||||
let gm = create_guest_mem();
|
let gm = create_guest_mem();
|
||||||
configure_segments_and_sregs(&gm, &mut sregs, BootProtocol::LinuxBoot).unwrap();
|
configure_segments_and_sregs(&gm, &mut sregs).unwrap();
|
||||||
|
|
||||||
assert_eq!(0x0, read_u64(&gm, BOOT_GDT_START));
|
|
||||||
assert_eq!(
|
|
||||||
0xaf9b000000ffff,
|
|
||||||
read_u64(&gm, BOOT_GDT_START.unchecked_add(8))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
0xcf93000000ffff,
|
|
||||||
read_u64(&gm, BOOT_GDT_START.unchecked_add(16))
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
0x8f8b000000ffff,
|
|
||||||
read_u64(&gm, BOOT_GDT_START.unchecked_add(24))
|
|
||||||
);
|
|
||||||
assert_eq!(0x0, read_u64(&gm, BOOT_IDT_START));
|
|
||||||
|
|
||||||
assert_eq!(0, sregs.cs.base);
|
|
||||||
assert_eq!(0xffffffff, sregs.ds.limit);
|
|
||||||
assert_eq!(0x10, sregs.es.selector);
|
|
||||||
assert_eq!(1, sregs.fs.present);
|
|
||||||
assert_eq!(1, sregs.gs.g);
|
|
||||||
assert_eq!(0, sregs.ss.avl);
|
|
||||||
assert_eq!(0, sregs.tr.base);
|
|
||||||
assert_eq!(0xffffffff, sregs.tr.limit);
|
|
||||||
assert_eq!(0, sregs.tr.avl);
|
|
||||||
assert_eq!(CR0_PE, sregs.cr0);
|
|
||||||
assert_eq!(EFER_LME | EFER_LMA, sregs.efer);
|
|
||||||
|
|
||||||
configure_segments_and_sregs(&gm, &mut sregs, BootProtocol::PvhBoot).unwrap();
|
|
||||||
assert_eq!(0x0, read_u64(&gm, BOOT_GDT_START));
|
assert_eq!(0x0, read_u64(&gm, BOOT_GDT_START));
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
0xcf9b000000ffff,
|
0xcf9b000000ffff,
|
||||||
@ -327,31 +210,4 @@ mod tests {
|
|||||||
assert_eq!(CR0_PE, sregs.cr0);
|
assert_eq!(CR0_PE, sregs.cr0);
|
||||||
assert_eq!(0, sregs.cr4);
|
assert_eq!(0, sregs.cr4);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn page_tables() {
|
|
||||||
let mut sregs: SpecialRegisters = Default::default();
|
|
||||||
let gm = create_guest_mem();
|
|
||||||
setup_page_tables(&gm, &mut sregs).unwrap();
|
|
||||||
|
|
||||||
if unsafe { std::arch::x86_64::__cpuid(7).ecx } & (1 << 16) != 0 {
|
|
||||||
assert_eq!(0xa003, read_u64(&gm, PML5_START));
|
|
||||||
}
|
|
||||||
assert_eq!(0xb003, read_u64(&gm, PML4_START));
|
|
||||||
assert_eq!(0xc003, read_u64(&gm, PDPTE_START));
|
|
||||||
for i in 0..512 {
|
|
||||||
assert_eq!(
|
|
||||||
(i << 21) + 0x83u64,
|
|
||||||
read_u64(&gm, PDE_START.unchecked_add(i * 8))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if unsafe { std::arch::x86_64::__cpuid(7).ecx } & (1 << 16) != 0 {
|
|
||||||
assert_eq!(PML5_START.raw_value(), sregs.cr3);
|
|
||||||
} else {
|
|
||||||
assert_eq!(PML4_START.raw_value(), sregs.cr3);
|
|
||||||
}
|
|
||||||
assert_eq!(CR4_PAE, sregs.cr4);
|
|
||||||
assert_eq!(CR0_PG, sregs.cr0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -194,7 +194,7 @@ fn create_app<'a, 'b>(
|
|||||||
.long("kernel")
|
.long("kernel")
|
||||||
.help(
|
.help(
|
||||||
"Path to loaded kernel. This may be a kernel or firmware that supports a PVH \
|
"Path to loaded kernel. This may be a kernel or firmware that supports a PVH \
|
||||||
entry point, a vmlinux ELF file or a Linux bzImage or achitecture equivalent",
|
entry point (e.g. vmlinux) or architecture equivalent",
|
||||||
)
|
)
|
||||||
.takes_value(true)
|
.takes_value(true)
|
||||||
.group("vm-config"),
|
.group("vm-config"),
|
||||||
|
@ -1558,13 +1558,9 @@ impl Migratable for CpuManager {}
|
|||||||
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
#[cfg(all(feature = "kvm", target_arch = "x86_64"))]
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use super::*;
|
|
||||||
use arch::x86_64::interrupts::*;
|
use arch::x86_64::interrupts::*;
|
||||||
use arch::x86_64::regs::*;
|
use arch::x86_64::regs::*;
|
||||||
use arch::x86_64::BootProtocol;
|
use hypervisor::x86_64::{FpuState, LapicState, StandardRegisters};
|
||||||
use hypervisor::x86_64::{FpuState, LapicState, SpecialRegisters, StandardRegisters};
|
|
||||||
use vm_memory::GuestAddress;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_setlint() {
|
fn test_setlint() {
|
||||||
@ -1652,41 +1648,16 @@ mod tests {
|
|||||||
|
|
||||||
let expected_regs: StandardRegisters = StandardRegisters {
|
let expected_regs: StandardRegisters = StandardRegisters {
|
||||||
rflags: 0x0000000000000002u64,
|
rflags: 0x0000000000000002u64,
|
||||||
|
rbx: arch::layout::PVH_INFO_START.0,
|
||||||
rip: 1,
|
rip: 1,
|
||||||
rsp: 2,
|
|
||||||
rbp: 2,
|
|
||||||
rsi: 3,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
setup_regs(
|
setup_regs(&vcpu, expected_regs.rip).unwrap();
|
||||||
&vcpu,
|
|
||||||
expected_regs.rip,
|
|
||||||
expected_regs.rsp,
|
|
||||||
expected_regs.rsi,
|
|
||||||
BootProtocol::LinuxBoot,
|
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let actual_regs: StandardRegisters = vcpu.get_regs().unwrap();
|
let actual_regs: StandardRegisters = vcpu.get_regs().unwrap();
|
||||||
assert_eq!(actual_regs, expected_regs);
|
assert_eq!(actual_regs, expected_regs);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_setup_sregs() {
|
|
||||||
let hv = hypervisor::new().unwrap();
|
|
||||||
let vm = hv.create_vm().expect("new VM fd creation failed");
|
|
||||||
let vcpu = vm.create_vcpu(0, None).unwrap();
|
|
||||||
|
|
||||||
let mut expected_sregs: SpecialRegisters = vcpu.get_sregs().unwrap();
|
|
||||||
let gm = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
|
|
||||||
configure_segments_and_sregs(&gm, &mut expected_sregs, BootProtocol::LinuxBoot).unwrap();
|
|
||||||
setup_page_tables(&gm, &mut expected_sregs).unwrap();
|
|
||||||
|
|
||||||
setup_sregs(&gm, &vcpu, BootProtocol::LinuxBoot).unwrap();
|
|
||||||
let actual_sregs: SpecialRegisters = vcpu.get_sregs().unwrap();
|
|
||||||
assert_eq!(expected_sregs, actual_sregs);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
|
@ -41,15 +41,11 @@ use crate::{
|
|||||||
};
|
};
|
||||||
use anyhow::anyhow;
|
use anyhow::anyhow;
|
||||||
use arch::get_host_cpu_phys_bits;
|
use arch::get_host_cpu_phys_bits;
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
use arch::BootProtocol;
|
|
||||||
use arch::EntryPoint;
|
use arch::EntryPoint;
|
||||||
use devices::AcpiNotificationFlags;
|
use devices::AcpiNotificationFlags;
|
||||||
use hypervisor::vm::{HypervisorVmError, VmmOps};
|
use hypervisor::vm::{HypervisorVmError, VmmOps};
|
||||||
use linux_loader::cmdline::Cmdline;
|
use linux_loader::cmdline::Cmdline;
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
use linux_loader::loader::elf::Error::InvalidElfMagicNumber;
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
use linux_loader::loader::elf::PvhBootCapability::PvhEntryPresent;
|
use linux_loader::loader::elf::PvhBootCapability::PvhEntryPresent;
|
||||||
use linux_loader::loader::KernelLoader;
|
use linux_loader::loader::KernelLoader;
|
||||||
use seccomp::{SeccompAction, SeccompFilter};
|
use seccomp::{SeccompAction, SeccompFilter};
|
||||||
@ -89,10 +85,6 @@ use arch::aarch64::gic::gicv3::kvm::{KvmGicV3, GIC_V3_SNAPSHOT_ID};
|
|||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
use arch::aarch64::gic::kvm::create_gic;
|
use arch::aarch64::gic::kvm::create_gic;
|
||||||
|
|
||||||
// 64 bit direct boot entry offset for bzImage
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
|
||||||
const KERNEL_64BIT_ENTRY_OFFSET: u64 = 0x200;
|
|
||||||
|
|
||||||
/// Errors associated with VM management
|
/// Errors associated with VM management
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
@ -245,6 +237,9 @@ pub enum Error {
|
|||||||
/// Error triggering power button
|
/// Error triggering power button
|
||||||
PowerButton(device_manager::DeviceManagerError),
|
PowerButton(device_manager::DeviceManagerError),
|
||||||
|
|
||||||
|
/// Kernel lacks PVH header
|
||||||
|
KernelMissingPvhHeader,
|
||||||
|
|
||||||
/// Error doing I/O on TDX firmware file
|
/// Error doing I/O on TDX firmware file
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
LoadTdvf(std::io::Error),
|
LoadTdvf(std::io::Error),
|
||||||
@ -924,15 +919,6 @@ impl Vm {
|
|||||||
Some(arch::layout::HIGH_RAM_START),
|
Some(arch::layout::HIGH_RAM_START),
|
||||||
) {
|
) {
|
||||||
Ok(entry_addr) => entry_addr,
|
Ok(entry_addr) => entry_addr,
|
||||||
Err(linux_loader::loader::Error::Elf(InvalidElfMagicNumber)) => {
|
|
||||||
linux_loader::loader::bzimage::BzImage::load(
|
|
||||||
mem.deref(),
|
|
||||||
None,
|
|
||||||
&mut kernel,
|
|
||||||
Some(arch::layout::HIGH_RAM_START),
|
|
||||||
)
|
|
||||||
.map_err(Error::KernelLoad)?
|
|
||||||
}
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
return Err(Error::KernelLoad(e));
|
return Err(Error::KernelLoad(e));
|
||||||
}
|
}
|
||||||
@ -945,43 +931,20 @@ impl Vm {
|
|||||||
)
|
)
|
||||||
.map_err(Error::LoadCmdLine)?;
|
.map_err(Error::LoadCmdLine)?;
|
||||||
|
|
||||||
if entry_addr.setup_header.is_some() {
|
|
||||||
let load_addr = entry_addr
|
|
||||||
.kernel_load
|
|
||||||
.raw_value()
|
|
||||||
.checked_add(KERNEL_64BIT_ENTRY_OFFSET)
|
|
||||||
.ok_or(Error::MemOverflow)?;
|
|
||||||
|
|
||||||
Ok(EntryPoint {
|
|
||||||
entry_addr: GuestAddress(load_addr),
|
|
||||||
protocol: BootProtocol::LinuxBoot,
|
|
||||||
setup_header: entry_addr.setup_header,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
let entry_point_addr: GuestAddress;
|
|
||||||
let boot_prot: BootProtocol;
|
|
||||||
|
|
||||||
if let PvhEntryPresent(pvh_entry_addr) = entry_addr.pvh_boot_cap {
|
if let PvhEntryPresent(pvh_entry_addr) = entry_addr.pvh_boot_cap {
|
||||||
// Use the PVH kernel entry point to boot the guest
|
// Use the PVH kernel entry point to boot the guest
|
||||||
|
let entry_point_addr: GuestAddress;
|
||||||
entry_point_addr = pvh_entry_addr;
|
entry_point_addr = pvh_entry_addr;
|
||||||
boot_prot = BootProtocol::PvhBoot;
|
|
||||||
} else {
|
|
||||||
// Use the Linux 64-bit boot protocol
|
|
||||||
entry_point_addr = entry_addr.kernel_load;
|
|
||||||
boot_prot = BootProtocol::LinuxBoot;
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(EntryPoint {
|
Ok(EntryPoint {
|
||||||
entry_addr: entry_point_addr,
|
entry_addr: entry_point_addr,
|
||||||
protocol: boot_prot,
|
|
||||||
setup_header: None,
|
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
Err(Error::KernelMissingPvhHeader)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "x86_64")]
|
#[cfg(target_arch = "x86_64")]
|
||||||
fn configure_system(&mut self, entry_addr: EntryPoint) -> Result<()> {
|
fn configure_system(&mut self) -> Result<()> {
|
||||||
let cmdline_cstring = self.get_cmdline()?;
|
|
||||||
let mem = self.memory_manager.lock().unwrap().boot_guest_memory();
|
let mem = self.memory_manager.lock().unwrap().boot_guest_memory();
|
||||||
|
|
||||||
let initramfs_config = match self.initramfs {
|
let initramfs_config = match self.initramfs {
|
||||||
@ -1013,41 +976,20 @@ impl Vm {
|
|||||||
.as_ref()
|
.as_ref()
|
||||||
.cloned();
|
.cloned();
|
||||||
|
|
||||||
match entry_addr.setup_header {
|
|
||||||
Some(hdr) => {
|
|
||||||
arch::configure_system(
|
arch::configure_system(
|
||||||
&mem,
|
&mem,
|
||||||
arch::layout::CMDLINE_START,
|
arch::layout::CMDLINE_START,
|
||||||
cmdline_cstring.to_bytes().len() + 1,
|
|
||||||
&initramfs_config,
|
&initramfs_config,
|
||||||
boot_vcpus,
|
boot_vcpus,
|
||||||
Some(hdr),
|
|
||||||
rsdp_addr,
|
rsdp_addr,
|
||||||
BootProtocol::LinuxBoot,
|
|
||||||
sgx_epc_region,
|
sgx_epc_region,
|
||||||
)
|
)
|
||||||
.map_err(Error::ConfigureSystem)?;
|
.map_err(Error::ConfigureSystem)?;
|
||||||
}
|
|
||||||
None => {
|
|
||||||
arch::configure_system(
|
|
||||||
&mem,
|
|
||||||
arch::layout::CMDLINE_START,
|
|
||||||
cmdline_cstring.to_bytes().len() + 1,
|
|
||||||
&initramfs_config,
|
|
||||||
boot_vcpus,
|
|
||||||
None,
|
|
||||||
rsdp_addr,
|
|
||||||
entry_addr.protocol,
|
|
||||||
sgx_epc_region,
|
|
||||||
)
|
|
||||||
.map_err(Error::ConfigureSystem)?;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_arch = "aarch64")]
|
#[cfg(target_arch = "aarch64")]
|
||||||
fn configure_system(&mut self, _entry_addr: EntryPoint) -> Result<()> {
|
fn configure_system(&mut self) -> Result<()> {
|
||||||
let cmdline_cstring = self.get_cmdline()?;
|
let cmdline_cstring = self.get_cmdline()?;
|
||||||
let vcpu_mpidrs = self.cpu_manager.lock().unwrap().get_mpidrs();
|
let vcpu_mpidrs = self.cpu_manager.lock().unwrap().get_mpidrs();
|
||||||
let mem = self.memory_manager.lock().unwrap().boot_guest_memory();
|
let mem = self.memory_manager.lock().unwrap().boot_guest_memory();
|
||||||
@ -1715,9 +1657,7 @@ impl Vm {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Configure shared state based on loaded kernel
|
// Configure shared state based on loaded kernel
|
||||||
entry_point
|
entry_point.map(|_| self.configure_system()).transpose()?;
|
||||||
.map(|entry_point| self.configure_system(entry_point))
|
|
||||||
.transpose()?;
|
|
||||||
|
|
||||||
#[cfg(feature = "tdx")]
|
#[cfg(feature = "tdx")]
|
||||||
if let Some(hob_address) = hob_address {
|
if let Some(hob_address) = hob_address {
|
||||||
|
Loading…
Reference in New Issue
Block a user