@@ -104,6 +104,12 @@ pub fn functionally_same(base: CpuIdDump, target: CpuIdDump) -> bool {
104
104
if base_info. has_fp256 ( ) != target_info. has_fp256 ( ) {
105
105
return false ;
106
106
}
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
+ }
107
113
}
108
114
_ => {
109
115
// Specific cases here may be acceptable, but for expediency (and
@@ -500,8 +506,8 @@ fn milan_ideal() -> CpuIdDump {
500
506
501
507
// Set up processor optimization info (leaf 8000_001Ah)
502
508
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 ) ;
505
511
cpuid
506
512
. set_performance_optimization_info ( Some ( leaf) )
507
513
. expect ( "can set leaf 8000_001Ah" ) ;
@@ -555,11 +561,21 @@ pub fn turin_v1() -> CpuIdDump {
555
561
556
562
let mut cpuid = CpuId :: with_cpuid_reader ( baseline) ;
557
563
558
- let mut leaf = cpuid. get_extended_feature_info ( )
564
+ let mut leaf = cpuid
565
+ . get_extended_feature_info ( )
559
566
. expect ( "baseline Milan defines leaf 7" ) ;
560
567
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.
563
579
leaf. set_avx512f ( true ) ;
564
580
leaf. set_avx512dq ( true ) ;
565
581
leaf. set_avx512_ifma ( true ) ;
@@ -573,20 +589,77 @@ pub fn turin_v1() -> CpuIdDump {
573
589
leaf. set_avx512vnni ( true ) ;
574
590
leaf. set_avx512bitalg ( true ) ;
575
591
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 ) ;
576
597
577
598
leaf. set_avx512_bf16 ( true ) ;
578
599
leaf. set_avx_vnni ( true ) ;
579
600
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" ) ;
582
654
583
655
let mut leaf = cpuid
584
656
. get_extended_processor_and_feature_identifiers ( )
585
657
. expect ( "baseline Milan defines leaf 8000_0001" ) ;
586
658
// RDTSCP requires some bhyve and Propolis work to support, so it is masked
587
659
// off for now.
588
660
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) )
590
663
. expect ( "can set leaf 8000_0001h" ) ;
591
664
592
665
cpuid
@@ -602,10 +675,57 @@ pub fn turin_v1() -> CpuIdDump {
602
675
// hiding this instruction.
603
676
leaf. set_wbnoinvd ( false ) ;
604
677
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
+
605
691
cpuid
606
692
. set_processor_capacity_feature_info ( Some ( leaf) )
607
693
. expect ( "can set leaf 8000_0008h" ) ;
608
694
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
+
609
729
// Cache topology leaves are otherwise left zeroed; if we can avoid getting
610
730
// into it, let's try!
611
731
@@ -817,7 +937,7 @@ pub fn dump_to_cpuid_entries(dump: CpuIdDump) -> Vec<CpuidEntry> {
817
937
#[ cfg( test) ]
818
938
mod test {
819
939
use crate :: app:: instance_platform:: cpu_platform:: {
820
- dump_to_cpuid_entries, milan_rfd314,
940
+ dump_to_cpuid_entries, milan_rfd314, turin_v1 ,
821
941
} ;
822
942
use raw_cpuid:: {
823
943
CpuId , CpuIdReader , CpuIdResult , CpuIdWriter , L1CacheTlbInfo ,
@@ -910,6 +1030,77 @@ mod test {
910
1030
cpuid_leaf ! ( 0x80000021 , 0x00000045 , 0x00000000 , 0x00000000 , 0x00000000 ) ,
911
1031
] ;
912
1032
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
+
913
1104
// Test that the initial RFD 314 definition matches what we compute as the
914
1105
// CPUID profile with that configuration in `milan_rfd314()`.
915
1106
#[ test]
0 commit comments