@@ -20,6 +20,9 @@ pub enum MachineConfigError {
2020 IncompatibleBalloonSize ,
2121 /// The memory size (MiB) is either 0, or not a multiple of the configured page size.
2222 InvalidMemorySize ,
23+ /// The specified swiotlb region matches or exceeds the total VM memory, or not a multiple of the configured page size.
24+ #[ cfg( target_arch = "aarch64" ) ]
25+ InvalidSwiotlbRegionSize ,
2326 /// The number of vCPUs must be greater than 0, less than {MAX_SUPPORTED_VCPUS:} and must be 1 or an even number if SMT is enabled.
2427 InvalidVcpuCount ,
2528 /// Could not get the configuration of the previously installed balloon device to validate the memory size.
@@ -89,6 +92,16 @@ impl From<HugePageConfig> for Option<memfd::HugetlbSize> {
8992 }
9093}
9194
95+ /// Structure containing options for tweaking guest memory configuration.
96+ #[ derive( Clone , Copy , Debug , Default , PartialEq , Eq , Deserialize , Serialize ) ]
97+ pub struct MemoryConfig {
98+ /// The initial size of the swiotlb region. If 0, no swiotlb region will be created.
99+ /// If non-zero, all device will be forced to bounce buffers through a swiotlb region
100+ /// of the specified size that will have been placed into a dedicated kvm memslot.
101+ #[ cfg( target_arch = "aarch64" ) ]
102+ pub initial_swiotlb_size : usize ,
103+ }
104+
92105/// Struct used in PUT `/machine-config` API call.
93106#[ derive( Clone , Debug , PartialEq , Eq , Deserialize , Serialize ) ]
94107#[ serde( deny_unknown_fields) ]
@@ -97,6 +110,9 @@ pub struct MachineConfig {
97110 pub vcpu_count : u8 ,
98111 /// The memory size in MiB.
99112 pub mem_size_mib : usize ,
113+ /// Additional configuration options for guest memory
114+ #[ serde( default ) ]
115+ pub mem_config : MemoryConfig ,
100116 /// Enables or disabled SMT.
101117 #[ serde( default ) ]
102118 pub smt : bool ,
@@ -153,6 +169,7 @@ impl Default for MachineConfig {
153169 Self {
154170 vcpu_count : 1 ,
155171 mem_size_mib : DEFAULT_MEM_SIZE_MIB ,
172+ mem_config : Default :: default ( ) ,
156173 smt : false ,
157174 cpu_template : None ,
158175 track_dirty_pages : false ,
@@ -178,6 +195,9 @@ pub struct MachineConfigUpdate {
178195 /// The memory size in MiB.
179196 #[ serde( default ) ]
180197 pub mem_size_mib : Option < usize > ,
198+ /// The memory configuration
199+ #[ serde( default ) ]
200+ pub mem_config : Option < MemoryConfig > ,
181201 /// Enables or disabled SMT.
182202 #[ serde( default ) ]
183203 pub smt : Option < bool > ,
@@ -210,6 +230,7 @@ impl From<MachineConfig> for MachineConfigUpdate {
210230 MachineConfigUpdate {
211231 vcpu_count : Some ( cfg. vcpu_count ) ,
212232 mem_size_mib : Some ( cfg. mem_size_mib ) ,
233+ mem_config : Some ( cfg. mem_config ) ,
213234 smt : Some ( cfg. smt ) ,
214235 cpu_template : cfg. static_template ( ) ,
215236 track_dirty_pages : Some ( cfg. track_dirty_pages ) ,
@@ -263,11 +284,19 @@ impl MachineConfig {
263284
264285 let mem_size_mib = update. mem_size_mib . unwrap_or ( self . mem_size_mib ) ;
265286 let page_config = update. huge_pages . unwrap_or ( self . huge_pages ) ;
287+ let mem_config = update. mem_config . unwrap_or ( self . mem_config ) ;
266288
267289 if mem_size_mib == 0 || !page_config. is_valid_mem_size ( mem_size_mib) {
268290 return Err ( MachineConfigError :: InvalidMemorySize ) ;
269291 }
270292
293+ #[ cfg( target_arch = "aarch64" ) ]
294+ if mem_config. initial_swiotlb_size >= mem_size_mib
295+ || !page_config. is_valid_mem_size ( mem_config. initial_swiotlb_size )
296+ {
297+ return Err ( MachineConfigError :: InvalidSwiotlbRegionSize ) ;
298+ }
299+
271300 let cpu_template = match update. cpu_template {
272301 None => self . cpu_template . clone ( ) ,
273302 Some ( StaticCpuTemplate :: None ) => None ,
@@ -277,6 +306,7 @@ impl MachineConfig {
277306 Ok ( MachineConfig {
278307 vcpu_count,
279308 mem_size_mib,
309+ mem_config,
280310 smt,
281311 cpu_template,
282312 track_dirty_pages : update. track_dirty_pages . unwrap_or ( self . track_dirty_pages ) ,
0 commit comments