@@ -10,19 +10,22 @@ use std::ffi::CString;
1010use std:: fmt:: Debug ;
1111
1212use vm_fdt:: { Error as VmFdtError , FdtWriter , FdtWriterNode } ;
13- use vm_memory:: GuestMemoryError ;
13+ use vm_memory:: { GuestMemoryError , GuestMemoryRegion } ;
1414
1515use super :: super :: { DeviceType , InitrdConfig } ;
1616use super :: cache_info:: { CacheEntry , read_cache_config} ;
1717use super :: gic:: GICDevice ;
1818use crate :: device_manager:: mmio:: MMIODeviceInfo ;
1919use 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.
2323const GIC_PHANDLE : u32 = 1 ;
2424// This is a value for uniquely identifying the FDT node containing the clock definition.
2525const 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.
5861pub 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 ( ) ,
0 commit comments