Skip to content

Commit 46e2c05

Browse files
committed
arm: describe swiotlb region in FDT
describe the swiotlb region as a restricted-mem node in the flattened device tree, and force all virtio devices to use it for their vrings and buffers by setting their `memory-region` property. Signed-off-by: Patrick Roy <[email protected]>
1 parent 7e2cdee commit 46e2c05

File tree

4 files changed

+53
-16
lines changed

4 files changed

+53
-16
lines changed

src/vmm/src/arch/aarch64/fdt.rs

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,19 +10,22 @@ use std::ffi::CString;
1010
use std::fmt::Debug;
1111

1212
use vm_fdt::{Error as VmFdtError, FdtWriter, FdtWriterNode};
13-
use vm_memory::GuestMemoryError;
13+
use vm_memory::{GuestMemoryError, GuestMemoryRegion};
1414

1515
use super::super::{DeviceType, InitrdConfig};
1616
use super::cache_info::{CacheEntry, read_cache_config};
1717
use super::gic::GICDevice;
1818
use crate::device_manager::mmio::MMIODeviceInfo;
1919
use crate::devices::acpi::vmgenid::{VMGENID_MEM_SIZE, VmGenId};
20-
use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap};
20+
use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap, GuestRegionMmap};
2121

2222
// This is a value for uniquely identifying the FDT node declaring the interrupt controller.
2323
const GIC_PHANDLE: u32 = 1;
2424
// This is a value for uniquely identifying the FDT node containing the clock definition.
2525
const CLOCK_PHANDLE: u32 = 2;
26+
/// Unique identifier for the /reserved-memory node describing the memory region the guest
27+
/// is allowed to use for swiotlb
28+
const IO_MEM_PHANDLE: u32 = 3;
2629
// You may be wondering why this big value?
2730
// This phandle is used to uniquely identify the FDT nodes containing cache information. Each cpu
2831
// can have a variable number of caches, some of these caches may be shared with other cpus.
@@ -57,6 +60,7 @@ pub enum FdtError {
5760
/// Creates the flattened device tree for this aarch64 microVM.
5861
pub fn create_fdt(
5962
guest_mem: &GuestMemoryMmap,
63+
swiotlb_region: Option<&GuestRegionMmap>,
6064
vcpu_mpidr: Vec<u64>,
6165
cmdline: CString,
6266
device_info: &HashMap<(DeviceType, String), MMIODeviceInfo>,
@@ -82,7 +86,7 @@ pub fn create_fdt(
8286
// containing description of the interrupt controller for this VM.
8387
fdt_writer.property_u32("interrupt-parent", GIC_PHANDLE)?;
8488
create_cpu_nodes(&mut fdt_writer, &vcpu_mpidr)?;
85-
create_memory_node(&mut fdt_writer, guest_mem)?;
89+
create_memory_node(&mut fdt_writer, guest_mem, swiotlb_region)?;
8690
create_chosen_node(&mut fdt_writer, cmdline, initrd)?;
8791
create_gic_node(&mut fdt_writer, gic_device)?;
8892
create_timer_node(&mut fdt_writer)?;
@@ -207,7 +211,11 @@ fn create_cpu_nodes(fdt: &mut FdtWriter, vcpu_mpidr: &[u64]) -> Result<(), FdtEr
207211
Ok(())
208212
}
209213

210-
fn create_memory_node(fdt: &mut FdtWriter, guest_mem: &GuestMemoryMmap) -> Result<(), FdtError> {
214+
fn create_memory_node(
215+
fdt: &mut FdtWriter,
216+
guest_mem: &GuestMemoryMmap,
217+
swiotlb_region: Option<&GuestRegionMmap>,
218+
) -> Result<(), FdtError> {
211219
// See https://github.com/torvalds/linux/blob/master/Documentation/devicetree/booting-without-of.txt#L960
212220
// for an explanation of this.
213221

@@ -219,9 +227,13 @@ fn create_memory_node(fdt: &mut FdtWriter, guest_mem: &GuestMemoryMmap) -> Resul
219227
// The reason we do this is that Linux does not allow remapping system memory. However, without
220228
// remap, kernel drivers cannot get virtual addresses to read data from device memory. Leaving
221229
// this memory region out allows Linux kernel modules to remap and thus read this region.
230+
//
231+
// The generic memory description must include the range that we later declare as a reserved
232+
// carve out.
222233
let mem_size = guest_mem.last_addr().raw_value()
223234
- super::layout::DRAM_MEM_START
224235
- super::layout::SYSTEM_MEM_SIZE
236+
+ swiotlb_region.map(|r| r.len()).unwrap_or(0)
225237
+ 1;
226238
let mem_reg_prop = &[
227239
super::layout::DRAM_MEM_START + super::layout::SYSTEM_MEM_SIZE,
@@ -232,6 +244,19 @@ fn create_memory_node(fdt: &mut FdtWriter, guest_mem: &GuestMemoryMmap) -> Resul
232244
fdt.property_array_u64("reg", mem_reg_prop)?;
233245
fdt.end_node(mem)?;
234246

247+
if let Some(region) = swiotlb_region {
248+
let rmem = fdt.begin_node("reserved-memory")?;
249+
fdt.property_u32("#address-cells", ADDRESS_CELLS)?;
250+
fdt.property_u32("#size-cells", SIZE_CELLS)?;
251+
fdt.property_null("ranges")?;
252+
let dma = fdt.begin_node("bouncy_boi")?;
253+
fdt.property_string("compatible", "restricted-dma-pool")?;
254+
fdt.property_phandle(IO_MEM_PHANDLE)?;
255+
fdt.property_array_u64("reg", &[region.start_addr().0, region.len()])?;
256+
fdt.end_node(dma)?;
257+
fdt.end_node(rmem)?;
258+
}
259+
235260
Ok(())
236261
}
237262

@@ -357,6 +382,9 @@ fn create_virtio_node(fdt: &mut FdtWriter, dev_info: &MMIODeviceInfo) -> Result<
357382

358383
fdt.property_string("compatible", "virtio,mmio")?;
359384
fdt.property_array_u64("reg", &[dev_info.addr, dev_info.len])?;
385+
// Force all virtio device to place their vrings and buffer into the dedicated I/O memory region
386+
// that is backed by traditional memory (e.g. not secret-free).
387+
fdt.property_u32("memory-region", IO_MEM_PHANDLE)?;
360388
fdt.property_array_u32(
361389
"interrupts",
362390
&[
@@ -498,6 +526,7 @@ mod tests {
498526
let gic = create_gic(&vm, 1, None).unwrap();
499527
create_fdt(
500528
&mem,
529+
None,
501530
vec![0],
502531
CString::new("console=tty0").unwrap(),
503532
&dev_info,
@@ -518,6 +547,7 @@ mod tests {
518547
let gic = create_gic(&vm, 1, None).unwrap();
519548
create_fdt(
520549
&mem,
550+
None,
521551
vec![0],
522552
CString::new("console=tty0").unwrap(),
523553
&HashMap::<(DeviceType, std::string::String), MMIODeviceInfo>::new(),
@@ -543,6 +573,7 @@ mod tests {
543573

544574
let current_dtb_bytes = create_fdt(
545575
&mem,
576+
None,
546577
vec![0],
547578
CString::new("console=tty0").unwrap(),
548579
&HashMap::<(DeviceType, std::string::String), MMIODeviceInfo>::new(),
@@ -605,6 +636,7 @@ mod tests {
605636

606637
let current_dtb_bytes = create_fdt(
607638
&mem,
639+
None,
608640
vec![0],
609641
CString::new("console=tty0").unwrap(),
610642
&HashMap::<(DeviceType, std::string::String), MMIODeviceInfo>::new(),

src/vmm/src/arch/aarch64/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,9 @@ use self::gic::GICDevice;
2323
use crate::arch::DeviceType;
2424
use crate::device_manager::mmio::MMIODeviceInfo;
2525
use crate::devices::acpi::vmgenid::VmGenId;
26-
use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap};
26+
use crate::vstate::memory::{
27+
Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap, GuestRegionMmap,
28+
};
2729

2830
/// Errors thrown while configuring aarch64 system.
2931
#[derive(Debug, thiserror::Error, displaydoc::Display)]
@@ -72,6 +74,7 @@ pub fn bytes_before_last_gap() -> usize {
7274
/// * `initrd` - Information about an optional initrd.
7375
pub fn configure_system(
7476
guest_mem: &GuestMemoryMmap,
77+
swiotlb_region: Option<&GuestRegionMmap>,
7578
cmdline_cstring: CString,
7679
vcpu_mpidr: Vec<u64>,
7780
device_info: &HashMap<(DeviceType, String), MMIODeviceInfo>,
@@ -81,6 +84,7 @@ pub fn configure_system(
8184
) -> Result<(), ConfigurationError> {
8285
let fdt = fdt::create_fdt(
8386
guest_mem,
87+
swiotlb_region,
8488
vcpu_mpidr,
8589
cmdline_cstring,
8690
device_info,

src/vmm/src/builder.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,8 @@ pub fn build_microvm_for_boot(
238238

239239
let io_memory = vm_resources
240240
.allocate_io_memory()
241-
.map_err(StartMicrovmError::GuestMemory)?;
241+
.map_err(StartMicrovmError::GuestMemory)?
242+
.map(Arc::new);
242243

243244
// Clone the command-line so that a failed boot doesn't pollute the original.
244245
#[allow(unused_mut)]
@@ -264,9 +265,9 @@ pub fn build_microvm_for_boot(
264265
.map_err(StartMicrovmError::Internal)?;
265266
}
266267

267-
if let Some(io_memory) = io_memory {
268+
if let Some(ref io_memory) = io_memory {
268269
vmm.vm
269-
.register_io_region(io_memory)
270+
.register_io_region(Arc::clone(io_memory))
270271
.map_err(VmmError::Vm)
271272
.map_err(StartMicrovmError::Internal)?;
272273
}
@@ -325,6 +326,7 @@ pub fn build_microvm_for_boot(
325326

326327
configure_system_for_boot(
327328
&mut vmm,
329+
io_memory.as_deref(),
328330
vcpus.as_mut(),
329331
&vm_resources.machine_config,
330332
&cpu_template,
@@ -741,9 +743,11 @@ fn attach_legacy_devices_aarch64(
741743
}
742744

743745
/// Configures the system for booting Linux.
744-
#[cfg_attr(target_arch = "aarch64", allow(unused))]
746+
#[allow(unused)]
747+
#[allow(clippy::too_many_arguments)]
745748
pub fn configure_system_for_boot(
746749
vmm: &mut Vmm,
750+
swiotlb_region: Option<&GuestRegionMmap>,
747751
vcpus: &mut [Vcpu],
748752
machine_config: &MachineConfig,
749753
cpu_template: &CustomCpuTemplate,
@@ -855,6 +859,7 @@ pub fn configure_system_for_boot(
855859
let cmdline = boot_cmdline.as_cstring()?;
856860
crate::arch::aarch64::configure_system(
857861
&vmm.vm.guest_memory(),
862+
swiotlb_region,
858863
cmdline,
859864
vcpu_mpidr,
860865
vmm.mmio_device_manager.get_device_info(),

src/vmm/src/vstate/vm/mod.rs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -151,14 +151,10 @@ impl Vm {
151151
}
152152

153153
/// Registers a new io memory region to this [`Vm`].
154-
pub fn register_io_region(&mut self, region: GuestRegionMmap) -> Result<(), VmError> {
155-
let arcd_region = Arc::new(region);
156-
let new_io_memory = self
157-
.common
158-
.io_memory
159-
.insert_region(Arc::clone(&arcd_region))?;
154+
pub fn register_io_region(&mut self, region: Arc<GuestRegionMmap>) -> Result<(), VmError> {
155+
let new_io_memory = self.common.io_memory.insert_region(Arc::clone(&region))?;
160156

161-
self.register_kvm_region(arcd_region.as_ref())?;
157+
self.register_kvm_region(region.as_ref())?;
162158

163159
self.common.io_memory = new_io_memory;
164160
Ok(())

0 commit comments

Comments
 (0)