Skip to content

Commit 2f1902e

Browse files
authored
Merge branch 'main' into allow-snapshot-tap-changes
2 parents 75be992 + 983a20a commit 2f1902e

File tree

8 files changed

+481
-300
lines changed

8 files changed

+481
-300
lines changed

docs/cpu_templates/cpuid-normalization.md

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -28,15 +28,16 @@ See also: [boot protocol settings](boot-protocol.md)
2828

2929
## Intel-specific CPUID normalization
3030

31-
| Description | Leaf | Subleaf | Register | Bits |
32-
| -------------------------------------------------------------- | :--------------------------------: | :-----: | :----------------: | :---: |
33-
| Update deterministic cache parameters | 0x4 | all | EAX | 31:14 |
34-
| Disable Intel Turbo Boost technology | 0x6 | - | EAX | 1 |
35-
| Disable frequency selection | 0x6 | - | ECX | 3 |
36-
| Set FDP_EXCPTN_ONLY bit | 0x7 | 0x0 | EBX | 6 |
37-
| Set "Deprecates FPU CS and FPU DS values" bit | 0x7 | 0x0 | EBX | 13 |
38-
| Disable performance monitoring | 0xa | - | EAX, EBX, ECX, EDX | all |
39-
| Update brand string to use a default format and real frequency | 0x80000002, 0x80000003, 0x80000004 | - | EAX, EBX, ECX, EDX | all |
31+
| Description | Leaf | Subleaf | Register | Bits |
32+
| -------------------------------------------------------------- | :--------------------------------: | :-----: | :------: | :---: |
33+
| Update deterministic cache parameters | 0x4 | all | EAX | 31:14 |
34+
| Disable Intel Turbo Boost technology | 0x6 | - | EAX | 1 |
35+
| Disable frequency selection | 0x6 | - | ECX | 3 |
36+
| Set FDP_EXCPTN_ONLY bit | 0x7 | 0x0 | EBX | 6 |
37+
| Set "Deprecates FPU CS and FPU DS values" bit | 0x7 | 0x0 | EBX | 13 |
38+
| Disable performance monitoring | 0xa | - | all | all |
39+
| Fill v2 extended topology enumeration leaf | 0x1f | all | all | all |
40+
| Update brand string to use a default format and real frequency | 0x80000002, 0x80000003, 0x80000004 | - | all | all |
4041

4142
## AMD-specifc CPUID normalization
4243

src/vmm/src/cpu_config/x86_64/cpuid/amd/normalize.rs

