Skip to content

Commit 2244c3a

Browse files
author
Jonathan Woollett-Light
committed
Error type expansion
Signed-off-by: Jonathan Woollett-Light <[email protected]>
1 parent c127040 commit 2244c3a

26 files changed

+815
-437
lines changed

src/api_server/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ serde = { version = ">=1.0.27", features = ["derive"] }
1111
serde_derive = ">=1.0.27"
1212
serde_json = ">=1.0.9"
1313
derive_more = { version = "0.99.17", default-features = false, features = ["from"] }
14+
thiserror = "1.0.32"
1415

1516
logger = { path = "../logger" }
1617
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", rev = "0a58eb1" }

src/api_server/src/lib.rs

Lines changed: 3 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -34,22 +34,16 @@ pub type ApiRequest = Box<VmmAction>;
3434
pub type ApiResponse = Box<std::result::Result<VmmData, VmmActionError>>;
3535

3636
/// Errors thrown when binding the API server to the socket path.
37+
#[derive(thiserror::Error)]
3738
pub enum Error {
3839
/// IO related error.
40+
#[error("IO error: {0}")]
3941
Io(io::Error),
4042
/// EventFD related error.
43+
#[error("EventFd error: {0}")]
4144
Eventfd(io::Error),
4245
}
4346

44-
impl fmt::Display for Error {
45-
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
46-
match *self {
47-
Error::Io(ref err) => write!(f, "IO error: {}", err),
48-
Error::Eventfd(ref err) => write!(f, "EventFd error: {}", err),
49-
}
50-
}
51-
}
52-
5347
impl fmt::Debug for Error {
5448
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
5549
match *self {

src/arch/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ versionize = ">=0.1.6"
1414
versionize_derive = ">=0.1.3"
1515
vm-fdt = "0.1.0"
1616
derive_more = { version = "0.99.17", default-features = false, features = ["from"] }
17+
thiserror = "1.0.32"
1718
bitflags = ">=1.0.4"
1819

1920
arch_gen = { path = "../arch_gen" }

src/arch/src/x86_64/interrupts.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ use kvm_bindings::kvm_lapic_state;
99
use kvm_ioctls::VcpuFd;
1010
use utils::byte_order;
1111
/// Errors thrown while configuring the LAPIC.
12-
#[derive(Debug)]
12+
#[derive(Debug, thiserror::Error, PartialEq)]
1313
pub enum Error {
14-
/// Failure in retrieving the LAPIC configuration.
15-
GetLapic(kvm_ioctls::Error),
16-
/// Failure in modifying the LAPIC configuration.
17-
SetLapic(kvm_ioctls::Error),
14+
/// Failure in getting the LAPIC configuration.
15+
#[error("Failure in getting the LAPIC configuration: {0}")]
16+
Get(kvm_ioctls::Error),
17+
/// Failure in setting the LAPIC configuration.
18+
#[error("Failure in setting the LAPIC configuration: {0}")]
19+
Set(kvm_ioctls::Error),
1820
}
1921
type Result<T> = std::result::Result<T, Error>;
2022

@@ -45,7 +47,7 @@ fn set_apic_delivery_mode(reg: u32, mode: u32) -> u32 {
4547
/// # Arguments
4648
/// * `vcpu` - The VCPU object to configure.
4749
pub fn set_lint(vcpu: &VcpuFd) -> Result<()> {
48-
let mut klapic = vcpu.get_lapic().map_err(Error::GetLapic)?;
50+
let mut klapic = vcpu.get_lapic().map_err(Error::Get)?;
4951

5052
let lvt_lint0 = get_klapic_reg(&klapic, APIC_LVT0);
5153
set_klapic_reg(
@@ -60,7 +62,7 @@ pub fn set_lint(vcpu: &VcpuFd) -> Result<()> {
6062
set_apic_delivery_mode(lvt_lint1, APIC_MODE_NMI),
6163
);
6264

63-
vcpu.set_lapic(&klapic).map_err(Error::SetLapic)
65+
vcpu.set_lapic(&klapic).map_err(Error::Set)
6466
}
6567

6668
#[cfg(test)]

src/arch/src/x86_64/msr.rs

Lines changed: 30 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -282,20 +282,44 @@ pub fn create_boot_msr_entries() -> Vec<kvm_msr_entry> {
282282
]
283283
}
284284

285+
/// Error type for [`set_msrs`].
286+
#[derive(Debug, thiserror::Error)]
287+
pub enum SetMSRsError {
288+
/// Failed to create [`vmm_sys_util::fam::FamStructWrapper`] for MSRs.
289+
#[error("Could not create `vmm_sys_util::fam::FamStructWrapper` for MSRs")]
290+
Create(utils::fam::Error),
291+
/// Settings MSRs resulted in an error.
292+
#[error("Setting MSRs resulted in an error: {0}")]
293+
Set(#[from] kvm_ioctls::Error),
294+
/// Not all given MSRs where set.
295+
#[error("Not all given MSRs where set.")]
296+
Incomplete,
297+
}
298+
285299
/// Configure Model Specific Registers (MSRs) required to boot Linux for a given x86_64 vCPU.
286300
///
287301
/// # Arguments
288302
///
289303
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
290-
pub fn set_msrs(vcpu: &VcpuFd, msr_entries: &[kvm_msr_entry]) -> Result<()> {
291-
let msrs = Msrs::from_entries(&msr_entries).map_err(Error::FamError)?;
304+
///
305+
/// # Errors
306+
///
307+
/// When:
308+
/// - Failed to create [`vmm_sys_util::fam::FamStructWrapper`] for MSRs.
309+
/// - [`kvm_ioctls::ioctls::vcpu::VcpuFd::set_msrs`] errors.
310+
/// - [`kvm_ioctls::ioctls::vcpu::VcpuFd::set_msrs`] fails to write all given MSRs entries.
311+
pub fn set_msrs(
312+
vcpu: &VcpuFd,
313+
msr_entries: &[kvm_msr_entry],
314+
) -> std::result::Result<(), SetMSRsError> {
315+
let msrs = Msrs::from_entries(&msr_entries).map_err(SetMSRsError::Create)?;
292316
vcpu.set_msrs(&msrs)
293-
.map_err(Error::SetModelSpecificRegisters)
317+
.map_err(SetMSRsError::Set)
294318
.and_then(|msrs_written| {
295-
if msrs_written as u32 != msrs.as_fam_struct_ref().nmsrs {
296-
Err(Error::SetModelSpecificRegistersCount)
297-
} else {
319+
if msrs_written as u32 == msrs.as_fam_struct_ref().nmsrs {
298320
Ok(())
321+
} else {
322+
Err(SetMSRsError::Incomplete)
299323
}
300324
})
301325
}

src/arch/src/x86_64/regs.rs

Lines changed: 83 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// Use of this source code is governed by a BSD-style license that can be
66
// found in the THIRD-PARTY file.
77

8-
use std::mem;
8+
use std::{fmt, mem};
99

1010
use kvm_bindings::{kvm_fpu, kvm_regs, kvm_sregs};
1111
use kvm_ioctls::VcpuFd;
@@ -19,42 +19,76 @@ const PDPTE_START: u64 = 0xa000;
1919
const PDE_START: u64 = 0xb000;
2020

2121
/// Errors thrown while setting up x86_64 registers.
22-
#[derive(Debug)]
22+
#[derive(Debug, thiserror::Error, PartialEq)]
2323
pub enum Error {
2424
/// Failed to get SREGs for this CPU.
25+
#[error("Failed to get SREGs for this CPU: {0}")]
2526
GetStatusRegisters(kvm_ioctls::Error),
2627
/// Failed to set base registers for this CPU.
28+
#[error("Failed to set base registers for this CPU: {0}")]
2729
SetBaseRegisters(kvm_ioctls::Error),
2830
/// Failed to configure the FPU.
31+
#[error("Failed to configure the FPU: {0}")]
2932
SetFPURegisters(kvm_ioctls::Error),
3033
/// Failed to set SREGs for this CPU.
34+
#[error("Failed to set SREGs for this CPU: {0}")]
3135
SetStatusRegisters(kvm_ioctls::Error),
3236
/// Writing the GDT to RAM failed.
37+
#[error("Writing the GDT to RAM failed.")]
3338
WriteGDT,
3439
/// Writing the IDT to RAM failed.
40+
#[error("Writing the IDT to RAM failed")]
3541
WriteIDT,
3642
/// Writing PDPTE to RAM failed.
43+
#[error("WritePDPTEAddress")]
3744
WritePDPTEAddress,
3845
/// Writing PDE to RAM failed.
46+
#[error("WritePDEAddress")]
3947
WritePDEAddress,
4048
/// Writing PML4 to RAM failed.
49+
#[error("WritePML4Address")]
4150
WritePML4Address,
4251
}
4352
type Result<T> = std::result::Result<T, Error>;
4453

54+
/// Error type for [`setup_fpu`].
55+
#[derive(Debug, derive_more::From, PartialEq)]
56+
pub struct SetupFpuError(utils::errno::Error);
57+
impl std::error::Error for SetupFpuError {}
58+
impl fmt::Display for SetupFpuError {
59+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
60+
write!(f, "Failed to setup FPU: {}", self.0)
61+
}
62+
}
63+
4564
/// Configure Floating-Point Unit (FPU) registers for a given CPU.
4665
///
4766
/// # Arguments
4867
///
4968
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
50-
pub fn setup_fpu(vcpu: &VcpuFd) -> Result<()> {
69+
///
70+
/// # Errors
71+
///
72+
/// When [`kvm_ioctls::ioctls::vcpu::VcpuFd::set_fpu`] errors.
73+
pub fn setup_fpu(vcpu: &VcpuFd) -> std::result::Result<(), SetupFpuError> {
5174
let fpu: kvm_fpu = kvm_fpu {
5275
fcw: 0x37f,
5376
mxcsr: 0x1f80,
5477
..Default::default()
5578
};
5679

57-
vcpu.set_fpu(&fpu).map_err(Error::SetFPURegisters)
80+
let res = vcpu.set_fpu(&fpu)?;
81+
Ok(res)
82+
}
83+
84+
/// Error type of [`setup_regs`].
85+
#[derive(Debug, derive_more::From, PartialEq)]
86+
pub struct SetupRegistersError(utils::errno::Error);
87+
impl std::error::Error for SetupRegistersError {}
88+
impl fmt::Display for SetupRegistersError {
89+
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
90+
write!(f, "Failed to setup registers:{}", self.0)
91+
}
5892
}
5993

6094
/// Configure base registers for a given CPU.
@@ -63,7 +97,11 @@ pub fn setup_fpu(vcpu: &VcpuFd) -> Result<()> {
6397
///
6498
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
6599
/// * `boot_ip` - Starting instruction pointer.
66-
pub fn setup_regs(vcpu: &VcpuFd, boot_ip: u64) -> Result<()> {
100+
///
101+
/// # Errors
102+
///
103+
/// When [`kvm_ioctls::ioctls::vcpu::VcpuFd::set_regs`] errors.
104+
pub fn setup_regs(vcpu: &VcpuFd, boot_ip: u64) -> std::result::Result<(), SetupRegistersError> {
67105
let regs: kvm_regs = kvm_regs {
68106
rflags: 0x0000_0000_0000_0002u64,
69107
rip: boot_ip,
@@ -79,7 +117,24 @@ pub fn setup_regs(vcpu: &VcpuFd, boot_ip: u64) -> Result<()> {
79117
..Default::default()
80118
};
81119

82-
vcpu.set_regs(&regs).map_err(Error::SetBaseRegisters)
120+
vcpu.set_regs(&regs).map_err(SetupRegistersError)
121+
}
122+
123+
/// Error type for [`setup_sregs`].
124+
#[derive(Debug, thiserror::Error, PartialEq)]
125+
pub enum SetupSegmentRegistersError {
126+
/// Failed to get segment registers
127+
#[error("Failed to get segment registers: {0}")]
128+
GetSegmentRegisters(utils::errno::Error),
129+
/// Failed to configure segments and segment registers
130+
#[error("Failed to configure segments and segment registers: {0}")]
131+
ConfigureSegmentsAndSegmentRegisters(Error),
132+
/// Failed to setup page tables
133+
#[error("Failed to setup page tables: {0}")]
134+
SetupPageTables(Error),
135+
/// Failed to set segment registers
136+
#[error("Failed to set segment registers: {0}")]
137+
SetSegmentRegisters(utils::errno::Error),
83138
}
84139

85140
/// Configures the segment registers and system page tables for a given CPU.
@@ -88,13 +143,28 @@ pub fn setup_regs(vcpu: &VcpuFd, boot_ip: u64) -> Result<()> {
88143
///
89144
/// * `mem` - The memory that will be passed to the guest.
90145
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
91-
pub fn setup_sregs(mem: &GuestMemoryMmap, vcpu: &VcpuFd) -> Result<()> {
92-
let mut sregs: kvm_sregs = vcpu.get_sregs().map_err(Error::GetStatusRegisters)?;
93-
94-
configure_segments_and_sregs(mem, &mut sregs)?;
95-
setup_page_tables(mem, &mut sregs)?; // TODO(dgreid) - Can this be done once per system instead?
96-
97-
vcpu.set_sregs(&sregs).map_err(Error::SetStatusRegisters)
146+
///
147+
/// # Errors
148+
///
149+
/// When:
150+
/// - [`kvm_ioctls::ioctls::vcpu::VcpuFd::get_sregs`] errors.
151+
/// - [`configure_segments_and_sregs`] errors.
152+
/// - [`setup_page_tables`] errors
153+
/// - [`kvm_ioctls::ioctls::vcpu::VcpuFd::set_sregs`] errors.
154+
pub fn setup_sregs(
155+
mem: &GuestMemoryMmap,
156+
vcpu: &VcpuFd,
157+
) -> std::result::Result<(), SetupSegmentRegistersError> {
158+
let mut sregs: kvm_sregs = vcpu
159+
.get_sregs()
160+
.map_err(SetupSegmentRegistersError::GetSegmentRegisters)?;
161+
162+
configure_segments_and_sregs(mem, &mut sregs)
163+
.map_err(SetupSegmentRegistersError::ConfigureSegmentsAndSegmentRegisters)?;
164+
setup_page_tables(mem, &mut sregs).map_err(SetupSegmentRegistersError::SetupPageTables)?; // TODO(dgreid) - Can this be done once per system instead?
165+
166+
vcpu.set_sregs(&sregs)
167+
.map_err(SetupSegmentRegistersError::SetSegmentRegisters)
98168
}
99169

100170
const BOOT_GDT_OFFSET: u64 = 0x500;

src/cpuid/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ license = "Apache-2.0"
99
kvm-bindings = { version = ">=0.5.0", features = ["fam-wrappers"] }
1010
kvm-ioctls = ">=0.9.0"
1111
derive_more = { version = "0.99.17", default-features = false, features = ["from"] }
12+
thiserror = "1.0.32"
1213

1314
utils = { path = "../utils"}
1415
arch = { path = "../arch" }

src/cpuid/src/common.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@ pub const VENDOR_ID_INTEL: &[u8; 12] = b"GenuineIntel";
1818
pub const VENDOR_ID_AMD: &[u8; 12] = b"AuthenticAMD";
1919

2020
/// cpuid related error.
21-
#[derive(Clone, Debug)]
21+
#[derive(Clone, Debug, thiserror::Error, PartialEq, Eq)]
2222
pub enum Error {
2323
/// The function was called with invalid parameters.
24+
#[error("The function was called with invalid parameters.")]
2425
InvalidParameters(String),
2526
/// Function not supported on the current architecture.
27+
#[error("Function not supported on the current architecture.")]
2628
NotSupported,
2729
}
2830

src/cpuid/src/transformer/common.rs

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -114,16 +114,18 @@ pub fn use_host_cpuid_function(
114114
break;
115115
}
116116

117-
cpuid.push(kvm_cpuid_entry2 {
118-
function,
119-
index: count,
120-
flags: 0,
121-
eax: entry.eax,
122-
ebx: entry.ebx,
123-
ecx: entry.ecx,
124-
edx: entry.edx,
125-
padding: [0, 0, 0],
126-
})?;
117+
cpuid
118+
.push(kvm_cpuid_entry2 {
119+
function,
120+
index: count,
121+
flags: 0,
122+
eax: entry.eax,
123+
ebx: entry.ebx,
124+
ecx: entry.ecx,
125+
edx: entry.edx,
126+
padding: [0, 0, 0],
127+
})
128+
.map_err(Error::FamError)?;
127129

128130
count += 1;
129131
}

src/cpuid/src/transformer/mod.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,15 +53,19 @@ impl VmSpec {
5353
}
5454

5555
/// Errors associated with processing the CPUID leaves.
56-
#[derive(Debug, Clone, derive_more::From)]
56+
#[derive(Debug, Clone, thiserror::Error)]
5757
pub enum Error {
5858
/// A FamStructWrapper operation has failed
59+
#[error("A FamStructWrapper operation has failed.")]
5960
FamError(utils::fam::Error),
6061
/// A call to an internal helper method failed
61-
InternalError(super::common::Error),
62+
#[error("A call to an internal helper method failed: {0}")]
63+
InternalError(#[from] super::common::Error),
6264
/// The operation is not permitted for the current vendor
65+
#[error("The operation is not permitted for the current vendor.")]
6366
InvalidVendor,
6467
/// The maximum number of addressable logical CPUs cannot be stored in an `u8`.
68+
#[error("The maximum number of addressable logical CPUs cannot be stored in an `u8`.")]
6569
VcpuCountOverflow,
6670
}
6771

src/seccompiler/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ pub enum InstallationError {
5656
/// Error returned by `prctl`.
5757
Prctl(i32),
5858
}
59+
impl std::error::Error for InstallationError {}
5960

6061
impl Display for InstallationError {
6162
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {

src/snapshot/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ license = "Apache-2.0"
1010
libc = "0.2"
1111
versionize = ">=0.1.6"
1212
versionize_derive = ">=0.1.3"
13+
thiserror = "1.0.32"
1314

1415
[dev-dependencies]
1516
criterion = "0.3.0"

0 commit comments

Comments
 (0)