@@ -73,6 +73,7 @@ impl super::IntelCpuid {
7373 self . update_power_management_entry ( ) ?;
7474 self . update_extended_feature_flags_entry ( ) ?;
7575 self . update_performance_monitoring_entry ( ) ?;
76+ self . update_extended_topology_v2_entry ( ) ;
7677 self . update_brand_string_entry ( ) ?;
7778
7879 Ok ( ( ) )
@@ -210,6 +211,29 @@ impl super::IntelCpuid {
210211 Ok ( ( ) )
211212 }
212213
214+ /// Update extended topology v2 entry
215+ ///
216+ /// CPUID leaf 1FH is a preferred superset to leaf 0xB. Intel recommends using leaf 0x1F when
217+ /// available rather than leaf 0xB.
218+ ///
219+ /// Since we don't use any domains than ones supported in leaf 0xB, we just copy contents of
220+ /// leaf 0xB to leaf 0x1F.
221+ fn update_extended_topology_v2_entry ( & mut self ) {
222+ // Skip if leaf 0x1F does not exist.
223+ if self . get ( & CpuidKey :: leaf ( 0x1F ) ) . is_none ( ) {
224+ return ;
225+ }
226+
227+ for index in 0 .. {
228+ if let Some ( subleaf) = self . get ( & CpuidKey :: subleaf ( 0xB , index) ) {
229+ self . 0
230+ . insert ( CpuidKey :: subleaf ( 0x1F , index) , subleaf. clone ( ) ) ;
231+ } else {
232+ break ;
233+ }
234+ }
235+ }
236+
213237 fn update_brand_string_entry ( & mut self ) -> Result < ( ) , NormalizeCpuidError > {
214238 // Get host brand string.
215239 let host_brand_string: [ u8 ; BRAND_STRING_LENGTH ] = host_brand_string ( ) ;
@@ -331,9 +355,12 @@ mod tests {
331355 clippy:: as_conversions
332356 ) ]
333357
358+ use std:: collections:: BTreeMap ;
334359 use std:: ffi:: CStr ;
335360
336361 use super :: * ;
362+ use crate :: cpu_config:: x86_64:: cpuid:: { CpuidEntry , IntelCpuid , KvmCpuidFlags } ;
363+
337364 #[ test]
338365 fn default_brand_string_test ( ) {
339366 let brand_string = b"Intel(R) Xeon(R) Platinum 8275CL CPU @ 3.00GHz\0 \0 " ;
@@ -394,4 +421,106 @@ mod tests {
394421 assert ! ( ( leaf_7_0. result. ebx & ( 1 << 6 ) ) > 0 ) ;
395422 assert ! ( ( leaf_7_0. result. ebx & ( 1 << 13 ) ) > 0 ) ;
396423 }
424+
425+ #[ test]
426+ fn test_update_extended_topology_v2_entry_no_leaf_0x1f ( ) {
427+ let mut cpuid = IntelCpuid ( BTreeMap :: from ( [ (
428+ CpuidKey {
429+ leaf : 0xB ,
430+ subleaf : 0 ,
431+ } ,
432+ CpuidEntry {
433+ flags : KvmCpuidFlags :: SIGNIFICANT_INDEX ,
434+ ..Default :: default ( )
435+ } ,
436+ ) ] ) ) ;
437+
438+ cpuid. update_extended_topology_v2_entry ( ) ;
439+
440+ assert ! (
441+ cpuid
442+ . get( & CpuidKey {
443+ leaf: 0x1F ,
444+ subleaf: 0 ,
445+ } )
446+ . is_none( )
447+ ) ;
448+ }
449+
450+ #[ test]
451+ fn test_update_extended_topology_v2_entry ( ) {
452+ let mut cpuid = IntelCpuid ( BTreeMap :: from ( [
453+ (
454+ CpuidKey {
455+ leaf : 0xB ,
456+ subleaf : 0 ,
457+ } ,
458+ CpuidEntry {
459+ flags : KvmCpuidFlags :: SIGNIFICANT_INDEX ,
460+ result : CpuidRegisters {
461+ eax : 0x1 ,
462+ ebx : 0x2 ,
463+ ecx : 0x3 ,
464+ edx : 0x4 ,
465+ } ,
466+ } ,
467+ ) ,
468+ (
469+ CpuidKey {
470+ leaf : 0xB ,
471+ subleaf : 1 ,
472+ } ,
473+ CpuidEntry {
474+ flags : KvmCpuidFlags :: SIGNIFICANT_INDEX ,
475+ result : CpuidRegisters {
476+ eax : 0xa ,
477+ ebx : 0xb ,
478+ ecx : 0xc ,
479+ edx : 0xd ,
480+ } ,
481+ } ,
482+ ) ,
483+ (
484+ CpuidKey {
485+ leaf : 0x1F ,
486+ subleaf : 0 ,
487+ } ,
488+ CpuidEntry {
489+ flags : KvmCpuidFlags :: SIGNIFICANT_INDEX ,
490+ result : CpuidRegisters {
491+ eax : 0xFFFFFFFF ,
492+ ebx : 0xFFFFFFFF ,
493+ ecx : 0xFFFFFFFF ,
494+ edx : 0xFFFFFFFF ,
495+ } ,
496+ } ,
497+ ) ,
498+ ] ) ) ;
499+
500+ cpuid. update_extended_topology_v2_entry ( ) ;
501+
502+ // Check leaf 0x1F, subleaf 0 is updated.
503+ let leaf_1f_0 = cpuid
504+ . get ( & CpuidKey {
505+ leaf : 0x1F ,
506+ subleaf : 0 ,
507+ } )
508+ . unwrap ( ) ;
509+ assert_eq ! ( leaf_1f_0. result. eax, 0x1 ) ;
510+ assert_eq ! ( leaf_1f_0. result. ebx, 0x2 ) ;
511+ assert_eq ! ( leaf_1f_0. result. ecx, 0x3 ) ;
512+ assert_eq ! ( leaf_1f_0. result. edx, 0x4 ) ;
513+
514+ // Check lefa 0x1F, subleaf 1 is inserted.
515+ let leaf_1f_1 = cpuid
516+ . get ( & CpuidKey {
517+ leaf : 0x1F ,
518+ subleaf : 1 ,
519+ } )
520+ . unwrap ( ) ;
521+ assert_eq ! ( leaf_1f_1. result. eax, 0xa ) ;
522+ assert_eq ! ( leaf_1f_1. result. ebx, 0xb ) ;
523+ assert_eq ! ( leaf_1f_1. result. ecx, 0xc ) ;
524+ assert_eq ! ( leaf_1f_1. result. edx, 0xd ) ;
525+ }
397526}
0 commit comments