Skip to content

Commit a33d3c5

Browse files
Alexandru-Cezar Sardanalsrdn
authored andcommitted
cpu templates: add T2S templates
The T2 template lets KVM populate the ARCH_CAPABILITIES MSR by using a copy of the Host information. We sometimes want to force the information contained in that MSR in order to make it look like a less capable processor WRT speculative execution vulnerabilities and mitigations. This is helpful when we want to snapshot a uVM on a newer processor and resume on an older processor. In this case, the software should use only the capabilities that are available in both the newer and older host. Create a new CPU template called T2S which is similar to the T2 template but also sets additional information in the ARCH_CAPABILITIES MSR. We basically set the MSR to expose to the guest a CPU that has the security capabilities of a Skylake CPU, regardless of the host. Also set some bits that were missing from the T2 CPUID config. Adding the MSR information to the cpuid crate is not ideal based on the current implementation. In the end the whole cpuid crate should be refactored to remove the templates implementation into another crate. The assumption that CPUID is the only place where information about the processor is stored proves to be false so we need to extend the templates to include at least the MSRs. Signed-off-by: Alexandru-Cezar Sardan <[email protected]>
1 parent eb2bbca commit a33d3c5

File tree

15 files changed

+212
-21
lines changed

15 files changed

+212
-21
lines changed

CHANGELOG.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,22 @@
11
# Changelog
22

3+
## Unreleased
4+
5+
### Added
6+
7+
- Add a new CPU template called `T2S`. This exposes the same CPUID as `T2`
8+
to the Guest and also overwrites the `ARCH_CAPABILITIES` MSR to expose a
9+
reduced set of capabilities. With regards to hardware vulnerabilities
10+
and mitigations, the Guest vCPU will apear to look like a Skylake CPU,
11+
making it safe to snapshot uVMs running on a newer host CPU (Cascade Lake)
12+
and restore on a host that has a Skylake CPU.
13+
14+
### Fixed
15+
16+
- Make the `T2` template more robust by explicitly disabling additional
17+
CPUID flags that should be off but were missed initially or that were
18+
not available in the spec when the template was created.
19+
320
## [1.1.0]
421

522
### Added

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ The **API endpoint** can be used to:
9696
- Configure the microvm by:
9797
- Setting the number of vCPUs (the default is 1).
9898
- Setting the memory size (the default is 128 MiB).
99-
- [x86_64 only] Choosing a CPU template (currently, C3 and T2 are available).
99+
- [x86_64 only] Choosing a CPU template (currently, C3, T2 and T2S are available).
100100
- Add one or more network interfaces to the microVM.
101101
- Add one or more read-write or read-only disks to the microVM, each represented
102102
by a file-backed block device.

src/api_server/swagger/firecracker.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -782,6 +782,7 @@ definitions:
782782
enum:
783783
- C3
784784
- T2
785+
- T2S
785786
- None
786787
default: "None"
787788

src/arch/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ linux-loader = ">=0.4.0"
1313
versionize = ">=0.1.6"
1414
versionize_derive = ">=0.1.3"
1515
vm-fdt = "0.1.0"
16+
bitflags = ">=1.0.4"
1617

1718
arch_gen = { path = "../arch_gen" }
1819
logger = { path = "../logger" }

src/arch/src/x86_64/msr.rs

Lines changed: 73 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use std::result;
66

77
use arch_gen::x86::msr_index::*;
8+
use bitflags::bitflags;
89
use kvm_bindings::{kvm_msr_entry, MsrList, Msrs};
910
use kvm_ioctls::{Kvm, VcpuFd};
1011

@@ -54,9 +55,74 @@ const MSR_KVM_POLL_CONTROL: u32 = 0x4b56_4d05;
5455
const MSR_KVM_ASYNC_PF_INT: u32 = 0x4b56_4d06;
5556

5657
/// Taken from arch/x86/include/asm/msr-index.h
57-
const MSR_IA32_SPEC_CTRL: u32 = 0x0000_0048;
58+
/// Spectre mitigations control MSR
59+
pub const MSR_IA32_SPEC_CTRL: u32 = 0x0000_0048;
60+
/// Architecture capabilities MSR
61+
pub const MSR_IA32_ARCH_CAPABILITIES: u32 = 0x0000_010a;
62+
5863
const MSR_IA32_PRED_CMD: u32 = 0x0000_0049;
5964

