Skip to content

Commit c380367

Browse files
Improved error typing
Signed-off-by: Jonathan Woollett-Light <[email protected]
1 parent 4418a0c commit c380367

30 files changed

+886
-455
lines changed

.cargo/config

-6
This file was deleted.

src/arch/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ 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"
19+
vmm-sys-util = ">=0.8.0"
1820

1921
arch_gen = { path = "../arch_gen" }
2022
logger = { path = "../logger" }

src/arch/src/x86_64/interrupts.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,13 @@ 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)]
1313
pub enum Error {
1414
/// Failure in retrieving the LAPIC configuration.
15+
#[error("Failure in retrieving the LAPIC configuration: {0}")]
1516
GetLapic(kvm_ioctls::Error),
1617
/// Failure in modifying the LAPIC configuration.
18+
#[error("Failure in modifying the LAPIC configuration: {0}")]
1719
SetLapic(kvm_ioctls::Error),
1820
}
1921
type Result<T> = std::result::Result<T, Error>;

src/arch/src/x86_64/msr.rs

+28-4
Original file line numberDiff line numberDiff line change
@@ -282,18 +282,42 @@ 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+
/// Could not create [`vmm_sys_util::fam::FamStructWrapper`] for MSRs.
289+
#[error("Could not create `vmm_sys_util::fam::FamStructWrapper` for MSRs")]
290+
CreateMSRs(utils::fam::Error),
291+
/// Setting MSRs resulted in an error.
292+
#[error("Setting MSRs resulted in an error: {0}")]
293+
SetModelSpecificRegisters(#[from] kvm_ioctls::Error),
294+
/// Not all given MSRs where set.
295+
#[error("Not all given MSRs where set.")]
296+
SetModelSpecificRegistersCount,
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 when trying to create [`vmm_sys_util::fam::FamStructWrapper`] for MSRs.
309+
/// - [`kvm_ioctls::ioctls::vcpu::VcpuFd::set_msrs`] errors.
310+
/// - When [`kvm_ioctls::ioctls::vcpu::VcpuFd::set_msrs`] failed to write all 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::CreateMSRs)?;
292316
vcpu.set_msrs(&msrs)
293-
.map_err(Error::SetModelSpecificRegisters)
317+
.map_err(SetMSRsError::SetModelSpecificRegisters)
294318
.and_then(|msrs_written| {
295319
if msrs_written as u32 != msrs.as_fam_struct_ref().nmsrs {
296-
Err(Error::SetModelSpecificRegistersCount)
320+
Err(SetMSRsError::SetModelSpecificRegistersCount)
297321
} else {
298322
Ok(())
299323
}

src/arch/src/x86_64/regs.rs

+84-13
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)]
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 types for [`setup_fpu`].
55+
#[derive(Debug, derive_more::From)]
56+
pub struct SetupFpuError(vmm_sys_util::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)]
86+
pub struct SetupRegistersError(vmm_sys_util::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,25 @@ 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+
let res = vcpu.set_regs(&regs)?;
121+
Ok(res)
122+
}
123+
124+
/// Error type for [`setup_sregs`].
125+
#[derive(Debug, thiserror::Error)]
126+
pub enum SetupSegmentRegistersError {
127+
/// Failed to get segment registers
128+
#[error("Failed to get segment registers: {0}")]
129+
GetSegmentRegisters(#[from] vmm_sys_util::errno::Error),
130+
/// Failed to configure segments and segment registers
131+
#[error("Failed to configure segments and segment registers: {0}")]
132+
ConfigureSegmentsAndSegmentRegisters(Error),
133+
/// Failed to setup page tables
134+
#[error("Failed to setup page tables: {0}")]
135+
SetupPageTables(Error),
136+
/// Failed to set segment registers
137+
#[error("Failed to set segment registers: {0}")]
138+
SetSegmentRegisters(vmm_sys_util::errno::Error),
83139
}
84140

85141
/// Configures the segment registers and system page tables for a given CPU.
@@ -88,13 +144,28 @@ pub fn setup_regs(vcpu: &VcpuFd, boot_ip: u64) -> Result<()> {
88144
///
89145
/// * `mem` - The memory that will be passed to the guest.
90146
/// * `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)
147+
///
148+
/// # Errors
149+
///
150+
/// When:
151+
/// - [`kvm_ioctls::ioctls::vcpu::VcpuFd::get_sregs`] errors.
152+
/// - [`configure_segments_and_sregs`] errors.
153+
/// - [`setup_page_tables`] errors
154+
/// - [`kvm_ioctls::ioctls::vcpu::VcpuFd::set_sregs`] errors.
155+
pub fn setup_sregs(
156+
mem: &GuestMemoryMmap,
157+
vcpu: &VcpuFd,
158+
) -> std::result::Result<(), SetupSegmentRegistersError> {
159+
let mut sregs: kvm_sregs = vcpu
160+
.get_sregs()
161+
.map_err(SetupSegmentRegistersError::GetSegmentRegisters)?;
162+
163+
configure_segments_and_sregs(mem, &mut sregs)
164+
.map_err(SetupSegmentRegistersError::ConfigureSegmentsAndSegmentRegisters)?;
165+
setup_page_tables(mem, &mut sregs).map_err(SetupSegmentRegistersError::SetupPageTables)?; // TODO(dgreid) - Can this be done once per system instead?
166+
167+
vcpu.set_sregs(&sregs)
168+
.map_err(SetupSegmentRegistersError::SetSegmentRegisters)
98169
}
99170

100171
const BOOT_GDT_OFFSET: u64 = 0x500;

src/bit-fields-macros/src/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -446,8 +446,8 @@ pub fn bitfield(item: proc_macro::TokenStream) -> proc_macro::TokenStream {
446446
#[cfg(feature = "field_map")]
447447
write!(
448448
&mut field_setting_hashmap,
449-
"map.insert(String::from(\"{field_ident}\"),{struct_data_type}::\
450-
from(&bit_field.{field_ident}));",
449+
"map.insert(String::from(\"{field_ident}\"),\
450+
{struct_data_type}::from(&bit_field.{field_ident}));",
451451
struct_data_type = struct_data_type,
452452
field_ident = field_ident
453453
)

src/cpuid/Cargo.toml

+2
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ 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" }
1516

17+
vmm-sys-util = ">=0.8.0"
1618
bit-fields = { path = "../bit-fields", features = ["serde_feature"] }
1719
phf = { version = "0.10", features = ["macros"] }
1820
serde = { version="1.0.138", features=["derive"] }

src/cpuid/benches/benchmark.rs

+17-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
use criterion::{black_box, criterion_group, criterion_main, Criterion,BenchmarkId};
2-
use cpuid::{RawCpuid,Cpuid,AmdCpuid,IntelCpuid};
3-
use std::convert::{From,TryFrom};
1+
use std::convert::{From, TryFrom};
2+
3+
use cpuid::{AmdCpuid, Cpuid, IntelCpuid, RawCpuid};
4+
use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion};
45

