@@ -1246,12 +1246,89 @@ async fn new_underhill_vm(
1246
1246
1247
1247
let boot_info = runtime_params. parsed_openhcl_boot ( ) ;
1248
1248
1249
+ // Determine if x2apic is supported so that the topology matches
1250
+ // reality.
1251
+ //
1252
+ // We don't know if x2apic is forced on, but currently it doesn't really
1253
+ // matter because the topology's initial x2apic state is not currently
1254
+ // used in Underhill.
1255
+ //
1256
+ // FUTURE: consider having Underhill decide whether x2apic is enabled at
1257
+ // boot rather than allowing the host to make that decision. This would
1258
+ // just require Underhill setting the apicbase register on the VPs
1259
+ // before start.
1260
+ //
1261
+ // TODO: centralize cpuid querying logic.
1262
+ #[ cfg( guest_arch = "x86_64" ) ]
1263
+ let x2apic = if isolation. is_hardware_isolated ( ) {
1264
+ // For hardware CVMs, always enable x2apic support at boot.
1265
+ vm_topology:: processor:: x86:: X2ApicState :: Enabled
1266
+ } else if safe_x86_intrinsics:: cpuid ( x86defs:: cpuid:: CpuidFunction :: VersionAndFeatures . 0 , 0 ) . ecx
1267
+ & ( 1 << 21 )
1268
+ != 0
1269
+ {
1270
+ vm_topology:: processor:: x86:: X2ApicState :: Supported
1271
+ } else {
1272
+ vm_topology:: processor:: x86:: X2ApicState :: Unsupported
1273
+ } ;
1274
+
1275
+ #[ cfg( guest_arch = "x86_64" ) ]
1276
+ let processor_topology = new_x86_topology ( & boot_info. cpus , x2apic)
1277
+ . context ( "failed to construct the processor topology" ) ?;
1278
+
1279
+ #[ cfg( guest_arch = "aarch64" ) ]
1280
+ let processor_topology = new_aarch64_topology (
1281
+ boot_info
1282
+ . gic
1283
+ . context ( "did not get gic state from bootloader" ) ?,
1284
+ & boot_info. cpus ,
1285
+ )
1286
+ . context ( "failed to construct the processor topology" ) ?;
1287
+
1249
1288
// The amount of memory required by the GET igvm_attest request
1250
1289
let attestation = get_protocol:: IGVM_ATTEST_MSG_SHARED_GPA as u64 * hvdef:: HV_PAGE_SIZE ;
1251
1290
1252
- // TODO: determine actual memory usage by NVME/MANA. hardcode as 10MB
1253
- let device_dma = 10 * 1024 * 1024 ;
1291
+ const MIN_PER_QUEUE_PAGES : u64 = ( 128 * 1024 + hvdef:: HV_PAGE_SIZE ) / hvdef:: HV_PAGE_SIZE ;
1292
+ const DEFAULT_DMA_BOUNCE_BUFFER_PAGES_PER_QUEUE : u64 = 128 ;
1293
+ #[ allow( clippy:: assertions_on_constants) ]
1294
+ const _: ( ) = assert ! (
1295
+ DEFAULT_DMA_BOUNCE_BUFFER_PAGES_PER_QUEUE >= MIN_PER_QUEUE_PAGES ,
1296
+ "not enough room for an ATAPI IO plus a PRP list"
1297
+ ) ;
1298
+
1299
+ const DEFAULT_NVME_DRIVERS : u32 = 8 ;
1300
+ let ( max_nvme_drivers, dma_bounce_buffer_pages_per_queue, dma_bounce_buffer_pages_per_io_threshold) = dps. general . vtl2_settings . as_ref ( ) . map_or (
1301
+ ( DEFAULT_NVME_DRIVERS , DEFAULT_DMA_BOUNCE_BUFFER_PAGES_PER_QUEUE , None ) ,
1302
+ |vtl2_settings| {
1303
+ let original_dma_bounce_buffer_pages_per_queue = vtl2_settings
1304
+ . fixed
1305
+ . dma_bounce_buffer_pages_per_queue
1306
+ . unwrap_or ( DEFAULT_DMA_BOUNCE_BUFFER_PAGES_PER_QUEUE ) ;
1307
+
1308
+ let dma_bounce_buffer_pages_per_queue = if original_dma_bounce_buffer_pages_per_queue < MIN_PER_QUEUE_PAGES {
1309
+ tracing:: warn!(
1310
+ "the value of dma_bounce_buffer_pages_per_queue ({}) is less than MIN_PER_QUEUE_PAGES ({})" ,
1311
+ original_dma_bounce_buffer_pages_per_queue, MIN_PER_QUEUE_PAGES
1312
+ ) ;
1313
+ MIN_PER_QUEUE_PAGES
1314
+ } else {
1315
+ original_dma_bounce_buffer_pages_per_queue
1316
+ } ;
1317
+
1318
+ (
1319
+ vtl2_settings. fixed . max_nvme_drivers . unwrap_or ( DEFAULT_NVME_DRIVERS ) ,
1320
+ dma_bounce_buffer_pages_per_queue,
1321
+ vtl2_settings. fixed . dma_bounce_buffer_pages_per_io_threshold ,
1322
+ )
1323
+ } ,
1324
+ ) ;
1254
1325
1326
+ // TODO: determine actual memory usage by NVME/MANA. hardcode as 10MB
1327
+ let device_dma = 10 * 1024 * 1024
1328
+ + max_nvme_drivers as u64
1329
+ * processor_topology. vp_count ( ) as u64
1330
+ * dma_bounce_buffer_pages_per_queue
1331
+ * hvdef:: HV_PAGE_SIZE ;
1255
1332
// Determine the amount of shared memory to reserve from VTL0.
1256
1333
let shared_pool_size = match isolation {
1257
1334
#[ cfg( guest_arch = "x86_64" ) ]
@@ -1314,45 +1391,6 @@ async fn new_underhill_vm(
1314
1391
physical_address_size,
1315
1392
) ?;
1316
1393
1317
- // Determine if x2apic is supported so that the topology matches
1318
- // reality.
1319
- //
1320
- // We don't know if x2apic is forced on, but currently it doesn't really
1321
- // matter because the topology's initial x2apic state is not currently
1322
- // used in Underhill.
1323
- //
1324
- // FUTURE: consider having Underhill decide whether x2apic is enabled at
1325
- // boot rather than allowing the host to make that decision. This would
1326
- // just require Underhill setting the apicbase register on the VPs
1327
- // before start.
1328
- //
1329
- // TODO: centralize cpuid querying logic.
1330
- #[ cfg( guest_arch = "x86_64" ) ]
1331
- let x2apic = if isolation. is_hardware_isolated ( ) {
1332
- // For hardware CVMs, always enable x2apic support at boot.
1333
- vm_topology:: processor:: x86:: X2ApicState :: Enabled
1334
- } else if safe_x86_intrinsics:: cpuid ( x86defs:: cpuid:: CpuidFunction :: VersionAndFeatures . 0 , 0 ) . ecx
1335
- & ( 1 << 21 )
1336
- != 0
1337
- {
1338
- vm_topology:: processor:: x86:: X2ApicState :: Supported
1339
- } else {
1340
- vm_topology:: processor:: x86:: X2ApicState :: Unsupported
1341
- } ;
1342
-
1343
- #[ cfg( guest_arch = "x86_64" ) ]
1344
- let processor_topology = new_x86_topology ( & boot_info. cpus , x2apic)
1345
- . context ( "failed to construct the processor topology" ) ?;
1346
-
1347
- #[ cfg( guest_arch = "aarch64" ) ]
1348
- let processor_topology = new_aarch64_topology (
1349
- boot_info
1350
- . gic
1351
- . context ( "did not get gic state from bootloader" ) ?,
1352
- & boot_info. cpus ,
1353
- )
1354
- . context ( "failed to construct the processor topology" ) ?;
1355
-
1356
1394
let mut with_vmbus: bool = false ;
1357
1395
let mut with_vmbus_relay = false ;
1358
1396
if dps. general . vmbus_redirection_enabled {
@@ -1770,6 +1808,9 @@ async fn new_underhill_vm(
1770
1808
& driver_source,
1771
1809
processor_topology. vp_count ( ) ,
1772
1810
vfio_dma_buffer ( & shared_vis_pages_pool) ,
1811
+ dma_bounce_buffer_pages_per_queue,
1812
+ dma_bounce_buffer_pages_per_io_threshold,
1813
+ Some ( partition. clone ( ) ) ,
1773
1814
) ;
1774
1815
1775
1816
resolver. add_async_resolver :: < DiskHandleKind , _ , NvmeDiskConfig , _ > ( NvmeDiskResolver :: new (
0 commit comments