Skip to content

Commit 070dfc7

Browse files
committed
vmm: fix riscv64 non-TEE memory region setup
In non-x86 builds that don't use TEE features, vstate.rs used cfg!() to distinguish between TEE and non-TEE memory setup paths. cfg!() only evaluates to a compile-time constant; code in both branches still participates in compilation and type checking. As a result, normal riscv64 builds still type-check guest_memfd and memory attribute code, which leads to build failures. Refactor the memory-region setup into cfg-gated helpers so non-TEE builds do not compile TEE-only memory setup code, and reject unsupported TEE+architecture combinations during VM setup instead of during memory initialization. Verify with: cargo check -p vmm --target riscv64gc-unknown-linux-gnu Signed-off-by: Zewei Yang <yangzewei@loongson.cn>
1 parent 788cf91 commit 070dfc7

2 files changed

Lines changed: 130 additions & 79 deletions

File tree

src/vmm/src/builder.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1552,13 +1552,32 @@ pub(crate) fn setup_vm(
15521552
.map_err(StartMicrovmError::Internal)?;
15531553
Ok(vm)
15541554
}
1555+
1556+
#[cfg(all(feature = "tee", target_arch = "x86_64"))]
1557+
fn validate_tee_config(tee: Tee) -> std::result::Result<(), StartMicrovmError> {
1558+
match tee {
1559+
#[cfg(feature = "amd-sev")]
1560+
Tee::Snp => Ok(()),
1561+
#[cfg(feature = "tdx")]
1562+
Tee::Tdx => Ok(()),
1563+
_ => Err(StartMicrovmError::InvalidTee),
1564+
}
1565+
}
1566+
1567+
#[cfg(all(feature = "tee", not(target_arch = "x86_64")))]
1568+
fn validate_tee_config(_tee: Tee) -> std::result::Result<(), StartMicrovmError> {
1569+
Err(StartMicrovmError::InvalidTee)
1570+
}
1571+
15551572
#[cfg(all(target_os = "linux", feature = "tee"))]
15561573
pub(crate) fn setup_vm(
15571574
kvm: &KvmContext,
15581575
guest_memory: &GuestMemoryMmap,
15591576
resources: &super::resources::VmResources,
15601577
#[cfg(feature = "tdx")] _sender: Sender<WorkerMessage>,
15611578
) -> std::result::Result<Vm, StartMicrovmError> {
1579+
validate_tee_config(resources.tee_config().tee)?;
1580+
15621581
let mut vm = Vm::new(
15631582
kvm.fd(),
15641583
resources.tee_config(),

src/vmm/src/linux/vstate.rs

Lines changed: 111 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -42,21 +42,22 @@ use crate::resources::TeeConfig;
4242
use crate::vmm_config::machine_config::CpuFeaturesTemplate;
4343
#[cfg(target_arch = "x86_64")]
4444
use cpuid::{c3, filter_cpuid, t2, VmSpec};
45+
#[cfg(not(feature = "tee"))]
46+
use kvm_bindings::kvm_userspace_memory_region;
4547
#[cfg(target_arch = "x86_64")]
4648
use kvm_bindings::{
4749
kvm_clock_data, kvm_debugregs, kvm_irqchip, kvm_lapic_state, kvm_mp_state, kvm_pit_state2,
4850
kvm_regs, kvm_sregs, kvm_vcpu_events, kvm_xcrs, kvm_xsave, CpuId, MsrList, Msrs,
4951
KVM_CLOCK_TSC_STABLE, KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE,
5052
KVM_MAX_CPUID_ENTRIES,
5153
};
52-
use kvm_bindings::{
53-
kvm_create_guest_memfd, kvm_userspace_memory_region, kvm_userspace_memory_region2,
54-
KVM_API_VERSION, KVM_MEM_GUEST_MEMFD, KVM_SYSTEM_EVENT_RESET, KVM_SYSTEM_EVENT_SHUTDOWN,
55-
};
54+
#[cfg(all(feature = "tee", target_arch = "x86_64"))]
55+
use kvm_bindings::{kvm_create_guest_memfd, kvm_userspace_memory_region2, KVM_MEM_GUEST_MEMFD};
5656
#[cfg(feature = "tee")]
5757
use kvm_bindings::{kvm_enable_cap, KVM_CAP_EXIT_HYPERCALL, KVM_MEMORY_EXIT_FLAG_PRIVATE};
58-
#[cfg(not(target_arch = "riscv64"))]
58+
#[cfg(all(feature = "tee", target_arch = "x86_64"))]
5959
use kvm_bindings::{kvm_memory_attributes, KVM_MEMORY_ATTRIBUTE_PRIVATE};
60+
use kvm_bindings::{KVM_API_VERSION, KVM_SYSTEM_EVENT_RESET, KVM_SYSTEM_EVENT_SHUTDOWN};
6061
use kvm_ioctls::{Cap::*, *};
6162
use utils::eventfd::EventFd;
6263
use utils::signal::{register_signal_handler, sigrtmin, Killable};
@@ -661,90 +662,121 @@ impl Vm {
661662
None
662663
}
663664

664-
#[allow(unused_mut)]
665-
fn memory_region_set(
665+
// GuestMemfd is generally intended for either of two purposes:
666+
// * sharing the memory with out-of-process components, and conversely,
667+
// * hiding the memory completely from the VMM process (Confidential Computing).
668+
//
669+
// We only use it for the second use case currently, so don't even try to use it
670+
// outside of TEE builds. Software-protected VMs are only available on x86_64 and
671+
// are marked with strongly-worded warnings about them being for development only,
672+
// as of late 2025. Also, on other architectures like aarch64, guest_memfd in
673+
// general is unstable for now, so don't try to use it without a reason.
674+
675+
#[cfg(not(feature = "tee"))]
676+
fn create_guest_physical_memory_slot(
666677
&mut self,
667-
guest_mem: &GuestMemoryMmap,
678+
host_addr: u64,
679+
start: u64,
668680
region: &GuestRegionMmap,
669681
) -> Result<()> {
670-
let host_addr = guest_mem.get_host_address(region.start_addr()).unwrap();
671-
let start = region.start_addr().raw_value();
672-
let end = start + region.len();
682+
let memory_region = kvm_userspace_memory_region {
683+
slot: self.next_mem_slot,
684+
guest_phys_addr: start,
685+
memory_size: region.len(),
686+
userspace_addr: host_addr,
687+
flags: 0,
688+
};
673689

674-
// GuestMemfd is generally intended for either of two purposes:
675-
// * sharing the memory with out-of-process components, and conversely,
676-
// * hiding the memory completely from the VMM process (Confidential Computing).
677-
//
678-
// We only use it for the second use case currently, so don't even try to use it
679-
// outside of TEE builds. Software-protected VMs are only available on x86_64 and
680-
// are marked with strongly-worded warnings about them being for development only,
681-
// as of late 2025. Also, on other architectures like aarch64, guest_memfd in
682-
// general is unstable for now, so don't try to use it without a reason.
683-
684-
if cfg!(not(feature = "tee")) {
685-
let memory_region = kvm_userspace_memory_region {
686-
slot: self.next_mem_slot,
687-
guest_phys_addr: start,
688-
memory_size: region.len(),
689-
userspace_addr: host_addr as u64,
690-
flags: 0,
691-
};
690+
// Safe because we mapped the memory region and ensured regions do not overlap.
691+
unsafe {
692+
self.fd
693+
.set_user_memory_region(memory_region)
694+
.map_err(Error::SetUserMemoryRegion)?;
695+
};
692696

693-
// Safe because we mapped the memory region, we made sure that the regions
694-
// are not overlapping.
695-
unsafe {
696-
self.fd
697-
.set_user_memory_region(memory_region)
698-
.map_err(Error::SetUserMemoryRegion)?;
699-
};
700-
} else {
701-
if !self.fd.check_extension(GuestMemfd) {
702-
return Err(Error::KvmCap(GuestMemfd));
703-
}
697+
Ok(())
698+
}
704699

705-
// Create a guest_memfd and set the region.
706-
let guest_memfd = self
707-
.fd
708-
.create_guest_memfd(kvm_create_guest_memfd {
709-
size: region.size() as u64,
710-
flags: 0,
711-
reserved: [0; 6],
712-
})
713-
.map_err(Error::CreateGuestMemfd)?;
714-
715-
let memory_region = kvm_userspace_memory_region2 {
716-
slot: self.next_mem_slot,
717-
flags: KVM_MEM_GUEST_MEMFD,
718-
guest_phys_addr: start,
719-
memory_size: region.len(),
720-
userspace_addr: host_addr as u64,
721-
guest_memfd_offset: 0,
722-
guest_memfd: guest_memfd as u32,
723-
pad1: 0,
724-
pad2: [0; 14],
725-
};
726-
727-
// Safe because we mapped the memory region, we made sure that the regions
728-
// are not overlapping.
729-
unsafe {
730-
self.fd
731-
.set_user_memory_region2(memory_region)
732-
.map_err(Error::SetUserMemoryRegion)?;
733-
};
734-
735-
let attr = kvm_memory_attributes {
736-
address: start,
737-
size: region.len(),
738-
attributes: KVM_MEMORY_ATTRIBUTE_PRIVATE as u64,
700+
#[cfg(all(feature = "tee", target_arch = "x86_64"))]
701+
fn create_guest_physical_memory_slot(
702+
&mut self,
703+
host_addr: u64,
704+
start: u64,
705+
region: &GuestRegionMmap,
706+
) -> Result<()> {
707+
let end = start + region.len();
708+
709+
if !self.fd.check_extension(GuestMemfd) {
710+
return Err(Error::KvmCap(GuestMemfd));
711+
}
712+
713+
// GuestMemfd is only used for confidential-memory setups in TEE builds.
714+
let guest_memfd = self
715+
.fd
716+
.create_guest_memfd(kvm_create_guest_memfd {
717+
size: region.size() as u64,
739718
flags: 0,
740-
};
719+
reserved: [0; 6],
720+
})
721+
.map_err(Error::CreateGuestMemfd)?;
722+
723+
let memory_region = kvm_userspace_memory_region2 {
724+
slot: self.next_mem_slot,
725+
flags: KVM_MEM_GUEST_MEMFD,
726+
guest_phys_addr: start,
727+
memory_size: region.len(),
728+
userspace_addr: host_addr,
729+
guest_memfd_offset: 0,
730+
guest_memfd: guest_memfd as u32,
731+
pad1: 0,
732+
pad2: [0; 14],
733+
};
741734

735+
// Safe because we mapped the memory region and ensured regions do not overlap.
736+
unsafe {
742737
self.fd
743-
.set_memory_attributes(attr)
744-
.map_err(Error::SetMemoryAttributes)?;
738+
.set_user_memory_region2(memory_region)
739+
.map_err(Error::SetUserMemoryRegion)?;
740+
};
745741

746-
self.guest_memfds.push((Range { start, end }, guest_memfd));
747-
}
742+
let attr = kvm_memory_attributes {
743+
address: start,
744+
size: region.len(),
745+
attributes: KVM_MEMORY_ATTRIBUTE_PRIVATE as u64,
746+
flags: 0,
747+
};
748+
749+
self.fd
750+
.set_memory_attributes(attr)
751+
.map_err(Error::SetMemoryAttributes)?;
752+
753+
self.guest_memfds.push((Range { start, end }, guest_memfd));
754+
755+
Ok(())
756+
}
757+
758+
#[cfg(all(feature = "tee", not(target_arch = "x86_64")))]
759+
fn create_guest_physical_memory_slot(
760+
&mut self,
761+
_host_addr: u64,
762+
_start: u64,
763+
_region: &GuestRegionMmap,
764+
) -> Result<()> {
765+
// TEE support should be rejected during VM setup on non-x86_64 targets.
766+
// Do not silently fall back to the non-TEE path here, because that would
767+
// ignore an invalid TEE configuration and create a normal VM instead.
768+
Err(Error::InvalidTee)
769+
}
770+
771+
fn memory_region_set(
772+
&mut self,
773+
guest_mem: &GuestMemoryMmap,
774+
region: &GuestRegionMmap,
775+
) -> Result<()> {
776+
let host_addr = guest_mem.get_host_address(region.start_addr()).unwrap() as u64;
777+
let start = region.start_addr().raw_value();
778+
779+
self.create_guest_physical_memory_slot(host_addr, start, region)?;
748780

749781
self.next_mem_slot += 1;
750782

0 commit comments

Comments
 (0)