mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
virtio-devices: balloon: Enable use with confidential VMs
Following the pattern used by the existing virtio devices make the balloon device work with confidential VMs (e.g. SEV-SNP). This requires advertising the VIRTIO_F_ACCESS_PLATFORM feature. Do not expose this to the user as a controllable option and instead only enable in on the "force" case. Signed-off-by: Rob Bradford <rbradford@meta.com>
This commit is contained in:
@@ -49,6 +49,7 @@ fuzz_target!(|bytes: &[u8]| -> Corpus {
|
|||||||
BALLOON_SIZE,
|
BALLOON_SIZE,
|
||||||
true,
|
true,
|
||||||
true,
|
true,
|
||||||
|
false,
|
||||||
SeccompAction::Allow,
|
SeccompAction::Allow,
|
||||||
EventFd::new(EFD_NONBLOCK).unwrap(),
|
EventFd::new(EFD_NONBLOCK).unwrap(),
|
||||||
None,
|
None,
|
||||||
|
|||||||
@@ -34,14 +34,15 @@ use vm_memory::{
|
|||||||
GuestMemoryError, GuestMemoryRegion,
|
GuestMemoryError, GuestMemoryRegion,
|
||||||
};
|
};
|
||||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||||
|
use vm_virtio::{AccessPlatform, Translatable};
|
||||||
use vmm_sys_util::eventfd::EventFd;
|
use vmm_sys_util::eventfd::EventFd;
|
||||||
|
|
||||||
use crate::seccomp_filters::Thread;
|
use crate::seccomp_filters::Thread;
|
||||||
use crate::thread_helper::spawn_virtio_thread;
|
use crate::thread_helper::spawn_virtio_thread;
|
||||||
use crate::{
|
use crate::{
|
||||||
ActivateResult, EPOLL_HELPER_EVENT_LAST, EpollHelper, EpollHelperError, EpollHelperHandler,
|
ActivateResult, EPOLL_HELPER_EVENT_LAST, EpollHelper, EpollHelperError, EpollHelperHandler,
|
||||||
GuestMemoryMmap, VIRTIO_F_VERSION_1, VirtioCommon, VirtioDevice, VirtioDeviceType,
|
GuestMemoryMmap, VIRTIO_F_ACCESS_PLATFORM, VIRTIO_F_VERSION_1, VirtioCommon, VirtioDevice,
|
||||||
VirtioInterrupt, VirtioInterruptType,
|
VirtioDeviceType, VirtioInterrupt, VirtioInterruptType,
|
||||||
};
|
};
|
||||||
|
|
||||||
const QUEUE_SIZE: u16 = 128;
|
const QUEUE_SIZE: u16 = 128;
|
||||||
@@ -160,6 +161,7 @@ struct BalloonEpollHandler {
|
|||||||
kill_evt: EventFd,
|
kill_evt: EventFd,
|
||||||
pause_evt: EventFd,
|
pause_evt: EventFd,
|
||||||
pbp: Option<PartiallyBalloonedPage>,
|
pbp: Option<PartiallyBalloonedPage>,
|
||||||
|
access_platform: Option<Arc<dyn AccessPlatform>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BalloonEpollHandler {
|
impl BalloonEpollHandler {
|
||||||
@@ -277,7 +279,12 @@ impl BalloonEpollHandler {
|
|||||||
|
|
||||||
let mut offset = 0u64;
|
let mut offset = 0u64;
|
||||||
while offset < desc.len() as u64 {
|
while offset < desc.len() as u64 {
|
||||||
let addr = desc.addr().checked_add(offset).unwrap();
|
let addr = desc
|
||||||
|
.addr()
|
||||||
|
.checked_add(offset)
|
||||||
|
.unwrap()
|
||||||
|
.translate_gva(self.access_platform.as_deref(), data_chunk_size)
|
||||||
|
.map_err(|e| Error::GuestMemory(GuestMemoryError::IOError(e)))?;
|
||||||
let pfn: u32 = desc_chain
|
let pfn: u32 = desc_chain
|
||||||
.memory()
|
.memory()
|
||||||
.read_obj(addr)
|
.read_obj(addr)
|
||||||
@@ -324,7 +331,11 @@ impl BalloonEpollHandler {
|
|||||||
let mut descs_len = 0;
|
let mut descs_len = 0;
|
||||||
while let Some(desc) = desc_chain.next() {
|
while let Some(desc) = desc_chain.next() {
|
||||||
descs_len += desc.len();
|
descs_len += desc.len();
|
||||||
Self::release_memory_range(desc_chain.memory(), desc.addr(), desc.len() as usize)?;
|
let addr = desc
|
||||||
|
.addr()
|
||||||
|
.translate_gva(self.access_platform.as_deref(), desc.len() as usize)
|
||||||
|
.map_err(|e| Error::GuestMemory(GuestMemoryError::IOError(e)))?;
|
||||||
|
Self::release_memory_range(desc_chain.memory(), addr, desc.len() as usize)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.queues[queue_index]
|
self.queues[queue_index]
|
||||||
@@ -437,11 +448,13 @@ pub struct Balloon {
|
|||||||
|
|
||||||
impl Balloon {
|
impl Balloon {
|
||||||
// Create a new virtio-balloon.
|
// Create a new virtio-balloon.
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
id: String,
|
id: String,
|
||||||
size: u64,
|
size: u64,
|
||||||
deflate_on_oom: bool,
|
deflate_on_oom: bool,
|
||||||
free_page_reporting: bool,
|
free_page_reporting: bool,
|
||||||
|
access_platform_enabled: bool,
|
||||||
seccomp_action: SeccompAction,
|
seccomp_action: SeccompAction,
|
||||||
exit_evt: EventFd,
|
exit_evt: EventFd,
|
||||||
state: Option<BalloonState>,
|
state: Option<BalloonState>,
|
||||||
@@ -464,6 +477,9 @@ impl Balloon {
|
|||||||
if free_page_reporting {
|
if free_page_reporting {
|
||||||
avail_features |= 1u64 << VIRTIO_BALLOON_F_REPORTING;
|
avail_features |= 1u64 << VIRTIO_BALLOON_F_REPORTING;
|
||||||
}
|
}
|
||||||
|
if access_platform_enabled {
|
||||||
|
avail_features |= 1u64 << VIRTIO_F_ACCESS_PLATFORM;
|
||||||
|
}
|
||||||
|
|
||||||
let config = VirtioBalloonConfig {
|
let config = VirtioBalloonConfig {
|
||||||
num_pages: (size >> VIRTIO_BALLOON_PFN_SHIFT) as u32,
|
num_pages: (size >> VIRTIO_BALLOON_PFN_SHIFT) as u32,
|
||||||
@@ -628,6 +644,7 @@ impl VirtioDevice for Balloon {
|
|||||||
kill_evt,
|
kill_evt,
|
||||||
pause_evt,
|
pause_evt,
|
||||||
pbp: None,
|
pbp: None,
|
||||||
|
access_platform: self.common.access_platform(),
|
||||||
};
|
};
|
||||||
|
|
||||||
let paused = self.common.paused.clone();
|
let paused = self.common.paused.clone();
|
||||||
@@ -648,6 +665,14 @@ impl VirtioDevice for Balloon {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn set_access_platform(&mut self, access_platform: Arc<dyn AccessPlatform>) {
|
||||||
|
self.common.set_access_platform(access_platform);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn access_platform(&self) -> Option<Arc<dyn AccessPlatform>> {
|
||||||
|
self.common.access_platform()
|
||||||
|
}
|
||||||
|
|
||||||
fn reset(&mut self) -> Option<Arc<dyn VirtioInterrupt>> {
|
fn reset(&mut self) -> Option<Arc<dyn VirtioInterrupt>> {
|
||||||
let result = self.common.reset();
|
let result = self.common.reset();
|
||||||
event!("virtio-device", "reset", "id", &self.id);
|
event!("virtio-device", "reset", "id", &self.id);
|
||||||
|
|||||||
@@ -3704,6 +3704,7 @@ impl DeviceManager {
|
|||||||
balloon_config.size,
|
balloon_config.size,
|
||||||
balloon_config.deflate_on_oom,
|
balloon_config.deflate_on_oom,
|
||||||
balloon_config.free_page_reporting,
|
balloon_config.free_page_reporting,
|
||||||
|
self.force_access_platform,
|
||||||
self.seccomp_action.clone(),
|
self.seccomp_action.clone(),
|
||||||
self.exit_evt
|
self.exit_evt
|
||||||
.try_clone()
|
.try_clone()
|
||||||
|
|||||||
Reference in New Issue
Block a user