Skip to content

Commit 350772c

Browse files
committed
kernel: migrate CPUID feature detection to cpufeature crate
The kernel currently maintains CPU feature detection using hand-written CPUID leaf/register/bit checks. This duplicates CPUID definitions, requires updating multiple locations as new features are added, and is prone to inconsistencies. Replace the local CPUID feature machinery with the shared cpufeature crate, which is auto-generated from the X86-CPUID database and serves as a single source of truth for CPU feature definitions. Remove features.rs and the local Feature enum, implement CpuidBackend for Native, SNP, and TDP, and route feature queries through platform::{cpuid, cpuid_value, has_cpuid_feature}. Update call sites to use cpufeature leaf descriptors directly for SMEP, SMAP, CET, XSAVE, TLB, and other CPU features. Signed-off-by: tanish111 <tanishdesai37@gmail.com>
1 parent 8352549 commit 350772c

17 files changed

Lines changed: 152 additions & 272 deletions

File tree

Cargo.lock

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

Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,9 @@ virtio-drivers = { git = "https://github.com/rcore-os/virtio-drivers.git", rev =
103103
zerocopy = { version = "0.8.2", features = ["derive"] }
104104
zeroize = { version = "1.8.2", default-features = false }
105105

106+
#Github repos
107+
cpufeature = { git = "https://github.com/tanish111/cpufeature.git", rev = "4f86e2d062ab8e456566d00db64913caa2f53f33" }
108+
106109
# Verus repos
107110
verus_builtin = { version = "=0.0.0-2026-04-12-0118", default-features = false }
108111
verus_builtin_macros = { version = "=0.0.0-2026-04-12-0118", features = ["vpanic"], default-features = false }

kernel/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ doctest = true
1616
bootdefs.workspace = true
1717
bootimg.workspace = true
1818
cpuarch.workspace = true
19+
cpufeature.workspace = true
1920
libaproxy = { workspace = true, optional = true }
2021
elf.workspace = true
2122
syscall.workspace = true

kernel/src/cpu/control_regs.rs

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
// Author: Joerg Roedel <jroedel@suse.de>
66

77
use crate::address::{Address, PhysAddr};
8-
use crate::cpu::features::{Feature, cpu_has_feat};
8+
use crate::platform::has_cpuid_feature;
99
use core::arch::asm;
1010
use cpuarch::x86::CR0Flags;
1111
use cpuarch::x86::CR4Flags;
12+
use cpufeature::leaves::{
13+
CET_SS, X86_FEATURE_PGE, X86_FEATURE_SMAP, X86_FEATURE_SMEP, X86_FEATURE_UMIP,
14+
};
1215

1316
#[inline]
1417
pub fn cr0_init() {
@@ -33,25 +36,34 @@ pub fn cr4_init() {
3336
// All processors that are capable of virtualization will support global
3437
// page table entries, so there is no reason to support any processor that
3538
// does not enumerate PGE capability.
36-
assert!(cpu_has_feat(Feature::Pge), "CPU does not support PGE");
39+
assert!(
40+
has_cpuid_feature(&X86_FEATURE_PGE),
41+
"CPU does not support PGE"
42+
);
3743

3844
cr4.insert(CR4Flags::PGE); // Enable Global Pages
3945

4046
if !cfg!(feature = "nosmep") {
41-
assert!(cpu_has_feat(Feature::Smep), "CPU does not support SMEP");
47+
assert!(
48+
has_cpuid_feature(&X86_FEATURE_SMEP),
49+
"CPU does not support SMEP"
50+
);
4251
cr4.insert(CR4Flags::SMEP);
4352
}
4453

4554
if !cfg!(feature = "nosmap") {
46-
assert!(cpu_has_feat(Feature::Smap), "CPU does not support SMAP");
55+
assert!(
56+
has_cpuid_feature(&X86_FEATURE_SMAP),
57+
"CPU does not support SMAP"
58+
);
4759
cr4.insert(CR4Flags::SMAP);
4860
}
4961

50-
if cpu_has_feat(Feature::Umip) {
62+
if has_cpuid_feature(&X86_FEATURE_UMIP) {
5163
cr4.insert(CR4Flags::UMIP);
5264
}
5365

54-
if cpu_has_feat(Feature::CetSS) {
66+
if has_cpuid_feature(&CET_SS) {
5567
cr4.insert(CR4Flags::CET);
5668
}
5769

kernel/src/cpu/features.rs

Lines changed: 0 additions & 174 deletions
This file was deleted.

kernel/src/cpu/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ pub mod cpuid;
1010
pub mod cpuset;
1111
pub mod efer;
1212
pub mod extable;
13-
pub mod features;
1413
pub mod gdt;
1514
pub mod idt;
1615
pub mod ipi;

kernel/src/cpu/percpu.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66

77
extern crate alloc;
88

9-
use super::features::{Feature, cpu_has_feat};
109
use super::gdt::GDT;
1110
use super::ipi::IpiState;
1211
use super::isst::Isst;
@@ -40,6 +39,7 @@ use crate::mm::{
4039
SVSM_SHADOW_STACK_ISST_DF_BASE, SVSM_SHADOW_STACKS_INIT_TASK, SVSM_STACK_IST_DF_BASE,
4140
virt_to_phys,
4241
};
42+
use crate::platform::has_cpuid_feature;
4343
use crate::platform::{SVSM_PLATFORM, SvsmPlatform};
4444
use crate::requests::SvsmCaa;
4545
use crate::sev::ghcb::{GHCB, GhcbPage};
@@ -75,6 +75,7 @@ use core::sync::atomic::AtomicU64;
7575
use core::sync::atomic::AtomicUsize;
7676
use core::sync::atomic::Ordering;
7777
use cpuarch::vmsa::VMSA;
78+
use cpufeature::leaves::CET_SS;
7879

7980
// PERCPU areas virtual addresses into shared memory
8081
pub static PERCPU_AREAS: PerCpuAreas = PerCpuAreas::new();
@@ -837,14 +838,14 @@ impl PerCpu {
837838
// Reserve ranges and initialize allocator for temporary mappings
838839
self.initialize_vm_ranges()?;
839840

840-
if cpu_has_feat(Feature::CetSS) {
841+
if has_cpuid_feature(&CET_SS) {
841842
self.allocate_init_shadow_stack()?;
842843
}
843844

844845
// Allocate per-cpu context switch stack
845846
self.allocate_context_switch_stack()?;
846847

847-
if cpu_has_feat(Feature::CetSS) {
848+
if has_cpuid_feature(&CET_SS) {
848849
self.allocate_context_switch_shadow_stack()?;
849850
}
850851

@@ -854,7 +855,7 @@ impl PerCpu {
854855
// Setup TSS
855856
self.setup_tss();
856857

857-
if cpu_has_feat(Feature::CetSS) {
858+
if has_cpuid_feature(&CET_SS) {
858859
// Allocate ISST shadow stacks
859860
self.allocate_isst_shadow_stacks()?;
860861

@@ -869,7 +870,7 @@ impl PerCpu {
869870

870871
// Allocate hypercall pages if running on Hyper-V, unless this is the
871872
// BSP (where they will be allocated later).
872-
if self.shared.cpu_index() != 0 && cpu_has_feat(Feature::HyperV) {
873+
if self.shared.cpu_index() != 0 && hyperv::is_hyperv_host() {
873874
self.allocate_hypercall_pages()?;
874875
}
875876

kernel/src/cpu/sse.rs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,15 @@
55
// Author: Vasant Karasulli <vkarasulli@suse.de>
66

77
use crate::cpu::control_regs::{cr0_sse_enable, cr4_osfxsr_enable, cr4_xsave_enable};
8-
use crate::platform::cpuid;
8+
use crate::platform::{cpuid, has_cpuid_feature};
99
use core::arch::asm;
1010
use core::arch::x86_64::{_xgetbv, _xsetbv};
1111
use core::sync::atomic::{AtomicU64, Ordering};
12-
13-
use super::features::{Feature, cpu_has_feat};
14-
12+
use cpufeature::CpuidFeature;
13+
use cpufeature::leaves::{
14+
X86_FEATURE_XMM, X86_FEATURE_XSAVE, X86_FEATURE_XSAVEOPT, XCR0_AVX, XCR0_SSE, XCR0_X87,
15+
XSAVE_SZ,
16+
};
1517
const XCR0_X87_ENABLE: u64 = 0x1;
1618
const XCR0_SSE_ENABLE: u64 = 0x2;
1719
const XCR0_YMM_ENABLE: u64 = 0x4;
@@ -22,7 +24,7 @@ pub const XSAVE_LEGACY_SIZE: u32 = 0x240;
2224
static SVSM_XCR0: AtomicU64 = AtomicU64::new(XCR0_X87_ENABLE | XCR0_SSE_ENABLE);
2325

2426
fn legacy_sse_enable() {
25-
if cpu_has_feat(Feature::Sse1) {
27+
if has_cpuid_feature(&X86_FEATURE_XMM) {
2628
cr4_osfxsr_enable();
2729
cr0_sse_enable();
2830
} else {
@@ -40,10 +42,10 @@ fn xcr0_set() {
4042
}
4143

4244
fn xsave_enable() {
43-
if cpu_has_feat(Feature::Xsave) && cpu_has_feat(Feature::XsaveOpt) {
44-
if cpu_has_feat(Feature::Xcr0X87)
45-
&& cpu_has_feat(Feature::Xcr0Sse)
46-
&& cpu_has_feat(Feature::Xcr0Avx)
45+
if has_cpuid_feature(&X86_FEATURE_XSAVE) && has_cpuid_feature(&X86_FEATURE_XSAVEOPT) {
46+
if has_cpuid_feature(&XCR0_X87)
47+
&& has_cpuid_feature(&XCR0_SSE)
48+
&& has_cpuid_feature(&XCR0_AVX)
4749
{
4850
SVSM_XCR0.fetch_or(XCR0_YMM_ENABLE, Ordering::Relaxed);
4951
}
@@ -75,7 +77,11 @@ pub fn xsave_area_size() -> u32 {
7577
if xcr0 & (1u64 << bit) == 0 {
7678
continue;
7779
}
78-
let Some(result) = cpuid(0xd, bit) else {
80+
let feature = CpuidFeature {
81+
subleaf: bit,
82+
..XSAVE_SZ
83+
};
84+
let Some(result) = cpuid(&feature) else {
7985
log::warn!("FP feature {bit:#x} enabled but not present in CPUID");
8086
continue;
8187
};

0 commit comments

Comments
 (0)