Skip to content

Commit d5727cc

Browse files
committed
refine Turin bits after more careful comparison APM and PPRs
1 parent 026aa96 commit d5727cc

File tree

3 files changed

+202
-11
lines changed

3 files changed

+202
-11
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -658,7 +658,7 @@ rand_distr = "0.5.1"
658658
rand_seeder = "0.4.0"
659659
range-requests = { path = "range-requests" }
660660
ratatui = "0.29.0"
661-
raw-cpuid = { git = "https://github.com/oxidecomputer/rust-cpuid.git", rev = "8bdf76bfaa45bc30e944f8409d40f9edc7d62423" }
661+
raw-cpuid = { git = "https://github.com/oxidecomputer/rust-cpuid.git", rev = "a4cf01df76f35430ff5d39dc2fe470bcb953503b" }
662662
rayon = "1.10"
663663
rcgen = "0.12.1"
664664
reconfigurator-cli = { path = "dev-tools/reconfigurator-cli" }

nexus/src/app/instance_platform/cpu_platform.rs

Lines changed: 200 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,12 @@ pub fn functionally_same(base: CpuIdDump, target: CpuIdDump) -> bool {
104104
if base_info.has_fp256() != target_info.has_fp256() {
105105
return false;
106106
}
107+
108+
// TODO: same as above: we probably just need to require "base" has
109+
// the same or wider FPU datapath than "target"
110+
if base_info.has_fp512() != target_info.has_fp512() {
111+
return false;
112+
}
107113
}
108114
_ => {
109115
// Specific cases here may be acceptable, but for expediency (and
@@ -500,8 +506,8 @@ fn milan_ideal() -> CpuIdDump {
500506

501507
// Set up processor optimization info (leaf 8000_001Ah)
502508
let mut leaf = PerformanceOptimizationInfo::empty();
503-
leaf.set_movu(true); // TODO: BREAKING
504-
leaf.set_fp256(true); // TODO: BREAKINGISH?
509+
leaf.set_movu(true);
510+
leaf.set_fp256(true);
505511
cpuid
506512
.set_performance_optimization_info(Some(leaf))
507513
.expect("can set leaf 8000_001Ah");
@@ -555,11 +561,21 @@ pub fn turin_v1() -> CpuIdDump {
555561

556562
let mut cpuid = CpuId::with_cpuid_reader(baseline);
557563

558-
let mut leaf = cpuid.get_extended_feature_info()
564+
let mut leaf = cpuid
565+
.get_extended_feature_info()
559566
.expect("baseline Milan defines leaf 7");
560567

561-
// These are the AVX512 features present on a 9365, when I'd looked in
562-
// September, anyway
568+
// Turin supports the TSC_ADJUST MSR but guest plumbing is not present for
569+
// it and it's not clear what a guest would productively do with it anyway.
570+
leaf.set_tsc_adjust_msr(false);
571+
572+
// Turin supports MOVDIR64B and MOVDIRI. These instructions should just work
573+
// in guests, but it would be nice to test this before committing to passing
574+
// them.
575+
leaf.set_movdir64b(false);
576+
leaf.set_movdiri(false);
577+
578+
// These AVX512 features are present for all Turin processors.
563579
leaf.set_avx512f(true);
564580
leaf.set_avx512dq(true);
565581
leaf.set_avx512_ifma(true);
@@ -573,20 +589,77 @@ pub fn turin_v1() -> CpuIdDump {
573589
leaf.set_avx512vnni(true);
574590
leaf.set_avx512bitalg(true);
575591
leaf.set_avx512vpopcntdq(true);
592+
// While hardware supports 57-bit virtual addresses, the bhyve support is
593+
// not there yet.
594+
leaf.set_la57(false);
595+
596+
leaf.set_avx512_vp2intersect(true);
576597

577598
leaf.set_avx512_bf16(true);
578599
leaf.set_avx_vnni(true);
579600

580-
cpuid.set_extended_feature_info(Some(leaf))
581-
.expect("can set leaf 7h");
601+
cpuid.set_extended_feature_info(Some(leaf)).expect("can set leaf 7h");
602+
603+
// This is the same information for leaf D as in Milan, but with the new
604+
// AVX-512 bits in Turin.
605+
// TODO: kind of gross to have to pass an empty `CpuIdDump` here...
606+
let mut state = ExtendedStateInfo::empty(CpuIdDump::new());
607+
state.set_xcr0_supports_legacy_x87(true);
608+
state.set_xcr0_supports_sse_128(true);
609+
state.set_xcr0_supports_avx_256(true);
610+
// Update leaf D for the larger XCR0 set
611+
state.set_xcr0_supports_avx512_opmask(true);
612+
state.set_xcr0_supports_avx512_zmm_hi256(true);
613+
state.set_xcr0_supports_avx512_zmm_hi16(true);
614+
// Managed dynamically in practice.
615+
state.set_xsave_area_size_enabled_features(0x980);
616+
// `Core::X86::Cpuid::ProcExtStateEnumEcx00`, but minus the MPK support we
617+
// don't make available to guests.
618+
state.set_xsave_area_size_supported_features(0x980);
619+
620+
state.set_xsaveopt(true);
621+
state.set_xsavec(true);
622+
state.set_xgetbv(true);
623+
state.set_xsave_size(0x980);
624+
625+
let mut leaves = state.into_leaves().to_vec();
626+
let mut ymm_state = ExtendedState::empty();
627+
ymm_state.set_size(0x100);
628+
ymm_state.set_offset(0x240);
629+
leaves.push(Some(ymm_state.into_leaf()));
630+
// level 3
631+
leaves.push(None);
632+
// level 4
633+
leaves.push(None);
634+
// levels 5, 6, and 7 are described in the PPR:
635+
// `Core::X86::Cpuid::ProcExtStateEnumEax06`
636+
//
637+
// level 5
638+
let mut kregs_state = ExtendedState::empty();
639+
kregs_state.set_size(0x040);
640+
kregs_state.set_offset(0x340);
641+
leaves.push(Some(kregs_state.into_leaf()));
642+
// level 6
643+
let mut zmmhi_state = ExtendedState::empty();
644+
zmmhi_state.set_size(0x200);
645+
zmmhi_state.set_offset(0x380);
646+
leaves.push(Some(zmmhi_state.into_leaf()));
647+
// level 7
648+
let mut zmmhi16_state = ExtendedState::empty();
649+
zmmhi16_state.set_size(0x400);
650+
zmmhi16_state.set_offset(0x580);
651+
leaves.push(Some(zmmhi16_state.into_leaf()));
652+
653+
cpuid.set_extended_state_info(Some(&leaves[..])).expect("can set leaf Dh");
582654

583655
let mut leaf = cpuid
584656
.get_extended_processor_and_feature_identifiers()
585657
.expect("baseline Milan defines leaf 8000_0001");
586658
// RDTSCP requires some bhyve and Propolis work to support, so it is masked
587659
// off for now.
588660
leaf.set_rdtscp(false);
589-
cpuid.set_extended_processor_and_feature_identifiers(Some(leaf))
661+
cpuid
662+
.set_extended_processor_and_feature_identifiers(Some(leaf))
590663
.expect("can set leaf 8000_0001h");
591664

592665
cpuid
@@ -602,10 +675,57 @@ pub fn turin_v1() -> CpuIdDump {
602675
// hiding this instruction.
603676
leaf.set_wbnoinvd(false);
604677

678+
// "Processor is not vulnerable to Branch Type Confusion"
679+
// This is 1 for all Turin processors and does not require particular MSR
680+
// settings or hypervisor support, so pass it along.
681+
leaf.set_btc_no(true);
682+
683+
// BSFD, SSBD, STIBP, and IBRS, are all supported on Turin, but guests
684+
// are not yet allowed to access SPEC_CTRL to enable (or confirm they are
685+
// enabled).
686+
leaf.set_psfd(false);
687+
leaf.set_ssbd(false);
688+
leaf.set_stibp(false);
689+
leaf.set_ibrs(false);
690+
605691
cpuid
606692
.set_processor_capacity_feature_info(Some(leaf))
607693
.expect("can set leaf 8000_0008h");
608694

695+
let mut leaf = cpuid
696+
.get_performance_optimization_info()
697+
.expect("baseline Milan defines 8000_001Ah");
698+
leaf.set_fp256(false);
699+
leaf.set_fp512(true);
700+
cpuid
701+
.set_performance_optimization_info(Some(leaf))
702+
.expect("can set leaf 8000_001Ah");
703+
704+
let mut leaf = cpuid
705+
.get_extended_feature_identification_2()
706+
.expect("can get leaf 8000_0021h");
707+
708+
// FP512 downgrade is configurable via MSR, but the MSR is not made
709+
// available to guests. The other bits are present on all Turin processors.
710+
leaf.set_fp512_downgrade(false);
711+
leaf.set_fast_rep_scasb(true);
712+
leaf.set_epsf(true);
713+
leaf.set_opcode_0f_017_reclaim(true);
714+
leaf.set_amd_ermsb(true);
715+
leaf.set_fast_short_repe_cmpsb(true);
716+
leaf.set_fast_short_rep_stosb(true);
717+
// The EFER write is permitted in bhyve, so this *should* work?
718+
leaf.set_automatic_ibrs(true);
719+
// The EFER write is permitted in bhyve, so this *should* work? But the
720+
// forward utility of this bit is not as clear, so hide it.
721+
leaf.set_upper_address_ignore(false);
722+
// Architectural behavior, so we should pass this through.
723+
leaf.set_fs_gs_base_write_not_serializing(true);
724+
725+
cpuid
726+
.set_extended_feature_identification_2(Some(leaf))
727+
.expect("can set leaf 8000_0021h");
728+
609729
// Cache topology leaves are otherwise left zeroed; if we can avoid getting
610730
// into it, let's try!
611731

@@ -817,7 +937,7 @@ pub fn dump_to_cpuid_entries(dump: CpuIdDump) -> Vec<CpuidEntry> {
817937
#[cfg(test)]
818938
mod test {
819939
use crate::app::instance_platform::cpu_platform::{
820-
dump_to_cpuid_entries, milan_rfd314,
940+
dump_to_cpuid_entries, milan_rfd314, turin_v1,
821941
};
822942
use raw_cpuid::{
823943
CpuId, CpuIdReader, CpuIdResult, CpuIdWriter, L1CacheTlbInfo,
@@ -910,6 +1030,77 @@ mod test {
9101030
cpuid_leaf!(0x80000021, 0x00000045, 0x00000000, 0x00000000, 0x00000000),
9111031
];
9121032

1033+
// This CPUID leaf blob is some small tweaks on top of the "ideal Milan",
1034+
// maintaining some details that are disabled due to needed bhyve support
1035+
// and including Turin-specific features as supported and relevant to
1036+
// guests.
1037+
const TURIN_V1_CPUID: [CpuidEntry; 26] = [
1038+
cpuid_leaf!(0x0, 0x0000000D, 0x68747541, 0x444D4163, 0x69746E65),
1039+
cpuid_leaf!(0x1, 0x00A00F11, 0x00000800, 0xF6D83203, 0x078BFBFF),
1040+
cpuid_leaf!(0x5, 0x00000000, 0x00000000, 0x00000000, 0x00000000),
1041+
cpuid_leaf!(0x6, 0x00000004, 0x00000000, 0x00000000, 0x00000000),
1042+
cpuid_subleaf!(
1043+
0x7, 0x0, 0x00000001, 0xF1BF03A9, 0x00005F42, 0x00000110
1044+
),
1045+
cpuid_subleaf!(
1046+
0x7, 0x1, 0x00000030, 0x00000000, 0x00000000, 0x00000000
1047+
),
1048+
cpuid_subleaf!(
1049+
0xD, 0x0, 0x000000E7, 0x00000980, 0x00000980, 0x00000000
1050+
),
1051+
cpuid_subleaf!(
1052+
0xD, 0x1, 0x00000007, 0x00000980, 0x00000000, 0x00000000
1053+
),
1054+
cpuid_subleaf!(
1055+
0xD, 0x2, 0x00000100, 0x00000240, 0x00000000, 0x00000000
1056+
),
1057+
/*
1058+
* subleaves 3 and 4 are all-zero
1059+
*/
1060+
cpuid_subleaf!(
1061+
0xD, 0x5, 0x00000040, 0x00000340, 0x00000000, 0x00000000
1062+
),
1063+
cpuid_subleaf!(
1064+
0xD, 0x6, 0x00000200, 0x00000380, 0x00000000, 0x00000000
1065+
),
1066+
cpuid_subleaf!(
1067+
0xD, 0x7, 0x00000400, 0x00000580, 0x00000000, 0x00000000
1068+
),
1069+
cpuid_leaf!(0x80000000, 0x80000021, 0x68747541, 0x444D4163, 0x69746E65),
1070+
cpuid_leaf!(0x80000001, 0x00A00F11, 0x40000000, 0x44C001F1, 0x25D3FBFF),
1071+
cpuid_leaf!(0x80000002, 0x6469784F, 0x69562065, 0x61757472, 0x7554206C),
1072+
cpuid_leaf!(0x80000003, 0x2D6E6972, 0x656B696C, 0x6F725020, 0x73736563),
1073+
cpuid_leaf!(0x80000004, 0x2020726F, 0x20202020, 0x20202020, 0x00202020),
1074+
cpuid_leaf!(0x80000007, 0x00000000, 0x00000000, 0x00000000, 0x00000100),
1075+
cpuid_leaf!(0x80000008, 0x00003030, 0x20000005, 0x00000000, 0x00000000),
1076+
cpuid_leaf!(0x8000000A, 0x00000000, 0x00000000, 0x00000000, 0x00000000),
1077+
cpuid_leaf!(0x8000001A, 0x0000000A, 0x00000000, 0x00000000, 0x00000000),
1078+
cpuid_leaf!(0x8000001B, 0x00000000, 0x00000000, 0x00000000, 0x00000000),
1079+
cpuid_leaf!(0x8000001C, 0x00000000, 0x00000000, 0x00000000, 0x00000000),
1080+
cpuid_leaf!(0x8000001E, 0x00000000, 0x00000100, 0x00000000, 0x00000000),
1081+
cpuid_leaf!(0x8000001F, 0x00000000, 0x00000000, 0x00000000, 0x00000000),
1082+
cpuid_leaf!(0x80000021, 0x000D8D47, 0x00000000, 0x00000000, 0x00000000),
1083+
];
1084+
1085+
// Test that Turin V1 matches the predetermined CPUID leaves written above
1086+
// (e.g. that the collection of builders behind `turin_v1` produce this
1087+
// profile as used for testing and elsewhere).
1088+
//
1089+
// This is largely "baseline Milan" with Turin-specific additions.
1090+
#[test]
1091+
fn turin_v1_is_as_described() {
1092+
let computed = dump_to_cpuid_entries(turin_v1());
1093+
1094+
for (l, r) in TURIN_V1_CPUID.iter().zip(computed.as_slice().iter()) {
1095+
eprintln!("comparing {:#08x}.{:?}", l.leaf, l.subleaf);
1096+
assert_eq!(
1097+
l, r,
1098+
"leaf 0x{:08x} (subleaf? {:?}) did not match",
1099+
l.leaf, l.subleaf
1100+
);
1101+
}
1102+
}
1103+
9131104
// Test that the initial RFD 314 definition matches what we compute as the
9141105
// CPUID profile with that configuration in `milan_rfd314()`.
9151106
#[test]

0 commit comments

Comments
 (0)