Skip to content

Commit 5ea493a

Browse files
committed
add "secret_free" parameter to /machine-config endpoint
This will later indicate to Firecracker that guest memory should be backed by guest_memfd. Signed-off-by: Patrick Roy <[email protected]>
1 parent 5f11246 commit 5ea493a

File tree

5 files changed

+82
-1
lines changed

5 files changed

+82
-1
lines changed

src/vmm/src/resources.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,14 @@ pub struct VmResources {
110110
}
111111

112112
impl VmResources {
113+
/// Whether this [`VmResources`] object contains any devices that require host kernel access
114+
/// into guest memory.
115+
pub fn has_any_io_devices(&self) -> bool {
116+
!self.block.devices.is_empty()
117+
|| self.vsock.get().is_some()
118+
|| self.net_builder.iter().next().is_some()
119+
}
120+
113121
/// Configures Vmm resources as described by the `config_json` param.
114122
pub fn from_json(
115123
config_json: &str,
@@ -217,6 +225,11 @@ impl VmResources {
217225
BalloonConfigError::IncompatibleWith("huge pages"),
218226
));
219227
}
228+
if self.machine_config.mem_config.secret_free {
229+
return Err(ResourcesError::BalloonDevice(
230+
BalloonConfigError::IncompatibleWith("secret freedom"),
231+
));
232+
}
220233
}
221234

222235
SharedDeviceType::Vsock(vsock) => {
@@ -256,12 +269,23 @@ impl VmResources {
256269
return Err(MachineConfigError::IncompatibleBalloonSize);
257270
}
258271

272+
#[cfg(target_arch = "x86_64")]
273+
if self.has_any_io_devices() {
274+
return Err(MachineConfigError::Incompatible("secret freedom", "I/O"));
275+
}
276+
259277
if self.balloon.get().is_some() && updated.huge_pages != HugePageConfig::None {
260278
return Err(MachineConfigError::Incompatible(
261279
"balloon device",
262280
"huge pages",
263281
));
264282
}
283+
if self.balloon.get().is_some() && updated.mem_config.secret_free {
284+
return Err(MachineConfigError::Incompatible(
285+
"balloon device",
286+
"secret freedom",
287+
));
288+
}
265289
self.machine_config = updated;
266290

267291
Ok(())
@@ -320,6 +344,10 @@ impl VmResources {
320344
return Err(BalloonConfigError::IncompatibleWith("huge pages"));
321345
}
322346

347+
if self.machine_config.mem_config.secret_free {
348+
return Err(BalloonConfigError::IncompatibleWith("secret freedom"));
349+
}
350+
323351
self.balloon.set(config)
324352
}
325353

@@ -343,6 +371,11 @@ impl VmResources {
343371
&mut self,
344372
block_device_config: BlockDeviceConfig,
345373
) -> Result<(), DriveError> {
374+
#[cfg(target_arch = "x86_64")]
375+
if self.machine_config.mem_config.secret_free {
376+
return Err(DriveError::NoSecretFreeIOOnX86);
377+
}
378+
346379
self.block.insert(block_device_config)
347380
}
348381

@@ -351,12 +384,22 @@ impl VmResources {
351384
&mut self,
352385
body: NetworkInterfaceConfig,
353386
) -> Result<(), NetworkInterfaceError> {
387+
#[cfg(target_arch = "x86_64")]
388+
if self.machine_config.mem_config.secret_free {
389+
return Err(NetworkInterfaceError::NoSecretFreeIOOnX86);
390+
}
391+
354392
let _ = self.net_builder.build(body)?;
355393
Ok(())
356394
}
357395

358396
/// Sets a vsock device to be attached when the VM starts.
359397
pub fn set_vsock_device(&mut self, config: VsockDeviceConfig) -> Result<(), VsockConfigError> {
398+
#[cfg(target_arch = "x86_64")]
399+
if self.machine_config.mem_config.secret_free {
400+
return Err(VsockConfigError::NoSecretFreeIOOnX86);
401+
}
402+
360403
self.vsock.insert(config)
361404
}
362405

