Skip to content

Commit ebb78f0

Browse files
author
Jonathan Woollett-Light
committed
CPUID template expansion
Changes to support full CPUID coverage and template configurability. Signed-off-by: Jonathan Woollett-Light <[email protected]>
1 parent c127040 commit ebb78f0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+9161
-2508
lines changed

src/api_server/Cargo.toml

+1
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

+3-9
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

+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

+9-7
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)]
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

+30-6
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

+83-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 type 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,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)]
125+
pub enum SetupSegmentRegistersError {
126+
/// Failed to get segment registers
127+
#[error("Failed to get segment registers: {0}")]
128+
GetSegmentRegisters(vmm_sys_util::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(vmm_sys_util::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/bit-fields-macros/Cargo.toml

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
[package]
2+
name = "bit-fields-macros"
3+
version = "0.1.0"
4+
edition = "2018"
5+
6+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
7+
[dependencies]
8+
quote = "1.0.21"
9+
proc-macro2 = "1.0.43"
10+
11+
[features]
12+
set_theory = []
13+
bit_index = []
14+
flag_set = []
15+
field_map = []
16+
display = []
17+
cmp_flags = []
18+
serde = ["flag_set","field_map"]
19+
20+
[lib]
21+
proc-macro = true

0 commit comments

Comments
 (0)