From 429b53a67209ee0040f7c03d2c494dae8992e3e4 Mon Sep 17 00:00:00 2001 From: Cathy Zhang Date: Mon, 10 Jun 2019 17:14:02 +0800 Subject: [PATCH] vmm: Add bzimage loader support VMM may load different format kernel image to start guest, we currently only have elf loader support, so add bzimage loader support in case that VMM would like to load bzimage. Signed-off-by: Cathy Zhang --- arch/Cargo.toml | 4 +++ arch/src/lib.rs | 1 + arch/src/x86_64/mod.rs | 21 +++++++++----- vmm/Cargo.toml | 2 +- vmm/src/vm.rs | 62 ++++++++++++++++++++++++++++++++++-------- 5 files changed, 71 insertions(+), 19 deletions(-) diff --git a/arch/Cargo.toml b/arch/Cargo.toml index 1e62413ab..e973cc07b 100644 --- a/arch/Cargo.toml +++ b/arch/Cargo.toml @@ -15,5 +15,9 @@ arch_gen = { path = "../arch_gen" } git = "https://github.com/rust-vmm/vm-memory" features = ["backend-mmap"] +[dependencies.linux-loader] +git = "https://github.com/bjzhjing/linux-loader" +features = ["elf", "bzimage"] + [dev-dependencies] rand = ">=0.5.5" diff --git a/arch/src/lib.rs b/arch/src/lib.rs index 6e9eb4a94..85f041ce3 100644 --- a/arch/src/lib.rs +++ b/arch/src/lib.rs @@ -15,6 +15,7 @@ extern crate libc; extern crate arch_gen; extern crate kvm_ioctls; +extern crate linux_loader; extern crate vm_memory; use std::result; diff --git a/arch/src/x86_64/mod.rs b/arch/src/x86_64/mod.rs index 65223de62..220a00211 100644 --- a/arch/src/x86_64/mod.rs +++ b/arch/src/x86_64/mod.rs @@ -13,7 +13,7 @@ pub mod regs; use std::mem; -use arch_gen::x86::bootparam::{boot_params, E820_RAM}; +use linux_loader::loader::bootparam::{boot_params, setup_header, E820_RAM}; use vm_memory::{ Address, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap, GuestUsize, }; @@ -95,6 +95,7 @@ pub fn configure_system( cmdline_addr: GuestAddress, cmdline_size: usize, num_cpus: u8, + setup_hdr: Option, ) -> super::Result<()> { const KERNEL_BOOT_FLAG_MAGIC: u16 = 0xaa55; const KERNEL_HDR_MAGIC: u32 = 0x53726448; @@ -110,12 +111,18 @@ pub fn configure_system( let mut params: BootParamsWrapper = BootParamsWrapper(boot_params::default()); - params.0.hdr.type_of_loader = KERNEL_LOADER_OTHER; - params.0.hdr.boot_flag = KERNEL_BOOT_FLAG_MAGIC; - params.0.hdr.header = KERNEL_HDR_MAGIC; - params.0.hdr.cmd_line_ptr = cmdline_addr.raw_value() as u32; - params.0.hdr.cmdline_size = cmdline_size as u32; - params.0.hdr.kernel_alignment = KERNEL_MIN_ALIGNMENT_BYTES; + if setup_hdr.is_some() { + params.0.hdr = setup_hdr.unwrap(); + params.0.hdr.cmd_line_ptr = cmdline_addr.raw_value() as u32; + params.0.hdr.cmdline_size = cmdline_size as u32; + } else { + params.0.hdr.type_of_loader = KERNEL_LOADER_OTHER; + params.0.hdr.boot_flag = KERNEL_BOOT_FLAG_MAGIC; + params.0.hdr.header = KERNEL_HDR_MAGIC; + params.0.hdr.cmd_line_ptr = cmdline_addr.raw_value() as u32; + params.0.hdr.cmdline_size = cmdline_size as u32; + params.0.hdr.kernel_alignment = KERNEL_MIN_ALIGNMENT_BYTES; + }; add_e820_entry(&mut params.0, 0, EBDA_START.raw_value(), E820_RAM)?; diff --git a/vmm/Cargo.toml b/vmm/Cargo.toml index ad513671e..084891d0b 100755 --- a/vmm/Cargo.toml +++ b/vmm/Cargo.toml @@ -21,7 +21,7 @@ vmm-sys-util = { git = "https://github.com/rust-vmm/vmm-sys-util" } [dependencies.linux-loader] git = "https://github.com/bjzhjing/linux-loader" -features = ["elf"] +features = ["elf", "bzimage"] [dependencies.vm-memory] git = "https://github.com/rust-vmm/vm-memory" diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index d14b8dbed..e5a6c00e9 100755 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -55,6 +55,9 @@ const DEFAULT_MSIX_VEC_NUM: u16 = 2; const TSC_DEADLINE_TIMER_ECX_BIT: u8 = 24; // tsc deadline timer ecx bit. const HYPERVISOR_ECX_BIT: u8 = 31; // Hypervisor ecx bit. +// 64 bit direct boot entry offset for bzImage +const KERNEL_64BIT_ENTRY_OFFSET: u64 = 0x200; + /// Errors associated with VM management #[derive(Debug)] pub enum Error { @@ -143,6 +146,9 @@ pub enum Error { /// Unexpected KVM_RUN exit reason VcpuUnhandledKvmExit, + + /// Memory is overflow + MemOverflow, } pub type Result = result::Result; @@ -797,13 +803,24 @@ impl<'a> Vm<'a> { pub fn load_kernel(&mut self) -> Result { let cmdline_cstring = CString::new(self.config.cmdline.args.clone()).map_err(|_| Error::CmdLine)?; - let entry_addr = linux_loader::loader::Elf::load( + let entry_addr = match linux_loader::loader::Elf::load( &self.memory, None, &mut self.kernel, Some(arch::HIMEM_START), - ) - .map_err(Error::KernelLoad)?; + ) { + Ok(entry_addr) => entry_addr, + Err(linux_loader::loader::Error::InvalidElfMagicNumber) => { + linux_loader::loader::BzImage::load( + &self.memory, + None, + &mut self.kernel, + Some(arch::HIMEM_START), + ) + .map_err(Error::KernelLoad)? + } + _ => panic!("Invalid elf file"), + }; linux_loader::loader::load_cmdline( &self.memory, @@ -814,15 +831,38 @@ impl<'a> Vm<'a> { let vcpu_count = u8::from(&self.config.cpus); - arch::configure_system( - &self.memory, - self.config.cmdline.offset, - cmdline_cstring.to_bytes().len() + 1, - vcpu_count, - ) - .map_err(|_| Error::CmdLine)?; + match entry_addr.setup_header { + Some(hdr) => { + arch::configure_system( + &self.memory, + self.config.cmdline.offset, + cmdline_cstring.to_bytes().len() + 1, + vcpu_count, + Some(hdr), + ) + .map_err(|_| Error::CmdLine)?; - Ok(entry_addr.kernel_load) + let load_addr = entry_addr + .kernel_load + .raw_value() + .checked_add(KERNEL_64BIT_ENTRY_OFFSET) + .ok_or(Error::MemOverflow)?; + + Ok(GuestAddress(load_addr)) + } + None => { + arch::configure_system( + &self.memory, + self.config.cmdline.offset, + cmdline_cstring.to_bytes().len() + 1, + vcpu_count, + None, + ) + .map_err(|_| Error::CmdLine)?; + + Ok(entry_addr.kernel_load) + } + } } pub fn control_loop(&mut self) -> Result<()> {