@@ -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,17 @@ 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+ #[ serde( default ) ]
103+ pub initial_swiotlb_size : usize ,
104+ }
105+
92106/// Struct used in PUT `/machine-config` API call.
93107#[ derive( Clone , Debug , PartialEq , Eq , Deserialize , Serialize ) ]
94108#[ serde( deny_unknown_fields) ]
@@ -97,6 +111,9 @@ pub struct MachineConfig {
97111 pub vcpu_count : u8 ,
98112 /// The memory size in MiB.
99113 pub mem_size_mib : usize ,
114+ /// Additional configuration options for guest memory
115+ #[ serde( default ) ]
116+ pub mem_config : MemoryConfig ,
100117 /// Enables or disabled SMT.
101118 #[ serde( default ) ]
102119 pub smt : bool ,
@@ -153,6 +170,7 @@ impl Default for MachineConfig {
153170 Self {
154171 vcpu_count : 1 ,
155172 mem_size_mib : DEFAULT_MEM_SIZE_MIB ,
173+ mem_config : Default :: default ( ) ,
156174 smt : false ,
157175 cpu_template : None ,
158176 track_dirty_pages : false ,
@@ -178,6 +196,9 @@ pub struct MachineConfigUpdate {
178196 /// The memory size in MiB.
179197 #[ serde( default ) ]
180198 pub mem_size_mib : Option < usize > ,
199+ /// The memory configuration
200+ #[ serde( default ) ]
201+ pub mem_config : Option < MemoryConfig > ,
181202 /// Enables or disabled SMT.
182203 #[ serde( default ) ]
183204 pub smt : Option < bool > ,
@@ -210,6 +231,7 @@ impl From<MachineConfig> for MachineConfigUpdate {
210231 MachineConfigUpdate {
211232 vcpu_count : Some ( cfg. vcpu_count ) ,
212233 mem_size_mib : Some ( cfg. mem_size_mib ) ,
234+ mem_config : Some ( cfg. mem_config ) ,
213235 smt : Some ( cfg. smt ) ,
214236 cpu_template : cfg. static_template ( ) ,
215237 track_dirty_pages : Some ( cfg. track_dirty_pages ) ,
@@ -263,11 +285,19 @@ impl MachineConfig {
263285
264286 let mem_size_mib = update. mem_size_mib . unwrap_or ( self . mem_size_mib ) ;
265287 let page_config = update. huge_pages . unwrap_or ( self . huge_pages ) ;
288+ let mem_config = update. mem_config . unwrap_or ( self . mem_config ) ;
266289
267290 if mem_size_mib == 0 || !page_config. is_valid_mem_size ( mem_size_mib) {
268291 return Err ( MachineConfigError :: InvalidMemorySize ) ;
269292 }
270293
294+ #[ cfg( target_arch = "aarch64" ) ]
295+ if mem_config. initial_swiotlb_size >= mem_size_mib
296+ || !page_config. is_valid_mem_size ( mem_config. initial_swiotlb_size )
297+ {
298+ return Err ( MachineConfigError :: InvalidSwiotlbRegionSize ) ;
299+ }
300+
271301 let cpu_template = match update. cpu_template {
272302 None => self . cpu_template . clone ( ) ,
273303 Some ( StaticCpuTemplate :: None ) => None ,
@@ -277,6 +307,7 @@ impl MachineConfig {
277307 Ok ( MachineConfig {
278308 vcpu_count,
279309 mem_size_mib,
310+ mem_config,
280311 smt,
281312 cpu_template,
282313 track_dirty_pages : update. track_dirty_pages . unwrap_or ( self . track_dirty_pages ) ,
0 commit comments