Skip to content

Commit 5a1ba36

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 25bd91c commit 5a1ba36

File tree

2 files changed

+46
-5
lines changed

2 files changed

+46
-5
lines changed

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

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,20 +10,23 @@ 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;
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};
2020
use crate::initrd::InitrdConfig;
21-
use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap};
21+
use crate::vstate::memory::{Address, GuestMemory, GuestMemoryMmap, KvmRegion};
2222

2323
// This is a value for uniquely identifying the FDT node declaring the interrupt controller.
2424
const GIC_PHANDLE: u32 = 1;
2525
// This is a value for uniquely identifying the FDT node containing the clock definition.
2626
const CLOCK_PHANDLE: u32 = 2;
27+
/// Unique identifier for the /reserved-memory node describing the memory region the guest
28+
/// is allowed to use for swiotlb
29+
const IO_MEM_PHANDLE: u32 = 3;
2730
// You may be wondering why this big value?
2831
// This phandle is used to uniquely identify the FDT nodes containing cache information. Each cpu
2932
// can have a variable number of caches, some of these caches may be shared with other cpus.
@@ -56,8 +59,10 @@ pub enum FdtError {
5659
}
5760

5861
/// Creates the flattened device tree for this aarch64 microVM.
62+
#[allow(clippy::too_many_arguments)]
5963
pub fn create_fdt(
6064
guest_mem: &GuestMemoryMmap,
65+
swiotlb_region: Option<&KvmRegion>,
6166
vcpu_mpidr: Vec<u64>,
6267
cmdline: CString,
6368
device_info: &HashMap<(DeviceType, String), MMIODeviceInfo>,
@@ -83,7 +88,7 @@ pub fn create_fdt(
8388
// containing description of the interrupt controller for this VM.
8489
fdt_writer.property_u32("interrupt-parent", GIC_PHANDLE)?;
8590
create_cpu_nodes(&mut fdt_writer, &vcpu_mpidr)?;
86-
create_memory_node(&mut fdt_writer, guest_mem)?;
91+
create_memory_node(&mut fdt_writer, guest_mem, swiotlb_region)?;
8792
create_chosen_node(&mut fdt_writer, cmdline, initrd)?;
8893
create_gic_node(&mut fdt_writer, gic_device)?;
8994
create_timer_node(&mut fdt_writer)?;
@@ -208,7 +213,11 @@ fn create_cpu_nodes(fdt: &mut FdtWriter, vcpu_mpidr: &[u64]) -> Result<(), FdtEr
208213
Ok(())
209214
}
210215

211-
fn create_memory_node(fdt: &mut FdtWriter, guest_mem: &GuestMemoryMmap) -> Result<(), FdtError> {
216+
fn create_memory_node(
217+
fdt: &mut FdtWriter,
218+
guest_mem: &GuestMemoryMmap,
219+
swiotlb_region: Option<&KvmRegion>,
220+
) -> Result<(), FdtError> {
212221
// See https://github.com/torvalds/linux/blob/master/Documentation/devicetree/booting-without-of.txt#L960
213222
// for an explanation of this.
214223

@@ -220,9 +229,13 @@ fn create_memory_node(fdt: &mut FdtWriter, guest_mem: &GuestMemoryMmap) -> Resul
220229
// The reason we do this is that Linux does not allow remapping system memory. However, without
221230
// remap, kernel drivers cannot get virtual addresses to read data from device memory. Leaving
222231
// this memory region out allows Linux kernel modules to remap and thus read this region.
232+
//
233+
// The generic memory description must include the range that we later declare as a reserved
234+
// carve out.
223235
let mem_size = guest_mem.last_addr().raw_value()
224236
- super::layout::DRAM_MEM_START
225237
- super::layout::SYSTEM_MEM_SIZE
238+
+ swiotlb_region.map(|r| r.len()).unwrap_or(0)
226239
+ 1;
227240
let mem_reg_prop = &[
228241
super::layout::DRAM_MEM_START + super::layout::SYSTEM_MEM_SIZE,
@@ -233,6 +246,19 @@ fn create_memory_node(fdt: &mut FdtWriter, guest_mem: &GuestMemoryMmap) -> Resul
233246
fdt.property_array_u64("reg", mem_reg_prop)?;
234247
fdt.end_node(mem)?;
235248

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

@@ -358,6 +384,9 @@ fn create_virtio_node(fdt: &mut FdtWriter, dev_info: &MMIODeviceInfo) -> Result<
358384

359385
fdt.property_string("compatible", "virtio,mmio")?;
360386
fdt.property_array_u64("reg", &[dev_info.addr, dev_info.len])?;
387+
// Force all virtio device to place their vrings and buffer into the dedicated I/O memory region
388+
// that is backed by traditional memory (e.g. not secret-free).
389+
fdt.property_u32("memory-region", IO_MEM_PHANDLE)?;
361390
fdt.property_array_u32(
362391
"interrupts",
363392
&[
@@ -499,6 +528,7 @@ mod tests {
499528
let gic = create_gic(&vm, 1, None).unwrap();
500529
create_fdt(
501530
&mem,
531+
None,
502532
vec![0],
503533
CString::new("console=tty0").unwrap(),
504534
&dev_info,
@@ -519,6 +549,7 @@ mod tests {
519549
let gic = create_gic(&vm, 1, None).unwrap();
520550
create_fdt(
521551
&mem,
552+
None,
522553
vec![0],
523554
CString::new("console=tty0").unwrap(),
524555
&HashMap::<(DeviceType, std::string::String), MMIODeviceInfo>::new(),
@@ -544,6 +575,7 @@ mod tests {
544575

545576
let current_dtb_bytes = create_fdt(
546577
&mem,
578+
None,
547579
vec![0],
548580
CString::new("console=tty0").unwrap(),
549581
&HashMap::<(DeviceType, std::string::String), MMIODeviceInfo>::new(),
@@ -606,6 +638,7 @@ mod tests {
606638

607639
let current_dtb_bytes = create_fdt(
608640
&mem,
641+
None,
609642
vec![0],
610643
CString::new("console=tty0").unwrap(),
611644
&HashMap::<(DeviceType, std::string::String), MMIODeviceInfo>::new(),

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

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,9 @@ use crate::cpu_config::templates::CustomCpuTemplate;
3030
use crate::initrd::InitrdConfig;
3131
use crate::utils::{align_up, usize_to_u64};
3232
use crate::vmm_config::machine_config::MachineConfig;
33-
use crate::vstate::memory::{Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap};
33+
use crate::vstate::memory::{
34+
Address, Bytes, GuestAddress, GuestMemory, GuestMemoryMmap,
35+
};
3436
use crate::vstate::vcpu::KvmVcpuError;
3537
use crate::{Vcpu, VcpuConfig, Vmm, logger};
3638

@@ -138,8 +140,14 @@ pub fn configure_system_for_boot(
138140
.as_cstring()
139141
.expect("Cannot create cstring from cmdline string");
140142

143+
let swiotlb_region = match vmm.vm.swiotlb_regions().num_regions() {
144+
0 | 1 => vmm.vm.swiotlb_regions().iter().next(),
145+
_ => panic!("Firecracker tried to configure more than one swiotlb region. This is a logic bug.")
146+
};
147+
141148
let fdt = fdt::create_fdt(
142149
vmm.vm.guest_memory(),
150+
swiotlb_region,
143151
vcpu_mpidr,
144152
cmdline,
145153
vmm.mmio_device_manager.get_device_info(),

0 commit comments

Comments
 (0)