65+
bitflags! {
66+
/// Feature flags enumerated in the IA32_ARCH_CAPABILITIES MSR.
67+
/// See https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/technical-documentation/cpuid-enumeration-and-architectural-msrs.html
68+
#[derive(Default)]
69+
#[repr(C)]
70+
pub struct ArchCapaMSRFlags: u64 {
71+
/// The processor is not susceptible to Rogue Data Cache Load (RDCL).
72+
const RDCL_NO = 1 << 0;
73+
/// The processor supports enhanced Indirect Branch Restriction Speculation (IBRS)
74+
const IBRS_ALL = 1 << 1;
75+
/// The processor supports RSB Alternate. Alternative branch predictors may be used by RET instructions
76+
/// when the RSB is empty. Software using retpoline may be affected by this behavior.
77+
const RSBA = 1 << 2;
78+
/// A value of 1 indicates the hypervisor need not flush the L1D on VM entry.
79+
const SKIP_L1DFL_VMENTRY = 1 << 3;
80+
/// Processor is not susceptible to Speculative Store Bypass (SSB).
81+
const SSB_NO = 1 << 4;
82+
/// Processor is not susceptible to Microarchitectural Data Sampling (MDS).
83+
const MDS_NO = 1 << 5;
84+
/// The processor is not susceptible to a machine check error due to modifying the size of a code page
85+
/// without TLB invalidation.
86+
const IF_PSCHANGE_MC_NO = 1 << 6;
87+
/// The processor supports RTM_DISABLE and TSX_CPUID_CLEAR.
88+
const TSX_CTRL = 1 << 7;
89+
/// Processor is not susceptible to Intel® Transactional Synchronization Extensions
90+
/// (Intel® TSX) Asynchronous Abort (TAA).
91+
const TAA_NO = 1 << 8;
92+
// Bit 9 is reserved
93+
/// Processor supports IA32_MISC_PACKAGE_CTRLS MSR.
94+
const MISC_PACKAGE_CTRLS = 1 << 10;
95+
/// Processor supports setting and reading IA32_MISC_PACKAGE_CTLS[0] (ENERGY_FILTERING_ENABLE) bit.
96+
const ENERGY_FILTERING_CTL = 1 << 11;
97+
/// The processor supports data operand independent timing mode.
98+
const DOITM = 1 << 12;
99+
/// The processor is not affected by either the Shared Buffers Data Read (SBDR) vulnerability or the
100+
/// Sideband Stale Data Propagator (SSDP).
101+
const SBDR_SSDP_NO = 1 << 13;
102+
/// The processor is not affected by the Fill Buffer Stale Data Propagator (FBSDP).
103+
const FBSDP_NO = 1 << 14;
104+
/// The processor is not affected by vulnerabilities involving the Primary Stale Data Propagator (PSDP).
105+
const PSDP_NO = 1 << 15;
106+
// Bit 16 is reserved
107+
/// The processor will overwrite fill buffer values as part of MD_CLEAR operations with the VERW instruction.
108+
/// On these processors, L1D_FLUSH does not overwrite fill buffer values.
109+
const FB_CLEAR = 1 << 17;
110+
/// The processor supports read and write to the IA32_MCU_OPT_CTRL MSR (MSR 123H) and to the FB_CLEAR_DIS bit
111+
/// in that MSR (bit position 3).
112+
const FB_CLEAR_CTRL = 1 << 18;
113+
/// A value of 1 indicates processor may have the RRSBA alternate prediction behavior,
114+
/// if not disabled by RRSBA_DIS_U or RRSBA_DIS_S.
115+
const RRSBA = 1 << 19;
116+
/// A value of 1 indicates BHI_NO branch prediction behavior,
117+
/// regardless of the value of IA32_SPEC_CTRL[BHI_DIS_S] MSR bit.
118+
const BHI_NO = 1 << 20;
119+
// Bits 21:22 are reserved
120+
/// If set, the IA32_OVERCLOCKING STATUS MSR exists.
121+
const OVERCLOCKING_STATUS = 1 << 23;
122+
// Bits 24:63 are reserved
123+
}
124+
}
125+
60126
// Creates a MsrRange of one msr given as argument.
61127
macro_rules! SINGLE_MSR {
62128
($msr:expr) => {
@@ -188,8 +254,8 @@ pub fn msr_should_serialize(index: u32) -> bool {
188254
ALLOWED_MSR_RANGES.iter().any(|range| range.contains(index))
189255
}
190256

191-
// Creates and populates required MSR entries for booting Linux on X86_64.
192-
fn create_boot_msr_entries() -> Vec<kvm_msr_entry> {
257+
/// Creates and populates required MSR entries for booting Linux on X86_64.
258+
pub fn create_boot_msr_entries() -> Vec<kvm_msr_entry> {
193259
let msr_entry_default = |msr| kvm_msr_entry {
194260
index: msr,
195261
data: 0x0,
@@ -221,9 +287,8 @@ fn create_boot_msr_entries() -> Vec<kvm_msr_entry> {
221287
/// # Arguments
222288
///
223289
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
224-
pub fn setup_msrs(vcpu: &VcpuFd) -> Result<()> {
225-
let entry_vec = create_boot_msr_entries();
226-
let msrs = Msrs::from_entries(&entry_vec).map_err(Error::FamError)?;
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)?;
227292
vcpu.set_msrs(&msrs)
228293
.map_err(Error::SetModelSpecificRegisters)
229294
.and_then(|msrs_written| {
@@ -271,7 +336,8 @@ mod tests {
271336
let kvm = Kvm::new().unwrap();
272337
let vm = kvm.create_vm().unwrap();
273338
let vcpu = vm.create_vcpu(0).unwrap();
274-
setup_msrs(&vcpu).unwrap();
339+
let msr_boot_entries = create_boot_msr_entries();
340+
set_msrs(&vcpu, &msr_boot_entries).unwrap();
275341

276342
// This test will check against the last MSR entry configured (the tenth one).
277343
// See create_msr_entries() for details.

src/cpuid/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ kvm-bindings = { version = ">=0.5.0", features = ["fam-wrappers"] }
1010
kvm-ioctls = ">=0.9.0"
1111

1212
utils = { path = "../utils"}
13+
arch = { path = "../arch" }

src/cpuid/src/cpu_leaf.rs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,9 @@ pub mod leaf_0x1 {
3737
// Virtual Machine Extensions
3838
pub const VMX_BITINDEX: u32 = 5;
3939
// 6 = SMX (Safer Mode Extensions)
40+
pub const SMX_BITINDEX: u32 = 6;
4041
// 7 = EIST (Enhanced Intel SpeedStep® technology)
42+
pub const EIST_BITINDEX: u32 = 7;
4143
// TM2 = Thermal Monitor 2
4244
pub const TM2_BITINDEX: u32 = 8;
4345
// CNXT_ID = L1 Context ID (L1 data cache can be set to adaptive/shared mode)
@@ -50,6 +52,7 @@ pub mod leaf_0x1 {
5052
// PDCM = Perfmon and Debug Capability
5153
pub const PDCM_BITINDEX: u32 = 15;
5254
// 18 = DCA Direct Cache Access (prefetch data from a memory mapped device)
55+
pub const DCA_BITINDEX: u32 = 18;
5356
pub const MOVBE_BITINDEX: u32 = 22;
5457
pub const TSC_DEADLINE_TIMER_BITINDEX: u32 = 24;
5558
pub const OSXSAVE_BITINDEX: u32 = 27;
@@ -59,11 +62,13 @@ pub mod leaf_0x1 {
5962

6063
pub mod edx {
6164
pub const PSN_BITINDEX: u32 = 18; // Processor Serial Number
65+
pub const SSE42_BITINDEX: u32 = 20; // SSE 4.2
6266
pub const DS_BITINDEX: u32 = 21; // Debug Store.
6367
pub const ACPI_BITINDEX: u32 = 22; // Thermal Monitor and Software Controlled Clock Facilities.
6468
pub const SS_BITINDEX: u32 = 27; // Self Snoop
6569
pub const HTT_BITINDEX: u32 = 28; // Max APIC IDs reserved field is valid
6670
pub const TM_BITINDEX: u32 = 29; // Thermal Monitor.
71+
pub const IA64_BITINDEX: u32 = 30; // IA64 processor emulating x86
6772
pub const PBE_BITINDEX: u32 = 31; // Pending Break Enable.
6873
}
6974
}
@@ -127,6 +132,7 @@ pub mod leaf_0x7 {
127132
// Intel® Resource Director Technology (Intel® RDT) Monitoring
128133
pub const RDT_M_BITINDEX: u32 = 12;
129134
// 13 = Deprecates FPU CS and FPU DS values if 1
135+
pub const FPU_CS_DS_DEPRECATE_BITINDEX: u32 = 13;
130136
// Memory Protection Extensions
131137
pub const MPX_BITINDEX: u32 = 14;
132138
// RDT = Intel® Resource Director Technology
@@ -140,9 +146,10 @@ pub mod leaf_0x7 {
140146
// 20 = SMAP (Supervisor-Mode Access Prevention)
141147
// AVX512IFMA = AVX-512 Integer Fused Multiply-Add Instructions
142148
pub const AVX512IFMA_BITINDEX: u32 = 21;
143-
// 21 = PCOMMIT intruction
144-
// 22 reserved
145-
// CLFLUSHOPT (flushing multiple cache lines in parallel within a single logical processor)
149+
// 22 = PCOMMIT intruction
150+
pub const PCOMMIT_BITINDEX: u32 = 22;
151+
// CLFLUSHOPT (flushing multiple cache lines in parallel within a single logical
152+
// processor)
146153
pub const CLFLUSHOPT_BITINDEX: u32 = 23;
147154
// CLWB = Cache Line Write Back
148155
pub const CLWB_BITINDEX: u32 = 24;

src/cpuid/src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,7 @@ use crate::common::*;
1919
pub mod bit_helper;
2020

2121
mod template;
22-
pub use crate::template::intel::c3;
23-
pub use crate::template::intel::t2;
22+
pub use crate::template::intel::{c3, t2, t2s};
2423

2524
mod cpu_leaf;
2625

src/cpuid/src/template/intel/mod.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@
55
pub mod c3;
66
/// Follows a T2 template in setting up the CPUID.
77
pub mod t2;
8+
/// Follows a T2 template for setting up the CPUID with additional MSRs
9+
/// that are speciffic to an Intel Skylake CPU.
10+
pub mod t2s;
811

912
use crate::common::{get_vendor_id_from_host, VENDOR_ID_INTEL};
1013
use crate::transformer::Error;

0 commit comments

Comments
 (0)