@@ -10,20 +10,23 @@ 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 ;
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 } ;
2020use 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.
2424const GIC_PHANDLE : u32 = 1 ;
2525// This is a value for uniquely identifying the FDT node containing the clock definition.
2626const 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.
@@ -58,6 +61,7 @@ pub enum FdtError {
5861/// Creates the flattened device tree for this aarch64 microVM.
5962pub fn create_fdt (
6063 guest_mem : & GuestMemoryMmap ,
64+ swiotlb_region : Option < & KvmRegion > ,
6165 vcpu_mpidr : Vec < u64 > ,
6266 cmdline : CString ,
6367 device_info : & HashMap < ( DeviceType , String ) , MMIODeviceInfo > ,
@@ -83,7 +87,7 @@ pub fn create_fdt(
8387 // containing description of the interrupt controller for this VM.
8488 fdt_writer. property_u32 ( "interrupt-parent" , GIC_PHANDLE ) ?;
8589 create_cpu_nodes ( & mut fdt_writer, & vcpu_mpidr) ?;
86- create_memory_node ( & mut fdt_writer, guest_mem) ?;
90+ create_memory_node ( & mut fdt_writer, guest_mem, swiotlb_region ) ?;
8791 create_chosen_node ( & mut fdt_writer, cmdline, initrd) ?;
8892 create_gic_node ( & mut fdt_writer, gic_device) ?;
8993 create_timer_node ( & mut fdt_writer) ?;
@@ -208,7 +212,11 @@ fn create_cpu_nodes(fdt: &mut FdtWriter, vcpu_mpidr: &[u64]) -> Result<(), FdtEr
208212 Ok ( ( ) )
209213}
210214
211- fn create_memory_node ( fdt : & mut FdtWriter , guest_mem : & GuestMemoryMmap ) -> Result < ( ) , FdtError > {
215+ fn create_memory_node (
216+ fdt : & mut FdtWriter ,
217+ guest_mem : & GuestMemoryMmap ,
218+ swiotlb_region : Option < & KvmRegion > ,
219+ ) -> Result < ( ) , FdtError > {
212220 // See https://github.com/torvalds/linux/blob/master/Documentation/devicetree/booting-without-of.txt#L960
213221 // for an explanation of this.
214222
@@ -220,9 +228,13 @@ fn create_memory_node(fdt: &mut FdtWriter, guest_mem: &GuestMemoryMmap) -> Resul
220228 // The reason we do this is that Linux does not allow remapping system memory. However, without
221229 // remap, kernel drivers cannot get virtual addresses to read data from device memory. Leaving
222230 // this memory region out allows Linux kernel modules to remap and thus read this region.
231+ //
232+ // The generic memory description must include the range that we later declare as a reserved
233+ // carve out.
223234 let mem_size = guest_mem. last_addr ( ) . raw_value ( )
224235 - super :: layout:: DRAM_MEM_START
225236 - super :: layout:: SYSTEM_MEM_SIZE
237+ + swiotlb_region. map ( |r| r. len ( ) ) . unwrap_or ( 0 )
226238 + 1 ;
227239 let mem_reg_prop = & [
228240 super :: layout:: DRAM_MEM_START + super :: layout:: SYSTEM_MEM_SIZE ,
@@ -233,6 +245,19 @@ fn create_memory_node(fdt: &mut FdtWriter, guest_mem: &GuestMemoryMmap) -> Resul
233245 fdt. property_array_u64 ( "reg" , mem_reg_prop) ?;
234246 fdt. end_node ( mem) ?;
235247
248+ if let Some ( region) = swiotlb_region {
249+ let rmem = fdt. begin_node ( "reserved-memory" ) ?;
250+ fdt. property_u32 ( "#address-cells" , ADDRESS_CELLS ) ?;
251+ fdt. property_u32 ( "#size-cells" , SIZE_CELLS ) ?;
252+ fdt. property_null ( "ranges" ) ?;
253+ let dma = fdt. begin_node ( "bouncy_boi" ) ?;
254+ fdt. property_string ( "compatible" , "restricted-dma-pool" ) ?;
255+ fdt. property_phandle ( IO_MEM_PHANDLE ) ?;
256+ fdt. property_array_u64 ( "reg" , & [ region. start_addr ( ) . 0 , region. len ( ) ] ) ?;
257+ fdt. end_node ( dma) ?;
258+ fdt. end_node ( rmem) ?;
259+ }
260+
236261 Ok ( ( ) )
237262}
238263
@@ -358,6 +383,9 @@ fn create_virtio_node(fdt: &mut FdtWriter, dev_info: &MMIODeviceInfo) -> Result<
358383
359384 fdt. property_string ( "compatible" , "virtio,mmio" ) ?;
360385 fdt. property_array_u64 ( "reg" , & [ dev_info. addr , dev_info. len ] ) ?;
386+ // Force all virtio device to place their vrings and buffer into the dedicated I/O memory region
387+ // that is backed by traditional memory (e.g. not secret-free).
388+ fdt. property_u32 ( "memory-region" , IO_MEM_PHANDLE ) ?;
361389 fdt. property_array_u32 (
362390 "interrupts" ,
363391 & [
@@ -499,6 +527,7 @@ mod tests {
499527 let gic = create_gic ( & vm, 1 , None ) . unwrap ( ) ;
500528 create_fdt (
501529 & mem,
530+ None ,
502531 vec ! [ 0 ] ,
503532 CString :: new ( "console=tty0" ) . unwrap ( ) ,
504533 & dev_info,
@@ -519,6 +548,7 @@ mod tests {
519548 let gic = create_gic ( & vm, 1 , None ) . unwrap ( ) ;
520549 create_fdt (
521550 & mem,
551+ None ,
522552 vec ! [ 0 ] ,
523553 CString :: new ( "console=tty0" ) . unwrap ( ) ,
524554 & HashMap :: < ( DeviceType , std:: string:: String ) , MMIODeviceInfo > :: new ( ) ,
@@ -544,6 +574,7 @@ mod tests {
544574
545575 let current_dtb_bytes = create_fdt (
546576 & mem,
577+ None ,
547578 vec ! [ 0 ] ,
548579 CString :: new ( "console=tty0" ) . unwrap ( ) ,
549580 & HashMap :: < ( DeviceType , std:: string:: String ) , MMIODeviceInfo > :: new ( ) ,
@@ -606,6 +637,7 @@ mod tests {
606637
607638 let current_dtb_bytes = create_fdt (
608639 & mem,
640+ None ,
609641 vec ! [ 0 ] ,
610642 CString :: new ( "console=tty0" ) . unwrap ( ) ,
611643 & HashMap :: < ( DeviceType , std:: string:: String ) , MMIODeviceInfo > :: new ( ) ,
0 commit comments