summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--aarch64/src/fdt.rs27
-rw-r--r--aarch64/src/lib.rs110
-rw-r--r--arch/src/fdt.rs54
-rw-r--r--arch/src/lib.rs30
-rw-r--r--src/linux.rs7
-rw-r--r--x86_64/src/fdt.rs4
-rw-r--r--x86_64/src/lib.rs136
7 files changed, 187 insertions, 181 deletions
diff --git a/aarch64/src/fdt.rs b/aarch64/src/fdt.rs
index ff3274f..b03d039 100644
--- a/aarch64/src/fdt.rs
+++ b/aarch64/src/fdt.rs
@@ -6,7 +6,7 @@ use std::ffi::CStr;
 
 use arch::fdt::{
     begin_node, end_node, finish_fdt, generate_prop32, generate_prop64, property, property_cstring,
-    property_null, property_string, property_u32, property_u64, start_fdt, Error,
+    property_null, property_string, property_u32, property_u64, start_fdt, Error, Result,
 };
 use devices::PciInterruptPin;
 use sys_util::{GuestAddress, GuestMemory};
@@ -54,7 +54,7 @@ const IRQ_TYPE_EDGE_RISING: u32 = 0x00000001;
 const IRQ_TYPE_LEVEL_HIGH: u32 = 0x00000004;
 const IRQ_TYPE_LEVEL_LOW: u32 = 0x00000008;
 
