virtio-devices: add VIRTIO_F_ACCESS_PLATFORM to watchdog and iommu

A confidential guest (e.g. SEV-SNP) requires every virtio device to
advertise VIRTIO_F_ACCESS_PLATFORM so the guest driver routes DMA
through the platform's bounce-buffer path; the driver refuses a device
that does not offer it.

Add VIRTIO_F_ACCESS_PLATFORM support to virtio-{watchdog,iommu} which
are exercised as part of the CVM integration tests.

Assisted-by: Claude:Opus-4.8
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
This commit is contained in:
Ruben Hakobyan
2026-06-02 17:10:28 -07:00
committed by Rob Bradford
parent 2b71ffd48e
commit 9e6c817192
5 changed files with 19 additions and 4 deletions

View File

@@ -67,6 +67,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
EventFd::new(EFD_NONBLOCK).unwrap(), EventFd::new(EFD_NONBLOCK).unwrap(),
((MEM_SIZE - IOVA_SPACE_SIZE) as u64, (MEM_SIZE - 1) as u64), ((MEM_SIZE - IOVA_SPACE_SIZE) as u64, (MEM_SIZE - 1) as u64),
64, 64,
false,
None, None,
) )
.unwrap(); .unwrap();

View File

@@ -37,6 +37,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
let mut watchdog = virtio_devices::Watchdog::new( let mut watchdog = virtio_devices::Watchdog::new(
"fuzzer_watchdog".to_owned(), "fuzzer_watchdog".to_owned(),
false,
EventFd::new(EFD_NONBLOCK).unwrap(), EventFd::new(EFD_NONBLOCK).unwrap(),
SeccompAction::Allow, SeccompAction::Allow,
EventFd::new(EFD_NONBLOCK).unwrap(), EventFd::new(EFD_NONBLOCK).unwrap(),

View File

@@ -27,7 +27,8 @@ use vmm_sys_util::eventfd::EventFd;
use super::{ use super::{
ActivateResult, EPOLL_HELPER_EVENT_LAST, EpollHelper, EpollHelperError, EpollHelperHandler, ActivateResult, EPOLL_HELPER_EVENT_LAST, EpollHelper, EpollHelperError, EpollHelperHandler,
Error as DeviceError, VIRTIO_F_VERSION_1, VirtioCommon, VirtioDevice, VirtioDeviceType, Error as DeviceError, VIRTIO_F_ACCESS_PLATFORM, VIRTIO_F_VERSION_1, VirtioCommon, VirtioDevice,
VirtioDeviceType,
}; };
use crate::seccomp_filters::Thread; use crate::seccomp_filters::Thread;
use crate::{DmaRemapping, GuestMemoryMmap, VirtioInterrupt, VirtioInterruptType}; use crate::{DmaRemapping, GuestMemoryMmap, VirtioInterrupt, VirtioInterruptType};
@@ -1117,6 +1118,7 @@ impl Iommu {
exit_evt: EventFd, exit_evt: EventFd,
msi_iova_space: (u64, u64), msi_iova_space: (u64, u64),
address_width_bits: u8, address_width_bits: u8,
access_platform_enabled: bool,
state: Option<IommuState>, state: Option<IommuState>,
) -> io::Result<(Self, Arc<IommuMapping>)> { ) -> io::Result<(Self, Arc<IommuMapping>)> {
let (mut avail_features, acked_features, endpoints, domains, paused) = let (mut avail_features, acked_features, endpoints, domains, paused) =
@@ -1165,6 +1167,10 @@ impl Iommu {
None None
}; };
if access_platform_enabled {
avail_features |= 1u64 << VIRTIO_F_ACCESS_PLATFORM;
}
let mapping = Arc::new(IommuMapping { let mapping = Arc::new(IommuMapping {
endpoints: Arc::new(RwLock::new(endpoints)), endpoints: Arc::new(RwLock::new(endpoints)),
domains: Arc::new(RwLock::new(domains)), domains: Arc::new(RwLock::new(domains)),

View File

@@ -27,8 +27,8 @@ use vmm_sys_util::eventfd::EventFd;
use super::{ use super::{
ActivateError, ActivateResult, EPOLL_HELPER_EVENT_LAST, EpollHelper, EpollHelperError, ActivateError, ActivateResult, EPOLL_HELPER_EVENT_LAST, EpollHelper, EpollHelperError,
EpollHelperHandler, Error as DeviceError, VIRTIO_F_VERSION_1, VirtioCommon, VirtioDevice, EpollHelperHandler, Error as DeviceError, VIRTIO_F_ACCESS_PLATFORM, VIRTIO_F_VERSION_1,
VirtioDeviceType, VirtioCommon, VirtioDevice, VirtioDeviceType,
}; };
use crate::seccomp_filters::Thread; use crate::seccomp_filters::Thread;
use crate::{GuestMemoryMmap, VirtioInterrupt, VirtioInterruptType}; use crate::{GuestMemoryMmap, VirtioInterrupt, VirtioInterruptType};
@@ -208,6 +208,7 @@ impl Watchdog {
/// Create a new virtio watchdog device that will reboot VM if the guest hangs /// Create a new virtio watchdog device that will reboot VM if the guest hangs
pub fn new( pub fn new(
id: String, id: String,
access_platform_enabled: bool,
reset_evt: EventFd, reset_evt: EventFd,
seccomp_action: SeccompAction, seccomp_action: SeccompAction,
exit_evt: EventFd, exit_evt: EventFd,
@@ -226,7 +227,11 @@ impl Watchdog {
(state.avail_features, state.acked_features, true) (state.avail_features, state.acked_features, true)
} else { } else {
(1u64 << VIRTIO_F_VERSION_1, 0, false) let mut avail_features = 1u64 << VIRTIO_F_VERSION_1;
if access_platform_enabled {
avail_features |= 1u64 << VIRTIO_F_ACCESS_PLATFORM;
}
(avail_features, 0, false)
}; };
let timer_fd = timerfd_create().map_err(|e| { let timer_fd = timerfd_create().map_err(|e| {

View File

@@ -1673,6 +1673,7 @@ impl DeviceManager {
.map_err(DeviceManagerError::EventFd)?, .map_err(DeviceManagerError::EventFd)?,
self.get_msi_iova_space(), self.get_msi_iova_space(),
iommu_address_width_bits, iommu_address_width_bits,
self.force_access_platform,
state_from_id(snapshot, iommu_id.as_str()) state_from_id(snapshot, iommu_id.as_str())
.map_err(DeviceManagerError::RestoreGetState)?, .map_err(DeviceManagerError::RestoreGetState)?,
) )
@@ -3728,6 +3729,7 @@ impl DeviceManager {
let virtio_watchdog_device = Arc::new(Mutex::new( let virtio_watchdog_device = Arc::new(Mutex::new(
virtio_devices::Watchdog::new( virtio_devices::Watchdog::new(
id.clone(), id.clone(),
self.force_access_platform,
self.reset_evt.try_clone().unwrap(), self.reset_evt.try_clone().unwrap(),
self.seccomp_action.clone(), self.seccomp_action.clone(),
self.exit_evt self.exit_evt