Lines changed: 40 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -48,33 +48,35 @@ pub enum PassthroughCacheTopologyError {
4848
pub enum FeatureEntryError {
4949
/// Missing leaf 0x80000008.
5050
MissingLeaf0x80000008,
51-
/// Failed to set `nt` (number of physical threads) due to overflow.
52-
NumberOfPhysicalThreadsOverflow,
53-
/// Failed to set `nt` (number of physical threads).
51+
/// Failed to set number of physical threads (CPUID.80000008H:ECX[7:0]): {0}
5452
NumberOfPhysicalThreads(CheckedAssignError),
53+
/// Failed to set number of physical threads (CPUID.80000008H:ECX[7:0]) due to overflow.
54+
NumberOfPhysicalThreadsOverflow,
5555
}
5656

5757
/// Error type for setting leaf 0x8000001d section of [`super::AmdCpuid::normalize`].
5858
#[derive(Debug, thiserror::Error, displaydoc::Display, Eq, PartialEq)]
5959
pub enum ExtendedCacheTopologyError {
6060
/// Missing leaf 0x8000001d.
6161
MissingLeaf0x8000001d,
62-
/// Failed to set `num_sharing_cache` due to overflow.
63-
NumSharingCacheOverflow,
64-
/// Failed to set `num_sharing_cache`: {0}
65-
NumSharingCache(CheckedAssignError),
62+
#[rustfmt::skip]
63+
/// Failed to set number of logical processors sharing cache(CPUID.(EAX=8000001DH,ECX={0}):EAX[25:14]): {1}
64+
NumSharingCache(u32, CheckedAssignError),
65+
#[rustfmt::skip]
66+
/// Failed to set number of logical processors sharing cache (CPUID.(EAX=8000001DH,ECX={0}):EAX[25:14]) due to overflow.
67+
NumSharingCacheOverflow(u32),
6668
}
6769

6870
/// Error type for setting leaf 0x8000001e section of [`super::AmdCpuid::normalize`].
6971
#[derive(Debug, thiserror::Error, displaydoc::Display, Eq, PartialEq)]
7072
pub enum ExtendedApicIdError {
73+
/// Failed to set compute unit ID (CPUID.8000001EH:EBX[7:0]): {0}
74+
ComputeUnitId(CheckedAssignError),
75+
/// Failed to set extended APIC ID (CPUID.8000001EH:EAX[31:0]): {0}
76+
ExtendedApicId(CheckedAssignError),
7177
/// Missing leaf 0x8000001e.
7278
MissingLeaf0x8000001e,
73-
/// Failed to set `extended_apic_id`: {0}
74-
ExtendedApicId(CheckedAssignError),
75-
/// Failed to set `compute_unit_id`: {0}
76-
ComputeUnitId(CheckedAssignError),
77-
/// Failed to set `threads_per_compute_unit`: {0}
79+
/// Failed to set threads per core unit (CPUID:8000001EH:EBX[15:8]): {0}
7880
ThreadPerComputeUnit(CheckedAssignError),
7981
}
8082

@@ -153,6 +155,7 @@ impl super::AmdCpuid {
153155
// On non-AMD hosts this condition may never be true thus this loop may be
154156
// indefinite.
155157

158+
// CPUID Fn8000_0001D_EAX_x[4:0] (Field Name: CacheType)
156159
// Cache type. Identifies the type of cache.
157160
// ```text
158161
// Bits Description
@@ -162,8 +165,6 @@ impl super::AmdCpuid {
162165
// 03h Unified cache
163166
// 1Fh-04h Reserved.
164167
// ```
165-
//
166-
// cache_type: 0..4,
167168
let cache_type = result.eax & 15;
168169
if cache_type == 0 {
169170
break;
@@ -186,10 +187,9 @@ impl super::AmdCpuid {
186187
let leaf_80000001 = self
187188
.get_mut(&CpuidKey::leaf(0x80000001))
188189
.ok_or(NormalizeCpuidError::MissingLeaf0x80000001)?;
190+
// CPUID Fn8000_0001_ECX[22] (Field Name: TopologyExtensions)
189191
// Topology extensions support. Indicates support for CPUID Fn8000_001D_EAX_x[N:0]-CPUID
190192
// Fn8000_001E_EDX.
191-
//
192-
// topology_extensions: 22,
193193
set_bit(&mut leaf_80000001.result.ecx, 22, true);
194194
Ok(())
195195
}
@@ -220,6 +220,7 @@ impl super::AmdCpuid {
220220
.get_mut(&CpuidKey::leaf(0x80000008))
221221
.ok_or(FeatureEntryError::MissingLeaf0x80000008)?;
222222

223+
// CPUID Fn8000_0008_ECX[15:12] (Field Name: ApicIdSize)
223224
// APIC ID size. The number of bits in the initial APIC20[ApicId] value that indicate
224225
// logical processor ID within a package. The size of this field determines the
225226
// maximum number of logical processors (MNLP) that the package could
@@ -228,19 +229,15 @@ impl super::AmdCpuid {
228229
// Fn8000_0008_ECX[NC]. A value of zero indicates that legacy methods must be
229230
// used to determine the maximum number of logical processors, as indicated by
230231
// CPUID Fn8000_0008_ECX[NC].
231-
//
232-
// apic_id_size: 12..16,
233-
set_range(&mut leaf_80000008.result.ecx, 12..16, THREAD_ID_MAX_SIZE).unwrap();
232+
set_range(&mut leaf_80000008.result.ecx, 12..=15, THREAD_ID_MAX_SIZE).unwrap();
234233

234+
// CPUID Fn8000_0008_ECX[7:0] (Field Name: NC)
235235
// Number of physical threads - 1. The number of threads in the processor is NT+1
236236
// (e.g., if NT = 0, then there is one thread). See “Legacy Method” on page 633.
237-
//
238-
// nt: 0..8,
239-
//
240237
let sub = cpu_count
241238
.checked_sub(1)
242239
.ok_or(FeatureEntryError::NumberOfPhysicalThreadsOverflow)?;
243-
set_range(&mut leaf_80000008.result.ecx, 0..8, u32::from(sub))
240+
set_range(&mut leaf_80000008.result.ecx, 0..=7, u32::from(sub))
244241
.map_err(FeatureEntryError::NumberOfPhysicalThreads)?;
245242

246243
Ok(())
@@ -255,6 +252,7 @@ impl super::AmdCpuid {
255252
) -> Result<(), ExtendedCacheTopologyError> {
256253
for i in 0.. {
257254
if let Some(subleaf) = self.get_mut(&CpuidKey::subleaf(0x8000001d, i)) {
255+
// CPUID Fn8000_001D_EAX_x[7:5] (Field Name: CacheLevel)
258256
// Cache level. Identifies the level of this cache. Note that the enumeration value
259257
// is not necessarily equal to the cache level.
260258
// ```text
@@ -265,10 +263,9 @@ impl super::AmdCpuid {
265263
// 011b Level 3
266264
// 111b-100b Reserved.
267265
// ```
268-
//
269-
// cache_level: 5..8
270-
let cache_level = get_range(subleaf.result.eax, 5..8);
266+
let cache_level = get_range(subleaf.result.eax, 5..=7);
271267

268+
// CPUID Fn8000_001D_EAX_x[25:14] (Field Name: NumSharingCache)
272269
// Specifies the number of logical processors sharing the cache enumerated by N,
273270
// the value passed to the instruction in ECX. The number of logical processors
274271
// sharing this cache is the value of this field incremented by 1. To determine
@@ -279,26 +276,24 @@ impl super::AmdCpuid {
279276
//
280277
// Logical processors with the same ShareId then share a cache. If
281278
// NumSharingCache+1 is not a power of two, round it up to the next power of two.
282-
//
283-
// num_sharing_cache: 14..26,
284279

285280
match cache_level {
286281
// L1 & L2 Cache
287282
// The L1 & L2 cache is shared by at most 2 hyper-threads
288283
1 | 2 => {
289284
// SAFETY: We know `cpus_per_core > 0` therefore this is always safe.
290285
let sub = u32::from(cpus_per_core.checked_sub(1).unwrap());
291-
set_range(&mut subleaf.result.eax, 14..26, sub)
292-
.map_err(ExtendedCacheTopologyError::NumSharingCache)?;
286+
set_range(&mut subleaf.result.eax, 14..=25, sub)
287+
.map_err(|err| ExtendedCacheTopologyError::NumSharingCache(i, err))?;
293288
}
294289
// L3 Cache
295290
// The L3 cache is shared among all the logical threads
296291
3 => {
297292
let sub = cpu_count
298293
.checked_sub(1)
299-
.ok_or(ExtendedCacheTopologyError::NumSharingCacheOverflow)?;
300-
set_range(&mut subleaf.result.eax, 14..26, u32::from(sub))
301-
.map_err(ExtendedCacheTopologyError::NumSharingCache)?;
294+
.ok_or(ExtendedCacheTopologyError::NumSharingCacheOverflow(i))?;
295+
set_range(&mut subleaf.result.eax, 14..=25, u32::from(sub))
296+
.map_err(|err| ExtendedCacheTopologyError::NumSharingCache(i, err))?;
302297
}
303298
_ => (),
304299
}
@@ -334,16 +329,18 @@ impl super::AmdCpuid {
334329
.get_mut(&CpuidKey::leaf(0x8000001e))
335330
.ok_or(ExtendedApicIdError::MissingLeaf0x8000001e)?;
336331

332+
// CPUID Fn8000_001E_EAX[31:0] (Field Name: ExtendedApicId)
337333
// Extended APIC ID. If MSR0000_001B[ApicEn] = 0, this field is reserved.
338-
//
339-
// extended_apic_id: 0..32,
340-
set_range(&mut leaf_8000001e.result.eax, 0..32, u32::from(cpu_index))
334+
set_range(&mut leaf_8000001e.result.eax, 0..=31, u32::from(cpu_index))
341335
.map_err(ExtendedApicIdError::ExtendedApicId)?;
342336

343-
// compute_unit_id: 0..8,
344-
set_range(&mut leaf_8000001e.result.ebx, 0..8, core_id)
337+
// CPUID Fn8000_001E_EBX[7:0] (Field Name: ComputeUnitId)
338+
// Compute unit ID. Identifies a Compute Unit, which may be one or more physical cores that
339+
// each implement one or more logical processors.
340+
set_range(&mut leaf_8000001e.result.ebx, 0..=7, core_id)
345341
.map_err(ExtendedApicIdError::ComputeUnitId)?;
346342

343+
// CPUID Fn8000_001E_EBX[15:8] (Field Name: ThreadsPerComputeUnit)
347344
// Threads per compute unit (zero-based count). The actual number of threads
348345
// per compute unit is the value of this field + 1. To determine which logical
349346
// processors (threads) belong to a given Compute Unit, determine a ShareId
@@ -355,30 +352,26 @@ impl super::AmdCpuid {
355352
// Unit. (If ThreadsPerComputeUnit+1 is not a power of two, round it up to the
356353
// next power of two).
357354
//
358-
// threads_per_compute_unit: 8..16,
359-
//
360355
// SAFETY: We know `cpus_per_core > 0` therefore this is always safe.
361356
let sub = u32::from(cpus_per_core.checked_sub(1).unwrap());
362-
set_range(&mut leaf_8000001e.result.ebx, 8..16, sub)
357+
set_range(&mut leaf_8000001e.result.ebx, 8..=15, sub)
363358
.map_err(ExtendedApicIdError::ThreadPerComputeUnit)?;
364359

360+
// CPUID Fn8000_001E_ECX[10:8] (Field Name: NodesPerProcessor)
365361
// Specifies the number of nodes in the package/socket in which this logical
366362
// processor resides. Node in this context corresponds to a processor die.
367363
// Encoding is N-1, where N is the number of nodes present in the socket.
368364
//
369-
// nodes_per_processor: 8..11,
370-
//
371365
// SAFETY: We know the value always fits within the range and thus is always safe.
372366
// Set nodes per processor.
373-
set_range(&mut leaf_8000001e.result.ecx, 8..11, NODES_PER_PROCESSOR).unwrap();
367+
set_range(&mut leaf_8000001e.result.ecx, 8..=10, NODES_PER_PROCESSOR).unwrap();
374368

369+
// CPUID Fn8000_001E_ECX[7:0] (Field Name: NodeId)
375370
// Specifies the ID of the node containing the current logical processor. NodeId
376371
// values are unique across the system.
377372
//
378-
// node_id: 0..8,
379-
//
380373
// Put all the cpus in the same node.
381-
set_range(&mut leaf_8000001e.result.ecx, 0..8, 0).unwrap();
374+
set_range(&mut leaf_8000001e.result.ecx, 0..=7, 0).unwrap();
382375

383376
Ok(())
384377
}

0 commit comments

Comments
 (0)