@@ -10,6 +10,9 @@ use bit_helper::BitHelper;
1010use cpu_leaf:: * ;
1111use transformer:: common:: use_host_cpuid_function;
1212
13+ // Largest extended function. It has to be larger then 0x8000001d (Extended Cache Topology).
14+ const LARGEST_EXTENDED_FN : u32 = 0x8000_001f ;
15+
1316pub fn update_structured_extended_entry (
1417 entry : & mut kvm_cpuid_entry2 ,
1518 _vm_spec : & VmSpec ,
@@ -26,6 +29,21 @@ pub fn update_structured_extended_entry(
2629 Ok ( ( ) )
2730}
2831
32+ pub fn update_largest_extended_fn_entry (
33+ entry : & mut kvm_cpuid_entry2 ,
34+ _vm_spec : & VmSpec ,
35+ ) -> Result < ( ) , Error > {
36+ use cpu_leaf:: leaf_0x80000000:: * ;
37+
38+ // KVM sets the largest extended function to 0x80000000. Change it to 0x8000001f
39+ // Since we also use the leaf 0x8000001d (Extended Cache Topology).
40+ entry
41+ . eax
42+ . write_bits_in_range ( & eax:: LARGEST_EXTENDED_FN_BITRANGE , LARGEST_EXTENDED_FN ) ;
43+
44+ Ok ( ( ) )
45+ }
46+
2947pub fn update_extended_cache_topology_entry (
3048 entry : & mut kvm_cpuid_entry2 ,
3149 vm_spec : & VmSpec ,
@@ -46,6 +64,7 @@ impl CpuidTransformer for AmdCpuidTransformer {
4664 let maybe_transformer_fn: Option < EntryTransformerFn > = match entry. function {
4765 leaf_0x1:: LEAF_NUM => Some ( common:: update_feature_info_entry) ,
4866 leaf_0x7:: LEAF_NUM => Some ( amd:: update_structured_extended_entry) ,
67+ leaf_0x80000000:: LEAF_NUM => Some ( amd:: update_largest_extended_fn_entry) ,
4968 leaf_0x8000001d:: LEAF_NUM => Some ( amd:: update_extended_cache_topology_entry) ,
5069 0x8000_0002 ..=0x8000_0004 => Some ( common:: update_brand_string_entry) ,
5170 _ => None ,
@@ -65,10 +84,38 @@ mod test {
6584 use common:: VENDOR_ID_AMD ;
6685
6786 #[ test]
68- fn test_update_extended_cache_topology_entry ( ) {
87+ fn test_update_structured_extended_entry ( ) {
88+ use cpu_leaf:: leaf_0x7:: index0:: * ;
89+
90+ // Check that if index == 0 the entry is processed
6991 let vm_spec = VmSpec :: new ( VENDOR_ID_AMD , 0 , 1 , false ) ;
7092 let mut entry = & mut kvm_cpuid_entry2 {
71- function : leaf_0x8000001d:: LEAF_NUM ,
93+ function : leaf_0x7:: LEAF_NUM ,
94+ index : 0 ,
95+ flags : 0 ,
96+ eax : 0 ,
97+ ebx : 0 ,
98+ ecx : 0 ,
99+ edx : * ( 0 as u32 ) . write_bit ( edx:: ARCH_CAPABILITIES_BITINDEX , true ) ,
100+ padding : [ 0 , 0 , 0 ] ,
101+ } ;
102+ assert ! ( update_structured_extended_entry( & mut entry, & vm_spec) . is_ok( ) ) ;
103+ assert_eq ! ( entry. edx. read_bit( edx:: ARCH_CAPABILITIES_BITINDEX ) , false ) ;
104+
105+ // Check that if index != 0 the entry is not processed
106+ entry. index = 1 ;
107+ entry. edx . write_bit ( edx:: ARCH_CAPABILITIES_BITINDEX , true ) ;
108+ assert ! ( update_structured_extended_entry( & mut entry, & vm_spec) . is_ok( ) ) ;
109+ assert_eq ! ( entry. edx. read_bit( edx:: ARCH_CAPABILITIES_BITINDEX ) , true ) ;
110+ }
111+
112+ #[ test]
113+ fn test_update_largest_extended_fn_entry ( ) {
114+ use cpu_leaf:: leaf_0x80000000:: * ;
115+
116+ let vm_spec = VmSpec :: new ( VENDOR_ID_AMD , 0 , 1 , false ) ;
117+ let mut entry = & mut kvm_cpuid_entry2 {
118+ function : LEAF_NUM ,
72119 index : 0 ,
73120 flags : 0 ,
74121 eax : 0 ,
@@ -78,34 +125,32 @@ mod test {
78125 padding : [ 0 , 0 , 0 ] ,
79126 } ;
80127
81- assert ! ( update_extended_cache_topology_entry ( & mut entry, & vm_spec) . is_ok( ) ) ;
128+ assert ! ( update_largest_extended_fn_entry ( & mut entry, & vm_spec) . is_ok( ) ) ;
82129
83- assert_eq ! ( entry. flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX , 1 ) ;
130+ assert_eq ! (
131+ entry
132+ . eax
133+ . read_bits_in_range( & eax:: LARGEST_EXTENDED_FN_BITRANGE ) ,
134+ LARGEST_EXTENDED_FN
135+ ) ;
84136 }
85137
86138 #[ test]
87- fn test_update_structured_extended_entry ( ) {
88- use cpu_leaf:: leaf_0x7:: index0:: * ;
89-
90- // Check that if index == 0 the entry is processed
139+ fn test_update_extended_cache_topology_entry ( ) {
91140 let vm_spec = VmSpec :: new ( VENDOR_ID_AMD , 0 , 1 , false ) ;
92141 let mut entry = & mut kvm_cpuid_entry2 {
93- function : leaf_0x7 :: LEAF_NUM ,
142+ function : leaf_0x8000001d :: LEAF_NUM ,
94143 index : 0 ,
95144 flags : 0 ,
96145 eax : 0 ,
97146 ebx : 0 ,
98147 ecx : 0 ,
99- edx : * ( 0 as u32 ) . write_bit ( edx :: ARCH_CAPABILITIES_BITINDEX , true ) ,
148+ edx : 0 ,
100149 padding : [ 0 , 0 , 0 ] ,
101150 } ;
102- assert ! ( update_structured_extended_entry( & mut entry, & vm_spec) . is_ok( ) ) ;
103- assert_eq ! ( entry. edx. read_bit( edx:: ARCH_CAPABILITIES_BITINDEX ) , false ) ;
104151
105- // Check that if index != 0 the entry is not processed
106- entry. index = 1 ;
107- entry. edx . write_bit ( edx:: ARCH_CAPABILITIES_BITINDEX , true ) ;
108- assert ! ( update_structured_extended_entry( & mut entry, & vm_spec) . is_ok( ) ) ;
109- assert_eq ! ( entry. edx. read_bit( edx:: ARCH_CAPABILITIES_BITINDEX ) , true ) ;
152+ assert ! ( update_extended_cache_topology_entry( & mut entry, & vm_spec) . is_ok( ) ) ;
153+
154+ assert_eq ! ( entry. flags & KVM_CPUID_FLAG_SIGNIFCANT_INDEX , 1 ) ;
110155 }
111156}
0 commit comments