src/vmm/src/vmm_config/drive.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ pub enum DriveError {
2424
DeviceUpdate(VmmError),
2525
/// A root block device already exists!
2626
RootBlockDeviceAlreadyAdded,
27+
/// A block device was added on x86 while secret freedom was enabled.
28+
#[cfg(target_arch = "x86_64")]
29+
NoSecretFreeIOOnX86,
2730
}
2831

2932
/// Use this structure to set up the Block Device before booting the kernel.

src/vmm/src/vmm_config/machine_config.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,11 @@ pub struct MemoryConfig {
9999
#[cfg(target_arch = "aarch64")]
100100
#[serde(default)]
101101
pub initial_swiotlb_size: usize,
102+
/// Whether guest_memfd should be used to back normal guest memory. If this is enabled
103+
/// and any devices are attached to the VM, then initial_swiotlb_size must be non-zero,
104+
/// as I/O into secret free memory is not possible.
105+
#[serde(default)]
106+
pub secret_free: bool,
102107
}
103108

104109
/// Struct used in PUT `/machine-config` API call.
@@ -301,6 +306,13 @@ impl MachineConfig {
301306
return Err(MachineConfigError::InvalidSwiotlbRegionSize);
302307
}
303308

309+
if mem_config.secret_free && page_config != HugePageConfig::None {
310+
return Err(MachineConfigError::Incompatible(
311+
"secret freedom",
312+
"huge pages",
313+
));
314+
}
315+
304316
let cpu_template = match update.cpu_template {
305317
None => self.cpu_template.clone(),
306318
Some(StaticCpuTemplate::None) => None,
@@ -325,7 +337,7 @@ impl MachineConfig {
325337
mod tests {
326338
use crate::cpu_config::templates::{CpuTemplateType, CustomCpuTemplate, StaticCpuTemplate};
327339
use crate::vmm_config::machine_config::{
328-
HugePageConfig, MachineConfig, MachineConfigError, MachineConfigUpdate,
340+
HugePageConfig, MachineConfig, MachineConfigError, MachineConfigUpdate, MemoryConfig,
329341
};
330342

331343
#[test]
@@ -379,6 +391,23 @@ mod tests {
379391
.unwrap();
380392
assert_eq!(updated.huge_pages, HugePageConfig::Hugetlbfs2M);
381393
assert_eq!(updated.mem_size_mib, 32);
394+
395+
let res = mconf.update(&MachineConfigUpdate {
396+
huge_pages: Some(HugePageConfig::Hugetlbfs2M),
397+
mem_config: Some(MemoryConfig {
398+
secret_free: true,
399+
..Default::default()
400+
}),
401+
..Default::default()
402+
});
403+
404+
assert_eq!(
405+
res,
406+
Err(MachineConfigError::Incompatible(
407+
"secret freedom",
408+
"huge pages"
409+
))
410+
);
382411
}
383412

384413
#[test]

src/vmm/src/vmm_config/net.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ pub enum NetworkInterfaceError {
7171
GuestMacAddressInUse(String),
7272
/// Cannot open/create the tap device: {0}
7373
OpenTap(#[from] TapError),
74+
/// A net device was added on x86 while secret freedom was enabled.
75+
#[cfg(target_arch = "x86_64")]
76+
NoSecretFreeIOOnX86,
7477
}
7578

7679
/// Builder for a list of network devices.

src/vmm/src/vmm_config/vsock.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ pub enum VsockConfigError {
1717
CreateVsockBackend(VsockUnixBackendError),
1818
/// Cannot create vsock device: {0}
1919
CreateVsockDevice(VsockError),
20+
/// A vsock device was added on x86 while secret freedom was enabled.
21+
#[cfg(target_arch = "x86_64")]
22+
NoSecretFreeIOOnX86,
2023
}
2124

2225
/// This struct represents the strongly typed equivalent of the json body

0 commit comments

Comments
 (0)