-fn create_memory_node(fdt: &mut Vec<u8>, guest_mem: &GuestMemory) -> Result<(), Box<Error>> {
+fn create_memory_node(fdt: &mut Vec<u8>, guest_mem: &GuestMemory) -> Result<()> {
     let mem_size = guest_mem.memory_size();
     let mem_reg_prop = generate_prop64(&[AARCH64_PHYS_MEM_START, mem_size]);
 
@@ -65,7 +65,7 @@ fn create_memory_node(fdt: &mut Vec<u8>, guest_mem: &GuestMemory) -> Result<(),
     Ok(())
 }
 
-fn create_cpu_nodes(fdt: &mut Vec<u8>, num_cpus: u32) -> Result<(), Box<Error>> {
+fn create_cpu_nodes(fdt: &mut Vec<u8>, num_cpus: u32) -> Result<()> {
     begin_node(fdt, "cpus")?;
     property_u32(fdt, "#address-cells", 0x1)?;
     property_u32(fdt, "#size-cells", 0x0)?;
@@ -85,7 +85,7 @@ fn create_cpu_nodes(fdt: &mut Vec<u8>, num_cpus: u32) -> Result<(), Box<Error>>
     Ok(())
 }
 
-fn create_gic_node(fdt: &mut Vec<u8>) -> Result<(), Box<Error>> {
+fn create_gic_node(fdt: &mut Vec<u8>) -> Result<()> {
     let gic_reg_prop = generate_prop64(&[
         AARCH64_GIC_DIST_BASE,
         AARCH64_GIC_DIST_SIZE,
@@ -106,7 +106,7 @@ fn create_gic_node(fdt: &mut Vec<u8>) -> Result<(), Box<Error>> {
     Ok(())
 }
 
-fn create_timer_node(fdt: &mut Vec<u8>, num_cpus: u32) -> Result<(), Box<Error>> {
+fn create_timer_node(fdt: &mut Vec<u8>, num_cpus: u32) -> Result<()> {
     // These are fixed interrupt numbers for the timer device.
     let irqs = [13, 14, 11, 10];
     let compatible = "arm,armv8-timer";
@@ -130,7 +130,7 @@ fn create_timer_node(fdt: &mut Vec<u8>, num_cpus: u32) -> Result<(), Box<Error>>
     Ok(())
 }
 
-fn create_serial_node(fdt: &mut Vec<u8>) -> Result<(), Box<Error>> {
+fn create_serial_node(fdt: &mut Vec<u8>) -> Result<()> {
     let serial_reg_prop = generate_prop64(&[AARCH64_SERIAL_ADDR, AARCH64_SERIAL_SIZE]);
     let irq = generate_prop32(&[
         GIC_FDT_IRQ_TYPE_SPI,
@@ -149,7 +149,7 @@ fn create_serial_node(fdt: &mut Vec<u8>) -> Result<(), Box<Error>> {
 }
 
 // TODO(sonnyrao) -- check to see if host kernel supports PSCI 0_2
-fn create_psci_node(fdt: &mut Vec<u8>) -> Result<(), Box<Error>> {
+fn create_psci_node(fdt: &mut Vec<u8>) -> Result<()> {
     let compatible = "arm,psci-0.2";
     begin_node(fdt, "psci")?;
     property_string(fdt, "compatible", compatible)?;
@@ -169,7 +169,7 @@ fn create_chosen_node(
     fdt: &mut Vec<u8>,
     cmdline: &CStr,
     initrd: Option<(GuestAddress, usize)>,
-) -> Result<(), Box<Error>> {
+) -> Result<()> {
     begin_node(fdt, "chosen")?;
     property_u32(fdt, "linux,pci-probe-only", 1)?;
     property_cstring(fdt, "bootargs", cmdline)?;
@@ -185,10 +185,7 @@ fn create_chosen_node(
     Ok(())
 }
 
-fn create_pci_nodes(
-    fdt: &mut Vec<u8>,
-    pci_irqs: Vec<(u32, PciInterruptPin)>,
-) -> Result<(), Box<Error>> {
+fn create_pci_nodes(fdt: &mut Vec<u8>, pci_irqs: Vec<(u32, PciInterruptPin)>) -> Result<()> {
     // Add devicetree nodes describing a PCI generic host controller.
     // See Documentation/devicetree/bindings/pci/host-generic-pci.txt in the kernel
     // and "PCI Bus Binding to IEEE Std 1275-1994".
@@ -258,7 +255,7 @@ fn create_pci_nodes(
     Ok(())
 }
 
-fn create_rtc_node(fdt: &mut Vec<u8>) -> Result<(), Box<Error>> {
+fn create_rtc_node(fdt: &mut Vec<u8>) -> Result<()> {
     // the kernel driver for pl030 really really wants a clock node
     // associated with an AMBA device or it will fail to probe, so we
     // need to make up a clock node to associate with the pl030 rtc
@@ -306,7 +303,7 @@ pub fn create_fdt(
     fdt_load_offset: u64,
     cmdline: &CStr,
     initrd: Option<(GuestAddress, usize)>,
-) -> Result<(), Box<Error>> {
+) -> Result<()> {
     let mut fdt = vec![0; fdt_max_size];
     start_fdt(&mut fdt, fdt_max_size)?;
 
@@ -338,7 +335,7 @@ pub fn create_fdt(
         .write_at_addr(fdt_final.as_slice(), fdt_address)
         .map_err(|_| Error::FdtGuestMemoryWriteError)?;
     if written < fdt_max_size {
-        return Err(Box::new(Error::FdtGuestMemoryWriteError));
+        return Err(Error::FdtGuestMemoryWriteError);
     }
     Ok(())
 }
diff --git a/aarch64/src/lib.rs b/aarch64/src/lib.rs
index 58496ec..85e1076 100644
--- a/aarch64/src/lib.rs
+++ b/aarch64/src/lib.rs
@@ -14,6 +14,7 @@ extern crate resources;
 extern crate sync;
 extern crate sys_util;
 
+use std::error::Error as StdError;
 use std::ffi::{CStr, CString};
 use std::fmt::{self, Display};
 use std::fs::File;
@@ -26,12 +27,11 @@ use devices::{Bus, BusError, PciConfigMmio, PciDevice, PciInterruptPin};
 use io_jail::Minijail;
 use resources::{AddressRanges, SystemAllocator};
 use sync::Mutex;
-use sys_util::{EventFd, GuestAddress, GuestMemory};
+use sys_util::{EventFd, GuestAddress, GuestMemory, GuestMemoryError};
 
 use kvm::*;
 use kvm_sys::kvm_device_attr;
 
-use arch::Result;
 mod fdt;
 
 // We place the kernel at offset 8MB
@@ -117,40 +117,29 @@ const AARCH64_IRQ_BASE: u32 = 2;
 
 #[derive(Debug)]
 pub enum Error {
-    /// Unable to clone an EventFd
     CloneEventFd(sys_util::Error),
-    /// Error creating kernel command line.
     Cmdline(kernel_cmdline::Error),
-    /// Unable to make an EventFd
+    CreateDevices(Box<dyn StdError>),
     CreateEventFd(sys_util::Error),
-    /// Unable to create Kvm.
+    CreateFdt(arch::fdt::Error),
+    CreateGICFailure(sys_util::Error),
     CreateKvm(sys_util::Error),
-    /// Unable to create a PciRoot hub.
     CreatePciRoot(arch::DeviceRegistrationError),
-    /// Unable to create socket.
     CreateSocket(io::Error),
-    /// Unable to create Vcpu.
     CreateVcpu(sys_util::Error),
-    /// FDT could not be created
-    FDTCreateFailure(Box<std::error::Error>),
-    /// Kernel could not be loaded
-    KernelLoadFailure(arch::LoadImageError),
-    /// Initrd could not be loaded
+    CreateVm(sys_util::Error),
     InitrdLoadFailure(arch::LoadImageError),
-    /// Failure to Create GIC
-    CreateGICFailure(sys_util::Error),
-    /// Couldn't register PCI bus.
+    KernelLoadFailure(arch::LoadImageError),
+    ReadPreferredTarget(sys_util::Error),
+    RegisterIrqfd(sys_util::Error),
     RegisterPci(BusError),
-    /// Couldn't register virtio socket.
     RegisterVsock(arch::DeviceRegistrationError),
-    /// VCPU Init failed
-    VCPUInitFailure,
-    /// VCPU Set one reg failed
-    VCPUSetRegFailure,
+    SetDeviceAttr(sys_util::Error),
+    SetReg(sys_util::Error),
+    SetupGuestMemory(GuestMemoryError),
+    VcpuInit(sys_util::Error),
 }
 
-impl std::error::Error for Error {}
-
 impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         use self::Error::*;
@@ -158,23 +147,33 @@ impl Display for Error {
         match self {
             CloneEventFd(e) => write!(f, "unable to clone an EventFd: {}", e),
             Cmdline(e) => write!(f, "the given kernel command line was invalid: {}", e),
+            CreateDevices(e) => write!(f, "error creating devices: {}", e),
             CreateEventFd(e) => write!(f, "unable to make an EventFd: {}", e),
+            CreateFdt(e) => write!(f, "FDT could not be created: {}", e),
+            CreateGICFailure(e) => write!(f, "failed to create GIC: {}", e),
             CreateKvm(e) => write!(f, "failed to open /dev/kvm: {}", e),
             CreatePciRoot(e) => write!(f, "failed to create a PCI root hub: {}", e),
             CreateSocket(e) => write!(f, "failed to create socket: {}", e),
             CreateVcpu(e) => write!(f, "failed to create VCPU: {}", e),
-            FDTCreateFailure(e) => write!(f, "FDT could not be created: {}", e),
-            KernelLoadFailure(e) => write!(f, "kernel cound not be loaded: {}", e),
+            CreateVm(e) => write!(f, "failed to create vm: {}", e),
             InitrdLoadFailure(e) => write!(f, "initrd cound not be loaded: {}", e),
-            CreateGICFailure(e) => write!(f, "failed to create GIC: {}", e),
+            KernelLoadFailure(e) => write!(f, "kernel cound not be loaded: {}", e),
+            ReadPreferredTarget(e) => write!(f, "failed to read preferred target: {}", e),
+            RegisterIrqfd(e) => write!(f, "failed to register irq fd: {}", e),
             RegisterPci(e) => write!(f, "error registering PCI bus: {}", e),
             RegisterVsock(e) => write!(f, "error registering virtual socket device: {}", e),
-            VCPUInitFailure => write!(f, "failed to initialize VCPU"),
-            VCPUSetRegFailure => write!(f, "failed to set register"),
+            SetDeviceAttr(e) => write!(f, "failed to set device attr: {}", e),
+            SetReg(e) => write!(f, "failed to set register: {}", e),
+            SetupGuestMemory(e) => write!(f, "failed to set up guest memory: {}", e),
+            VcpuInit(e) => write!(f, "failed to initialize VCPU: {}", e),
         }
     }
 }
 
+pub type Result<T> = std::result::Result<T, Error>;
+
+impl std::error::Error for Error {}
+
 /// Returns a Vec of the valid memory addresses.
 /// These should be used to configure the GuestMemory structure for the platfrom.
 pub fn arch_memory_regions(size: u64) -> Vec<(GuestAddress, u64)> {
@@ -191,7 +190,9 @@ fn fdt_offset(mem_size: u64) -> u64 {
 pub struct AArch64;
 
 impl arch::LinuxArch for AArch64 {
-    fn build_vm<F>(
+    type Error = Error;
+
+    fn build_vm<F, E>(
         mut components: VmComponents,
         _split_irqchip: bool,
         create_devices: F,
@@ -200,13 +201,14 @@ impl arch::LinuxArch for AArch64 {
         F: FnOnce(
             &GuestMemory,
             &EventFd,
-        ) -> Result<Vec<(Box<PciDevice + 'static>, Option<Minijail>)>>,
+        ) -> std::result::Result<Vec<(Box<PciDevice>, Option<Minijail>)>, E>,
+        E: StdError + 'static,
     {
         let mut resources =
             Self::get_resource_allocator(components.memory_mb, components.wayland_dmabuf);
         let mem = Self::setup_memory(components.memory_mb)?;
         let kvm = Kvm::new().map_err(Error::CreateKvm)?;
-        let mut vm = Self::create_vm(&kvm, mem.clone())?;
+        let mut vm = Vm::new(&kvm, mem.clone()).map_err(Error::CreateVm)?;
 
         let vcpu_count = components.vcpu_count;
         let mut vcpus = Vec::with_capacity(vcpu_count as usize);
@@ -230,7 +232,8 @@ impl arch::LinuxArch for AArch64 {
 
         let exit_evt = EventFd::new().map_err(Error::CreateEventFd)?;
 
-        let pci_devices = create_devices(&mem, &exit_evt)?;
+        let pci_devices =
+            create_devices(&mem, &exit_evt).map_err(|e| Error::CreateDevices(Box::new(e)))?;
         let (pci, pci_irqs, pid_debug_label_map) =
             arch::generate_pci_root(pci_devices, &mut mmio_bus, &mut resources, &mut vm)
                 .map_err(Error::CreatePciRoot)?;
@@ -321,18 +324,14 @@ impl AArch64 {
             fdt_offset(mem_size),
             cmdline,
             initrd,
-        )?;
+        )
+        .map_err(Error::CreateFdt)?;
         Ok(())
     }
 
-    fn create_vm(kvm: &Kvm, mem: GuestMemory) -> Result<Vm> {
-        let vm = Vm::new(&kvm, mem)?;
-        Ok(vm)
-    }
-
     fn setup_memory(mem_size: u64) -> Result<GuestMemory> {
         let arch_mem_regions = arch_memory_regions(mem_size);
-        let mem = GuestMemory::new(&arch_mem_regions)?;
+        let mem = GuestMemory::new(&arch_mem_regions).map_err(Error::SetupGuestMemory)?;
         Ok(mem)
     }
 
@@ -364,13 +363,15 @@ impl AArch64 {
     /// * `vm` - The vm to add irqs to.
     /// * `bus` - The bus to add devices to.
     fn add_arch_devs(vm: &mut Vm, bus: &mut Bus) -> Result<Arc<Mutex<devices::Serial>>> {
-        let rtc_evt = EventFd::new()?;
-        vm.register_irqfd(&rtc_evt, AARCH64_RTC_IRQ)?;
+        let rtc_evt = EventFd::new().map_err(Error::CreateEventFd)?;
+        vm.register_irqfd(&rtc_evt, AARCH64_RTC_IRQ)
+            .map_err(Error::RegisterIrqfd)?;
 
-        let com_evt_1_3 = EventFd::new()?;
-        vm.register_irqfd(&com_evt_1_3, AARCH64_SERIAL_IRQ)?;
+        let com_evt_1_3 = EventFd::new().map_err(Error::CreateEventFd)?;
+        vm.register_irqfd(&com_evt_1_3, AARCH64_SERIAL_IRQ)
+            .map_err(Error::RegisterIrqfd)?;
         let serial = Arc::new(Mutex::new(devices::Serial::new_out(
-            com_evt_1_3.try_clone()?,
+            com_evt_1_3.try_clone().map_err(Error::CloneEventFd)?,
             Box::new(stdout()),
         )));
         bus.insert(
@@ -429,7 +430,7 @@ impl AArch64 {
             sys_util::ioctl_with_ref(&vgic_fd, kvm_sys::KVM_SET_DEVICE_ATTR(), &cpu_if_attr)
         };
         if ret != 0 {
-            return Err(Box::new(Error::CreateGICFailure(sys_util::Error::new(ret))));
+            return Err(Error::CreateGICFailure(sys_util::Error::new(ret)));
         }
 
         // Safe because we allocated the struct that's being passed in
@@ -437,7 +438,7 @@ impl AArch64 {
             sys_util::ioctl_with_ref(&vgic_fd, kvm_sys::KVM_SET_DEVICE_ATTR(), &dist_attr)
         };
         if ret != 0 {
-            return Err(Box::new(Error::CreateGICFailure(sys_util::Error::new(ret))));
+            return Err(Error::CreateGICFailure(sys_util::Error::new(ret)));
         }
 
         // We need to tell the kernel how many irqs to support with this vgic
@@ -454,7 +455,7 @@ impl AArch64 {
             sys_util::ioctl_with_ref(&vgic_fd, kvm_sys::KVM_SET_DEVICE_ATTR(), &nr_irqs_attr)
         };
         if ret != 0 {
-            return Err(Box::new(Error::CreateGICFailure(sys_util::Error::new(ret))));
+            return Err(Error::CreateGICFailure(sys_util::Error::new(ret)));
         }
 
         // Finalize the GIC
@@ -470,7 +471,7 @@ impl AArch64 {
             sys_util::ioctl_with_ref(&vgic_fd, kvm_sys::KVM_SET_DEVICE_ATTR(), &init_gic_attr)
         };
         if ret != 0 {
-            return Err(Box::new(sys_util::Error::new(ret)));
+            return Err(Error::SetDeviceAttr(sys_util::Error::new(ret)));
         }
         Ok(Some(vgic_fd))
     }
@@ -489,7 +490,8 @@ impl AArch64 {
         };
 
         // This reads back the kernel's preferred target type.
-        vm.arm_preferred_target(&mut kvi)?;
+        vm.arm_preferred_target(&mut kvi)
+            .map_err(Error::ReadPreferredTarget)?;
 
         // TODO(sonnyrao): need to verify this feature is supported by host kernel
         kvi.features[0] |= 1 << kvm_sys::KVM_ARM_VCPU_PSCI_0_2;
@@ -498,7 +500,7 @@ impl AArch64 {
         if cpu_id > 0 {
             kvi.features[0] |= 1 << kvm_sys::KVM_ARM_VCPU_POWER_OFF;
         }
-        vcpu.arm_vcpu_init(&kvi)?;
+        vcpu.arm_vcpu_init(&kvi).map_err(Error::VcpuInit)?;
 
         // set up registers
         let mut data: u64;
@@ -507,20 +509,20 @@ impl AArch64 {
         // All interrupts masked
         data = PSR_D_BIT | PSR_A_BIT | PSR_I_BIT | PSR_F_BIT | PSR_MODE_EL1H;
         reg_id = arm64_core_reg!(pstate);
-        vcpu.set_one_reg(reg_id, data)?;
+        vcpu.set_one_reg(reg_id, data).map_err(Error::SetReg)?;
 
         // Other cpus are powered off initially
         if cpu_id == 0 {
             data = AARCH64_PHYS_MEM_START + AARCH64_KERNEL_OFFSET;
             reg_id = arm64_core_reg!(pc);
-            vcpu.set_one_reg(reg_id, data)?;
+            vcpu.set_one_reg(reg_id, data).map_err(Error::SetReg)?;
 
             /* X0 -- fdt address */
             let mem_size = guest_mem.memory_size();
             data = (AARCH64_PHYS_MEM_START + fdt_offset(mem_size)) as u64;
             // hack -- can't get this to do offsetof(regs[0]) but luckily it's at offset 0
             reg_id = arm64_core_reg!(regs);
-            vcpu.set_one_reg(reg_id, data)?;
+            vcpu.set_one_reg(reg_id, data).map_err(Error::SetReg)?;
         }
         Ok(())
     }
diff --git a/arch/src/fdt.rs b/arch/src/fdt.rs
index 5b4961d..7761def 100644
--- a/arch/src/fdt.rs
+++ b/arch/src/fdt.rs
@@ -37,8 +37,6 @@ pub enum Error {
     FdtGuestMemoryWriteError,
 }
 
-impl std::error::Error for Error {}
-
 impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         use self::Error::*;
@@ -59,27 +57,31 @@ impl Display for Error {
     }
 }
 
-pub fn begin_node(fdt: &mut Vec<u8>, name: &str) -> Result<(), Box<Error>> {
+pub type Result<T> = std::result::Result<T, Error>;
+
+impl std::error::Error for Error {}
+
+pub fn begin_node(fdt: &mut Vec<u8>, name: &str) -> Result<()> {
     let cstr_name = CString::new(name).unwrap();
 
     // Safe because we allocated fdt and converted name to a CString
     let fdt_ret = unsafe { fdt_begin_node(fdt.as_mut_ptr() as *mut c_void, cstr_name.as_ptr()) };
     if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtBeginNodeError(fdt_ret)));
+        return Err(Error::FdtBeginNodeError(fdt_ret));
     }
     Ok(())
 }
 
-pub fn end_node(fdt: &mut Vec<u8>) -> Result<(), Box<Error>> {
+pub fn end_node(fdt: &mut Vec<u8>) -> Result<()> {
     // Safe because we allocated fdt
     let fdt_ret = unsafe { fdt_end_node(fdt.as_mut_ptr() as *mut c_void) };
     if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtEndNodeError(fdt_ret)));
+        return Err(Error::FdtEndNodeError(fdt_ret));
     }
     Ok(())
 }
 
-pub fn property(fdt: &mut Vec<u8>, name: &str, val: &[u8]) -> Result<(), Box<Error>> {
+pub fn property(fdt: &mut Vec<u8>, name: &str, val: &[u8]) -> Result<()> {
     let cstr_name = CString::new(name).unwrap();
     let val_ptr = val.as_ptr() as *const c_void;
 
@@ -93,7 +95,7 @@ pub fn property(fdt: &mut Vec<u8>, name: &str, val: &[u8]) -> Result<(), Box<Err
         )
     };
     if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtPropertyError(fdt_ret)));
+        return Err(Error::FdtPropertyError(fdt_ret));
     }
     Ok(())
 }
@@ -110,11 +112,11 @@ fn cpu_to_fdt64(input: u64) -> [u8; 8] {
     buf
 }
 
-pub fn property_u32(fdt: &mut Vec<u8>, name: &str, val: u32) -> Result<(), Box<Error>> {
+pub fn property_u32(fdt: &mut Vec<u8>, name: &str, val: u32) -> Result<()> {
     property(fdt, name, &cpu_to_fdt32(val))
 }
 
-pub fn property_u64(fdt: &mut Vec<u8>, name: &str, val: u64) -> Result<(), Box<Error>> {
+pub fn property_u64(fdt: &mut Vec<u8>, name: &str, val: u64) -> Result<()> {
     property(fdt, name, &cpu_to_fdt64(val))
 }
 
@@ -136,7 +138,7 @@ pub fn generate_prop64(cells: &[u64]) -> Vec<u8> {
     ret
 }
 
-pub fn property_null(fdt: &mut Vec<u8>, name: &str) -> Result<(), Box<Error>> {
+pub fn property_null(fdt: &mut Vec<u8>, name: &str) -> Result<()> {
     let cstr_name = CString::new(name).unwrap();
 
     // Safe because we allocated fdt, converted name to a CString
@@ -149,16 +151,12 @@ pub fn property_null(fdt: &mut Vec<u8>, name: &str) -> Result<(), Box<Error>> {
         )
     };
     if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtPropertyError(fdt_ret)));
+        return Err(Error::FdtPropertyError(fdt_ret));
     }
     Ok(())
 }
 
-pub fn property_cstring(
-    fdt: &mut Vec<u8>,
-    name: &str,
-    cstr_value: &CStr,
-) -> Result<(), Box<Error>> {
+pub fn property_cstring(fdt: &mut Vec<u8>, name: &str, cstr_value: &CStr) -> Result<()> {
     let value_bytes = cstr_value.to_bytes_with_nul();
     let cstr_name = CString::new(name).unwrap();
 
@@ -172,40 +170,36 @@ pub fn property_cstring(
         )
     };
     if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtPropertyError(fdt_ret)));
+        return Err(Error::FdtPropertyError(fdt_ret));
     }
     Ok(())
 }
 
-pub fn property_string(fdt: &mut Vec<u8>, name: &str, value: &str) -> Result<(), Box<Error>> {
+pub fn property_string(fdt: &mut Vec<u8>, name: &str, value: &str) -> Result<()> {
     let cstr_value = CString::new(value).unwrap();
     property_cstring(fdt, name, &cstr_value)
 }
 
-pub fn start_fdt(fdt: &mut Vec<u8>, fdt_max_size: usize) -> Result<(), Box<Error>> {
+pub fn start_fdt(fdt: &mut Vec<u8>, fdt_max_size: usize) -> Result<()> {
     // Safe since we allocated this array with fdt_max_size
     let mut fdt_ret = unsafe { fdt_create(fdt.as_mut_ptr() as *mut c_void, fdt_max_size as c_int) };
 
     if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtCreateError(fdt_ret)));
+        return Err(Error::FdtCreateError(fdt_ret));
     }
     // Safe since we allocated this array
     fdt_ret = unsafe { fdt_finish_reservemap(fdt.as_mut_ptr() as *mut c_void) };
     if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtFinishReservemapError(fdt_ret)));
+        return Err(Error::FdtFinishReservemapError(fdt_ret));
     }
     Ok(())
 }
 
-pub fn finish_fdt(
-    fdt: &mut Vec<u8>,
-    fdt_final: &mut Vec<u8>,
-    fdt_max_size: usize,
-) -> Result<(), Box<Error>> {
+pub fn finish_fdt(fdt: &mut Vec<u8>, fdt_final: &mut Vec<u8>, fdt_max_size: usize) -> Result<()> {
     // Safe since we allocated fdt_final and previously passed in it's size
     let mut fdt_ret = unsafe { fdt_finish(fdt.as_mut_ptr() as *mut c_void) };
     if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtFinishError(fdt_ret)));
+        return Err(Error::FdtFinishError(fdt_ret));
     }
 
     // Safe because we allocated both arrays with the correct size
@@ -217,13 +211,13 @@ pub fn finish_fdt(
         )
     };
     if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtOpenIntoError(fdt_ret)));
+        return Err(Error::FdtOpenIntoError(fdt_ret));
     }
 
     // Safe since we allocated fdt_final
     fdt_ret = unsafe { fdt_pack(fdt_final.as_mut_ptr() as *mut c_void) };
     if fdt_ret != 0 {
-        return Err(Box::new(Error::FdtPackError(fdt_ret)));
+        return Err(Error::FdtPackError(fdt_ret));
     }
     Ok(())
 }
diff --git a/arch/src/lib.rs b/arch/src/lib.rs
index d725baa..aa6c8a3 100644
--- a/arch/src/lib.rs
+++ b/arch/src/lib.rs
@@ -15,11 +15,11 @@ extern crate sync;
 extern crate sys_util;
 
 use std::collections::BTreeMap;
+use std::error::Error as StdError;
 use std::fmt::{self, Display};
 use std::fs::File;
-use std::io::{Read, Seek, SeekFrom};
+use std::io::{self, Read, Seek, SeekFrom};
 use std::os::unix::io::AsRawFd;
-use std::result;
 use std::sync::Arc;
 
 use devices::virtio::VirtioDevice;
@@ -33,8 +33,6 @@ use resources::SystemAllocator;
 use sync::Mutex;
 use sys_util::{syslog, EventFd, GuestAddress, GuestMemory, GuestMemoryError};
 
-pub type Result<T> = result::Result<T, Box<std::error::Error>>;
-
 /// Holds the pieces needed to build a VM. Passed to `build_vm` in the `LinuxArch` trait below to
 /// create a `RunnableLinuxVm`.
 pub struct VmComponents {
@@ -70,6 +68,8 @@ pub struct VirtioDeviceStub {
 /// Trait which is implemented for each Linux Architecture in order to
 /// set up the memory, cpus, and system devices and to boot the kernel.
 pub trait LinuxArch {
+    type Error: StdError;
+
     /// Takes `VmComponents` and generates a `RunnableLinuxVm`.
     ///
     /// # Arguments
@@ -77,16 +77,14 @@ pub trait LinuxArch {
     /// * `components` - Parts to use to build the VM.
     /// * `split_irqchip` - whether to use a split IRQ chip (i.e. userspace PIT/PIC/IOAPIC)
     /// * `create_devices` - Function to generate a list of devices.
-    fn build_vm<F>(
+    fn build_vm<F, E>(
         components: VmComponents,
         split_irqchip: bool,
         create_devices: F,
-    ) -> Result<RunnableLinuxVm>
+    ) -> Result<RunnableLinuxVm, Self::Error>
     where
-        F: FnOnce(
-            &GuestMemory,
-            &EventFd,
-        ) -> Result<Vec<(Box<PciDevice + 'static>, Option<Minijail>)>>;
+        F: FnOnce(&GuestMemory, &EventFd) -> Result<Vec<(Box<PciDevice>, Option<Minijail>)>, E>,
+        E: StdError + 'static;
 }
 
 /// Errors for device manager.
@@ -141,14 +139,12 @@ impl Display for DeviceRegistrationError {
 
 /// Creates a root PCI device for use by this Vm.
 pub fn generate_pci_root(
-    devices: Vec<(Box<PciDevice + 'static>, Option<Minijail>)>,
+    devices: Vec<(Box<PciDevice>, Option<Minijail>)>,
     mmio_bus: &mut Bus,
     resources: &mut SystemAllocator,
     vm: &mut Vm,
-) -> std::result::Result<
-    (PciRoot, Vec<(u32, PciInterruptPin)>, BTreeMap<u32, String>),
-    DeviceRegistrationError,
-> {
+) -> Result<(PciRoot, Vec<(u32, PciInterruptPin)>, BTreeMap<u32, String>), DeviceRegistrationError>
+{
     let mut root = PciRoot::new();
     let mut pci_irqs = Vec::new();
     let mut pid_labels = BTreeMap::new();
@@ -214,7 +210,7 @@ pub fn generate_pci_root(
 /// Errors for image loading.
 #[derive(Debug)]
 pub enum LoadImageError {
-    Seek(std::io::Error),
+    Seek(io::Error),
     ImageSizeTooLarge(u64),
     ReadToMemory(GuestMemoryError),
 }
@@ -246,7 +242,7 @@ pub fn load_image<F>(
     image: &mut F,
     guest_addr: GuestAddress,
     max_size: u64,
-) -> std::result::Result<usize, LoadImageError>
+) -> Result<usize, LoadImageError>
 where
     F: Read + Seek,
 {
diff --git a/src/linux.rs b/src/linux.rs
index acea1de..a0cb968 100644
--- a/src/linux.rs
+++ b/src/linux.rs
@@ -58,7 +58,7 @@ pub enum Error {
     BalloonDeviceNew(virtio::BalloonError),
     BlockDeviceNew(sys_util::Error),
     BlockSignal(sys_util::signal::Error),
-    BuildingVm(Box<error::Error>),
+    BuildVm(<Arch as LinuxArch>::Error),
     ChownTpmStorage(sys_util::Error),
     CloneEventFd(sys_util::Error),
     CreateCrasClient(libcras::Error),
@@ -123,7 +123,7 @@ impl Display for Error {
             BalloonDeviceNew(e) => write!(f, "failed to create balloon: {}", e),
             BlockDeviceNew(e) => write!(f, "failed to create block device: {}", e),
             BlockSignal(e) => write!(f, "failed to block signal: {}", e),
-            BuildingVm(e) => write!(f, "The architecture failed to build the vm: {}", e),
+            BuildVm(e) => write!(f, "The architecture failed to build the vm: {}", e),
             ChownTpmStorage(e) => write!(f, "failed to chown tpm storage: {}", e),
             CloneEventFd(e) => write!(f, "failed to clone eventfd: {}", e),
             CreateCrasClient(e) => write!(f, "failed to create cras client: {}", e),
@@ -1113,9 +1113,8 @@ pub fn run_config(cfg: Config) -> Result<()> {
             balloon_device_socket,
             &mut disk_device_sockets,
         )
-        .map_err(|e| Box::new(e) as Box<dyn std::error::Error>)
     })
-    .map_err(Error::BuildingVm)?;
+    .map_err(Error::BuildVm)?;
     run_control(
         linux,
         control_server_socket,
diff --git a/x86_64/src/fdt.rs b/x86_64/src/fdt.rs
index 4f3084f..d725ffe 100644
--- a/x86_64/src/fdt.rs
+++ b/x86_64/src/fdt.rs
@@ -29,7 +29,7 @@ pub fn create_fdt(
     guest_mem: &GuestMemory,
     fdt_load_offset: u64,
     android_fstab: &mut File,
-) -> Result<usize, Box<Error>> {
+) -> Result<usize, Error> {
     // Reserve space for the setup_data
     let fdt_data_size = fdt_max_size - mem::size_of::<setup_data>();
 
@@ -85,7 +85,7 @@ pub fn create_fdt(
         .write_at_addr(fdt_final.as_slice(), fdt_data_address)
         .map_err(|_| Error::FdtGuestMemoryWriteError)?;
     if written < fdt_data_size {
-        return Err(Box::new(Error::FdtGuestMemoryWriteError));
+        return Err(Error::FdtGuestMemoryWriteError);
     }
     Ok(fdt_data_size)
 }
diff --git a/x86_64/src/lib.rs b/x86_64/src/lib.rs
index fb4825c..0038a25 100644
--- a/x86_64/src/lib.rs
+++ b/x86_64/src/lib.rs
@@ -66,12 +66,12 @@ mod interrupts;
 mod mptable;
 mod regs;
 
+use std::error::Error as StdError;
 use std::ffi::{CStr, CString};
 use std::fmt::{self, Display};
 use std::fs::File;
 use std::io::{self, stdout};
 use std::mem;
-use std::result;
 use std::sync::Arc;
 
 use arch::{RunnableLinuxVm, VmComponents};
@@ -82,76 +82,90 @@ use io_jail::Minijail;
 use kvm::*;
 use resources::{AddressRanges, SystemAllocator};
 use sync::Mutex;
-use sys_util::{Clock, EventFd, GuestAddress, GuestMemory};
+use sys_util::{Clock, EventFd, GuestAddress, GuestMemory, GuestMemoryError};
 
 #[derive(Debug)]
 pub enum Error {
-    /// Error configuring the system
-    ConfigureSystem,
-    /// Unable to clone an EventFd
     CloneEventFd(sys_util::Error),
-    /// Error creating kernel command line.
     Cmdline(kernel_cmdline::Error),
-    /// Unable to make an EventFd
+    ConfigureSystem,
+    CreateDevices(Box<dyn StdError>),
     CreateEventFd(sys_util::Error),
-    /// Unable to create PIT device.
-    CreatePit(devices::PitError),
-    /// Unable to create Kvm.
+    CreateFdt(arch::fdt::Error),
+    CreateIrqChip(sys_util::Error),
     CreateKvm(sys_util::Error),
-    /// Unable to create a PciRoot hub.
     CreatePciRoot(arch::DeviceRegistrationError),
-    /// Unable to create socket.
+    CreatePit(sys_util::Error),
+    CreatePitDevice(devices::PitError),
     CreateSocket(io::Error),
-    /// Unable to create Vcpu.
     CreateVcpu(sys_util::Error),
-    /// The kernel extends past the end of RAM
+    CreateVm(sys_util::Error),
+    E820Configuration,
     KernelOffsetPastEnd,
-    /// Error registering an IrqFd
-    RegisterIrqfd(sys_util::Error),
-    /// Couldn't register virtio socket.
-    RegisterVsock(arch::DeviceRegistrationError),
     LoadCmdline(kernel_loader::Error),
-    LoadKernel(kernel_loader::Error),
     LoadInitrd(arch::LoadImageError),
-    /// Error writing the zero page of guest memory.
-    ZeroPageSetup,
-    /// The zero page extends past the end of guest_mem.
+    LoadKernel(kernel_loader::Error),
+    RegisterIrqfd(sys_util::Error),
+    RegisterVsock(arch::DeviceRegistrationError),
+    SetLint(interrupts::Error),
+    SetTssAddr(sys_util::Error),
+    SetupCpuid(cpuid::Error),
+    SetupFpu(regs::Error),
+    SetupGuestMemory(GuestMemoryError),
+    SetupMptable(mptable::Error),
+    SetupMsrs(regs::Error),
+    SetupRegs(regs::Error),
+    SetupSregs(regs::Error),
     ZeroPagePastRamEnd,
-    /// Invalid e820 setup params.
-    E820Configuration,
+    ZeroPageSetup,
 }
 
-impl std::error::Error for Error {}
-
 impl Display for Error {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         use self::Error::*;
 
         match self {
-            ConfigureSystem => write!(f, "error configuring the system"),
             CloneEventFd(e) => write!(f, "unable to clone an EventFd: {}", e),
             Cmdline(e) => write!(f, "the given kernel command line was invalid: {}", e),
+            ConfigureSystem => write!(f, "error configuring the system"),
+            CreateDevices(e) => write!(f, "error creating devices: {}", e),
             CreateEventFd(e) => write!(f, "unable to make an EventFd: {}", e),
-            CreatePit(e) => write!(f, "unable to make Pit device: {}", e),
+            CreateFdt(e) => write!(f, "failed to create fdt: {}", e),
+            CreateIrqChip(e) => write!(f, "failed to create irq chip: {}", e),
             CreateKvm(e) => write!(f, "failed to open /dev/kvm: {}", e),
             CreatePciRoot(e) => write!(f, "failed to create a PCI root hub: {}", e),
+            CreatePit(e) => write!(f, "unable to create PIT: {}", e),
+            CreatePitDevice(e) => write!(f, "unable to make PIT device: {}", e),
             CreateSocket(e) => write!(f, "failed to create socket: {}", e),
             CreateVcpu(e) => write!(f, "failed to create VCPU: {}", e),
+            CreateVm(e) => write!(f, "failed to create VM: {}", e),
+            E820Configuration => write!(f, "invalid e820 setup params"),
             KernelOffsetPastEnd => write!(f, "the kernel extends past the end of RAM"),
+            LoadCmdline(e) => write!(f, "error loading command line: {}", e),
+            LoadInitrd(e) => write!(f, "error loading initrd: {}", e),
+            LoadKernel(e) => write!(f, "error loading Kernel: {}", e),
             RegisterIrqfd(e) => write!(f, "error registering an IrqFd: {}", e),
             RegisterVsock(e) => write!(f, "error registering virtual socket device: {}", e),
-            LoadCmdline(e) => write!(f, "error Loading command line: {}", e),
-            LoadKernel(e) => write!(f, "error Loading Kernel: {}", e),
-            LoadInitrd(e) => write!(f, "error loading initrd: {}", e),
-            ZeroPageSetup => write!(f, "error writing the zero page of guest memory"),
+            SetLint(e) => write!(f, "failed to set interrupts: {}", e),
+            SetTssAddr(e) => write!(f, "failed to set tss addr: {}", e),
+            SetupCpuid(e) => write!(f, "failed to set up cpuid: {}", e),
+            SetupFpu(e) => write!(f, "failed to set up FPU: {}", e),
+            SetupGuestMemory(e) => write!(f, "failed to set up guest memory: {}", e),
+            SetupMptable(e) => write!(f, "failed to set up mptable: {}", e),
+            SetupMsrs(e) => write!(f, "failed to set up MSRs: {}", e),
+            SetupRegs(e) => write!(f, "failed to set up registers: {}", e),
+            SetupSregs(e) => write!(f, "failed to set up sregs: {}", e),
             ZeroPagePastRamEnd => write!(f, "the zero page extends past the end of guest_mem"),
-            E820Configuration => write!(f, "invalid e820 setup params"),
+            ZeroPageSetup => write!(f, "error writing the zero page of guest memory"),
         }
     }
 }
 
+pub type Result<T> = std::result::Result<T, Error>;
+
+impl std::error::Error for Error {}
+
 pub struct X8664arch;
-pub type Result<T> = result::Result<T, Box<std::error::Error>>;
 
 const BOOT_STACK_POINTER: u64 = 0x8000;
 const MEM_32BIT_GAP_SIZE: u64 = (768 << 20);
@@ -184,7 +198,7 @@ fn configure_system(
     let end_32bit_gap_start = GuestAddress(FIRST_ADDR_PAST_32BITS - MEM_32BIT_GAP_SIZE);
 
     // Note that this puts the mptable at 0x0 in guest physical memory.
-    mptable::setup_mptable(guest_mem, num_cpus, pci_irqs)?;
+    mptable::setup_mptable(guest_mem, num_cpus, pci_irqs).map_err(Error::SetupMptable)?;
 
     let mut params: boot_params = Default::default();
 
@@ -243,7 +257,7 @@ fn configure_system(
 /// 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<()> {
     if params.e820_entries >= params.e820_map.len() as u8 {
-        return Err(Box::new(Error::E820Configuration));
+        return Err(Error::E820Configuration);
     }
 
     params.e820_map[params.e820_entries as usize].addr = addr;
@@ -280,7 +294,9 @@ fn arch_memory_regions(size: u64) -> Vec<(GuestAddress, u64)> {
 }
 
 impl arch::LinuxArch for X8664arch {
-    fn build_vm<F>(
+    type Error = Error;
+
+    fn build_vm<F, E>(
         mut components: VmComponents,
         split_irqchip: bool,
         create_devices: F,
@@ -289,7 +305,8 @@ impl arch::LinuxArch for X8664arch {
         F: FnOnce(
             &GuestMemory,
             &EventFd,
-        ) -> Result<Vec<(Box<PciDevice + 'static>, Option<Minijail>)>>,
+        ) -> std::result::Result<Vec<(Box<PciDevice>, Option<Minijail>)>, E>,
+        E: StdError + 'static,
     {
         let mut resources =
             Self::get_resource_allocator(components.memory_mb, components.wayland_dmabuf);
@@ -319,7 +336,8 @@ impl arch::LinuxArch for X8664arch {
 
         let exit_evt = EventFd::new().map_err(Error::CreateEventFd)?;
 
-        let pci_devices = create_devices(&mem, &exit_evt)?;
+        let pci_devices =
+            create_devices(&mem, &exit_evt).map_err(|e| Error::CreateDevices(Box::new(e)))?;
         let (pci, pci_irqs, pid_debug_label_map) =
             arch::generate_pci_root(pci_devices, &mut mmio_bus, &mut resources, &mut vm)
                 .map_err(Error::CreatePciRoot)?;
@@ -374,11 +392,8 @@ impl X8664arch {
     /// * `mem` - The memory to be used by the guest.
     /// * `kernel_image` - the File object for the specified kernel.
     fn load_kernel(mem: &GuestMemory, mut kernel_image: &mut File) -> Result<u64> {
-        Ok(kernel_loader::load_kernel(
-            mem,
-            GuestAddress(KERNEL_START_OFFSET),
-            &mut kernel_image,
-        )?)
+        kernel_loader::load_kernel(mem, GuestAddress(KERNEL_START_OFFSET), &mut kernel_image)
+            .map_err(Error::LoadKernel)
     }
 
     /// Configures the system memory space should be called once per vm before
@@ -400,7 +415,8 @@ impl X8664arch {
         android_fstab: Option<File>,
         kernel_end: u64,
     ) -> Result<()> {
-        kernel_loader::load_cmdline(mem, GuestAddress(CMDLINE_OFFSET), cmdline)?;
+        kernel_loader::load_cmdline(mem, GuestAddress(CMDLINE_OFFSET), cmdline)
+            .map_err(Error::LoadCmdline)?;
 
         // Track the first free address after the kernel - this is where extra
         // data like the device tree blob and initrd will be loaded.
@@ -415,7 +431,8 @@ impl X8664arch {
                 mem,
                 dtb_start.offset(),
                 &mut fstab,
-            )?;
+            )
+            .map_err(Error::CreateFdt)?;
             free_addr = dtb_start.offset() + dtb_size as u64;
             Some(dtb_start)
         } else {
@@ -460,12 +477,12 @@ impl X8664arch {
     /// * `split_irqchip` - Whether to use a split IRQ chip.
     /// * `mem` - The memory to be used by the guest.
     fn create_vm(kvm: &Kvm, split_irqchip: bool, mem: GuestMemory) -> Result<Vm> {
-        let vm = Vm::new(&kvm, mem)?;
+        let vm = Vm::new(&kvm, mem).map_err(Error::CreateVm)?;
         let tss_addr = GuestAddress(0xfffbd000);
-        vm.set_tss_addr(tss_addr).expect("set tss addr failed");
+        vm.set_tss_addr(tss_addr).map_err(Error::SetTssAddr)?;
         if !split_irqchip {
-            vm.create_pit().expect("create pit failed");
-            vm.create_irq_chip()?;
+            vm.create_pit().map_err(Error::CreatePit)?;
+            vm.create_irq_chip().map_err(Error::CreateIrqChip)?;
         }
         Ok(vm)
     }
@@ -473,9 +490,9 @@ impl X8664arch {
     /// This creates a GuestMemory object for this VM
     ///
     /// * `mem_size` - Desired physical memory size in bytes for this VM
-    fn setup_memory(mem_size: u64) -> Result<sys_util::GuestMemory> {
+    fn setup_memory(mem_size: u64) -> Result<GuestMemory> {
         let arch_mem_regions = arch_memory_regions(mem_size);
-        let mem = GuestMemory::new(&arch_mem_regions)?;
+        let mem = GuestMemory::new(&arch_mem_regions).map_err(Error::SetupGuestMemory)?;
         Ok(mem)
     }
 
@@ -610,7 +627,7 @@ impl X8664arch {
                     pit_evt.try_clone().map_err(Error::CloneEventFd)?,
                     Arc::new(Mutex::new(Clock::new())),
                 )
-                .map_err(Error::CreatePit)?,
+                .map_err(Error::CreatePitDevice)?,
             ));
             // Reserve from 0x40 to 0x61 (the speaker).
             io_bus.insert(pit.clone(), 0x040, 0x22, false).unwrap();
@@ -667,8 +684,8 @@ impl X8664arch {
         num_cpus: u64,
     ) -> Result<()> {
         let kernel_load_addr = GuestAddress(KERNEL_START_OFFSET);
-        cpuid::setup_cpuid(kvm, vcpu, cpu_id, num_cpus)?;
-        regs::setup_msrs(vcpu)?;
+        cpuid::setup_cpuid(kvm, vcpu, cpu_id, num_cpus).map_err(Error::SetupCpuid)?;
+        regs::setup_msrs(vcpu).map_err(Error::SetupMsrs)?;
         let kernel_end = guest_mem
             .checked_offset(kernel_load_addr, KERNEL_64BIT_ENTRY_OFFSET)
             .ok_or(Error::KernelOffsetPastEnd)?;
@@ -677,10 +694,11 @@ impl X8664arch {
             (kernel_end).offset() as u64,
             BOOT_STACK_POINTER as u64,
             ZERO_PAGE_OFFSET as u64,
-        )?;
-        regs::setup_fpu(vcpu)?;
-        regs::setup_sregs(guest_mem, vcpu)?;
-        interrupts::set_lint(vcpu)?;
+        )
+        .map_err(Error::SetupRegs)?;
+        regs::setup_fpu(vcpu).map_err(Error::SetupFpu)?;
+        regs::setup_sregs(guest_mem, vcpu).map_err(Error::SetupSregs)?;
+        interrupts::set_lint(vcpu).map_err(Error::SetLint)?;
         Ok(())
     }
 }