56
pub fn conversions(c: &mut Criterion) {
67
let kvm = kvm_ioctls::Kvm::new().unwrap();
@@ -20,14 +21,22 @@ pub fn conversions(c: &mut Criterion) {
2021
c.bench_function("cpuid.clone()", |b| b.iter(|| cpuid.clone()));
2122

2223
c.bench_function("kvm->raw", |b| b.iter(|| RawCpuid::from(kvm_cpuid.clone())));
23-
c.bench_function("raw->kvm", |b| b.iter(|| kvm_bindings::CpuId::from(raw_cpuid.clone())));
24-
c.bench_function("raw->cpuid", |b| b.iter(|| Cpuid::try_from(raw_cpuid.clone())));
24+
c.bench_function("raw->kvm", |b| {
25+
b.iter(|| kvm_bindings::CpuId::from(raw_cpuid.clone()))
26+
});
27+
c.bench_function("raw->cpuid", |b| {
28+
b.iter(|| Cpuid::try_from(raw_cpuid.clone()))
29+
});
2530
c.bench_function("cpuid->raw", |b| b.iter(|| RawCpuid::from(cpuid.clone())));
2631
c.bench_function("amd->raw", |b| b.iter(|| RawCpuid::from(amd_cpuid.clone())));
2732
c.bench_function("raw->amd", |b| b.iter(|| AmdCpuid::from(raw_cpuid.clone())));
28-
c.bench_function("intel->raw", |b| b.iter(|| RawCpuid::from(intel_cpuid.clone())));
29-
c.bench_function("raw->intel", |b| b.iter(|| IntelCpuid::from(raw_cpuid.clone())));
33+
c.bench_function("intel->raw", |b| {
34+
b.iter(|| RawCpuid::from(intel_cpuid.clone()))
35+
});
36+
c.bench_function("raw->intel", |b| {
37+
b.iter(|| IntelCpuid::from(raw_cpuid.clone()))
38+
});
3039
}
3140

3241
criterion_group!(benches, conversions);
33-
criterion_main!(benches);
42+
criterion_main!(benches);

src/cpuid/src/brand_string.rs

+1
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,7 @@ impl BrandString {
139139
/// Returns the given register value for the given CPUID leaf.
140140
///
141141
/// `leaf` must be between 0x80000002 and 0x80000004.
142+
#[cfg(test)]
142143
#[inline]
143144
pub fn get_reg_for_leaf(&self, leaf: u32, reg: Reg) -> u32 {
144145
// It's ok not to validate parameters here, leaf and reg should

0 commit comments

Comments
 (0)