Skip to content

Commit 02b9063

Browse files
Serban Iorgaacatangiu
authored andcommitted
AMD: fix the value of the largest extended fn
KVM sets the largest extended function to 0x80000000. We have to change it to 0x8000001f since we also use the leaf 0x8000001d. Signed-off-by: Serban Iorga <[email protected]>
1 parent a8c32ea commit 02b9063

File tree

2 files changed

+72
-21
lines changed

2 files changed

+72
-21
lines changed

cpuid/src/cpu_leaf.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,6 @@ pub mod leaf_0x7 {
173173
}
174174
}
175175

176-
pub mod leaf_0x80000000 {
177-
pub const LEAF_NUM: u32 = 0x8000_0000;
178-
}
179-
180176
pub mod leaf_0x80000001 {
181177
pub const LEAF_NUM: u32 = 0x8000_0001;
182178

@@ -225,3 +221,13 @@ pub mod leaf_0xb {
225221
pub const LEVEL_NUMBER_BITRANGE: BitRange = bit_range!(7, 0);
226222
}
227223
}
224+
225+
pub mod leaf_0x80000000 {
226+
pub const LEAF_NUM: u32 = 0x8000_0000;
227+
228+
pub mod eax {
229+
use bit_helper::BitRange;
230+
231+
pub const LARGEST_EXTENDED_FN_BITRANGE: BitRange = bit_range!(31, 0);
232+
}
233+
}

cpuid/src/transformer/amd.rs

Lines changed: 62 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ use bit_helper::BitHelper;
1010
use cpu_leaf::*;
1111
use 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+
1316
pub 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+
2947
pub 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

Comments
 (0)