arch: Fix map_err losing the inner error

Signed-off-by: Sebastien Boeuf <sebastien.boeuf@intel.com>
This commit is contained in:
Sebastien Boeuf 2020-01-24 07:51:15 +01:00
parent a34893a402
commit f5a52eda2b
4 changed files with 39 additions and 45 deletions

View File

@ -22,7 +22,7 @@ extern crate vm_memory;
use std::result;
#[derive(Debug, PartialEq)]
#[derive(Debug)]
pub enum Error {
#[cfg(target_arch = "x86_64")]
/// X86_64 specific error triggered during system configuration.
@ -30,7 +30,7 @@ pub enum Error {
/// The zero page extends past the end of guest_mem.
ZeroPagePastRamEnd,
/// Error writing the zero page of guest memory.
ZeroPageSetup,
ZeroPageSetup(vm_memory::GuestMemoryError),
}
pub type Result<T> = result::Result<T, Error>;

View File

@ -32,7 +32,7 @@ struct BootParamsWrapper(boot_params);
// It is safe to initialize BootParamsWrap which is a wrapper over `boot_params` (a series of ints).
unsafe impl ByteValued for BootParamsWrapper {}
#[derive(Debug, PartialEq)]
#[derive(Debug)]
pub enum Error {
/// Invalid e820 setup params.
E820Configuration,
@ -177,7 +177,7 @@ pub fn configure_system(
.ok_or(super::Error::ZeroPagePastRamEnd)?;
guest_mem
.write_obj(params, zero_page_addr)
.map_err(|_| super::Error::ZeroPageSetup)?;
.map_err(super::Error::ZeroPageSetup)?;
Ok(())
}
@ -229,12 +229,6 @@ mod tests {
let gm = GuestMemoryMmap::new(&vec![(GuestAddress(0), 0x10000)]).unwrap();
let config_err = configure_system(&gm, GuestAddress(0), 0, 1, None, None);
assert!(config_err.is_err());
assert_eq!(
config_err.unwrap_err(),
super::super::Error::X86_64Setup(super::Error::MpTableSetup(
mptable::Error::NotEnoughMemory
))
);
// Now assigning some memory that falls before the 32bit memory hole.
let mem_size = 128 << 20;

View File

@ -14,7 +14,7 @@ use libc::c_char;
use arch_gen::x86::mpspec;
use layout::{APIC_START, IOAPIC_START, MPTABLE_START};
use vm_memory::{Address, ByteValued, Bytes, GuestMemory, GuestMemoryMmap};
use vm_memory::{Address, ByteValued, Bytes, GuestMemory, GuestMemoryError, GuestMemoryMmap};
// This is a workaround to the Rust enforcement specifying that any implementation of a foreign
// trait (in this case `ByteValued`) where:
@ -45,30 +45,30 @@ unsafe impl ByteValued for MpcTableWrapper {}
unsafe impl ByteValued for MpcLintsrcWrapper {}
unsafe impl ByteValued for MpfIntelWrapper {}
#[derive(Debug, PartialEq)]
#[derive(Debug)]
pub enum Error {
/// There was too little guest memory to store the entire MP table.
NotEnoughMemory,
/// The MP table has too little address space to be stored.
AddressOverflow,
/// Failure while zeroing out the memory for the MP table.
Clear,
Clear(GuestMemoryError),
/// Number of CPUs exceeds the maximum supported CPUs
TooManyCpus,
/// Failure to write the MP floating pointer.
WriteMpfIntel,
WriteMpfIntel(GuestMemoryError),
/// Failure to write MP CPU entry.
WriteMpcCpu,
WriteMpcCpu(GuestMemoryError),
/// Failure to write MP ioapic entry.
WriteMpcIoapic,
WriteMpcIoapic(GuestMemoryError),
/// Failure to write MP bus entry.
WriteMpcBus,
WriteMpcBus(GuestMemoryError),
/// Failure to write MP interrupt source entry.
WriteMpcIntsrc,
WriteMpcIntsrc(GuestMemoryError),
/// Failure to write MP local interrupt source entry.
WriteMpcLintsrc,
WriteMpcLintsrc(GuestMemoryError),
/// Failure to write MP table header.
WriteMpcTable,
WriteMpcTable(GuestMemoryError),
}
pub type Result<T> = result::Result<T, Error>;
@ -145,7 +145,7 @@ pub fn setup_mptable(mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> {
}
mem.read_exact_from(base_mp, &mut io::repeat(0), mp_size)
.map_err(|_| Error::Clear)?;
.map_err(Error::Clear)?;
{
let mut mpf_intel = MpfIntelWrapper(mpspec::mpf_intel::default());
@ -156,7 +156,7 @@ pub fn setup_mptable(mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> {
mpf_intel.0.physptr = (base_mp.raw_value() + size) as u32;
mpf_intel.0.checksum = mpf_intel_compute_checksum(&mpf_intel.0);
mem.write_obj(mpf_intel, base_mp)
.map_err(|_| Error::WriteMpfIntel)?;
.map_err(Error::WriteMpfIntel)?;
base_mp = base_mp.unchecked_add(size);
}
@ -181,7 +181,7 @@ pub fn setup_mptable(mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> {
mpc_cpu.0.cpufeature = CPU_STEPPING;
mpc_cpu.0.featureflag = CPU_FEATURE_APIC | CPU_FEATURE_FPU;
mem.write_obj(mpc_cpu, base_mp)
.map_err(|_| Error::WriteMpcCpu)?;
.map_err(Error::WriteMpcCpu)?;
base_mp = base_mp.unchecked_add(size as u64);
checksum = checksum.wrapping_add(compute_checksum(&mpc_cpu.0));
}
@ -193,7 +193,7 @@ pub fn setup_mptable(mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> {
mpc_bus.0.busid = 0;
mpc_bus.0.bustype = BUS_TYPE_ISA;
mem.write_obj(mpc_bus, base_mp)
.map_err(|_| Error::WriteMpcBus)?;
.map_err(Error::WriteMpcBus)?;
base_mp = base_mp.unchecked_add(size as u64);
checksum = checksum.wrapping_add(compute_checksum(&mpc_bus.0));
}
@ -206,7 +206,7 @@ pub fn setup_mptable(mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> {
mpc_ioapic.0.flags = mpspec::MPC_APIC_USABLE as u8;
mpc_ioapic.0.apicaddr = IOAPIC_START.0 as u32;
mem.write_obj(mpc_ioapic, base_mp)
.map_err(|_| Error::WriteMpcIoapic)?;
.map_err(Error::WriteMpcIoapic)?;
base_mp = base_mp.unchecked_add(size as u64);
checksum = checksum.wrapping_add(compute_checksum(&mpc_ioapic.0));
}
@ -222,7 +222,7 @@ pub fn setup_mptable(mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> {
mpc_intsrc.0.dstapic = ioapicid;
mpc_intsrc.0.dstirq = i;
mem.write_obj(mpc_intsrc, base_mp)
.map_err(|_| Error::WriteMpcIntsrc)?;
.map_err(Error::WriteMpcIntsrc)?;
base_mp = base_mp.unchecked_add(size as u64);
checksum = checksum.wrapping_add(compute_checksum(&mpc_intsrc.0));
}
@ -237,7 +237,7 @@ pub fn setup_mptable(mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> {
mpc_lintsrc.0.destapic = 0;
mpc_lintsrc.0.destapiclint = 0;
mem.write_obj(mpc_lintsrc, base_mp)
.map_err(|_| Error::WriteMpcLintsrc)?;
.map_err(Error::WriteMpcLintsrc)?;
base_mp = base_mp.unchecked_add(size as u64);
checksum = checksum.wrapping_add(compute_checksum(&mpc_lintsrc.0));
}
@ -252,7 +252,7 @@ pub fn setup_mptable(mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> {
mpc_lintsrc.0.destapic = 0xFF; /* to all local APICs */
mpc_lintsrc.0.destapiclint = 1;
mem.write_obj(mpc_lintsrc, base_mp)
.map_err(|_| Error::WriteMpcLintsrc)?;
.map_err(Error::WriteMpcLintsrc)?;
base_mp = base_mp.unchecked_add(size as u64);
checksum = checksum.wrapping_add(compute_checksum(&mpc_lintsrc.0));
}
@ -271,7 +271,7 @@ pub fn setup_mptable(mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> {
checksum = checksum.wrapping_add(compute_checksum(&mpc_table.0));
mpc_table.0.checksum = (!checksum).wrapping_add(1) as i8;
mem.write_obj(mpc_table, table_base)
.map_err(|_| Error::WriteMpcTable)?;
.map_err(Error::WriteMpcTable)?;
}
Ok(())
@ -393,7 +393,7 @@ mod tests {
let cpus = MAX_SUPPORTED_CPUS + 1;
let mem = GuestMemoryMmap::new(&[(MPTABLE_START, compute_mp_size(cpus as u8))]).unwrap();
let result = setup_mptable(&mem, cpus as u8).unwrap_err();
assert_eq!(result, Error::TooManyCpus);
let result = setup_mptable(&mem, cpus as u8);
assert!(result.is_err());
}
}

View File

@ -12,7 +12,7 @@ use arch_gen::x86::msr_index;
use kvm_bindings::{kvm_fpu, kvm_msr_entry, kvm_regs, kvm_sregs, Msrs};
use kvm_ioctls::VcpuFd;
use layout::{BOOT_GDT_START, BOOT_IDT_START, PDE_START, PDPTE_START, PML4_START};
use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryMmap};
use vm_memory::{Address, Bytes, GuestMemory, GuestMemoryError, GuestMemoryMmap};
// MTRR constants
const MTRR_ENABLE: u64 = 0x800; // IA32_MTRR_DEF_TYPE MSR: E (MTRRs enabled) flag, bit 11
@ -30,16 +30,18 @@ pub enum Error {
SetModelSpecificRegisters(kvm_ioctls::Error),
/// Failed to set SREGs for this CPU.
SetStatusRegisters(kvm_ioctls::Error),
/// Checking the GDT address failed.
CheckGDTAddr,
/// Writing the GDT to RAM failed.
WriteGDT,
WriteGDT(GuestMemoryError),
/// Writing the IDT to RAM failed.
WriteIDT,
WriteIDT(GuestMemoryError),
/// Writing PDPTE to RAM failed.
WritePDPTEAddress,
WritePDPTEAddress(GuestMemoryError),
/// Writing PDE to RAM failed.
WritePDEAddress,
WritePDEAddress(GuestMemoryError),
/// Writing PML4 to RAM failed.
WritePML4Address,
WritePML4Address(GuestMemoryError),
}
pub type Result<T> = result::Result<T, Error>;
@ -121,10 +123,8 @@ fn write_gdt_table(table: &[u64], guest_mem: &GuestMemoryMmap) -> Result<()> {
for (index, entry) in table.iter().enumerate() {
let addr = guest_mem
.checked_offset(boot_gdt_addr, index * mem::size_of::<u64>())
.ok_or(Error::WriteGDT)?;
guest_mem
.write_obj(*entry, addr)
.map_err(|_| Error::WriteGDT)?;
.ok_or(Error::CheckGDTAddr)?;
guest_mem.write_obj(*entry, addr).map_err(Error::WriteGDT)?;
}
Ok(())
}
@ -133,7 +133,7 @@ fn write_idt_value(val: u64, guest_mem: &GuestMemoryMmap) -> Result<()> {
let boot_idt_addr = BOOT_IDT_START;
guest_mem
.write_obj(val, boot_idt_addr)
.map_err(|_| Error::WriteIDT)
.map_err(Error::WriteIDT)
}
fn configure_segments_and_sregs(mem: &GuestMemoryMmap, sregs: &mut kvm_sregs) -> Result<()> {
@ -177,16 +177,16 @@ fn setup_page_tables(mem: &GuestMemoryMmap, sregs: &mut kvm_sregs) -> Result<()>
// Entry covering VA [0..512GB)
mem.write_obj(PDPTE_START.raw_value() | 0x03, PML4_START)
.map_err(|_| Error::WritePML4Address)?;
.map_err(Error::WritePML4Address)?;
// Entry covering VA [0..1GB)
mem.write_obj(PDE_START.raw_value() | 0x03, PDPTE_START)
.map_err(|_| Error::WritePDPTEAddress)?;
.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)?;
.map_err(Error::WritePDEAddress)?;
}
sregs.cr3 = PML4_START.raw_value();