@@ -564,6 +564,7 @@ impl CpuidFeatureEntry {
564564pub fn generate_common_cpuid (
565565 hypervisor : & dyn hypervisor:: Hypervisor ,
566566 config : & CpuidConfig ,
567+ #[ cfg( feature = "tdx" ) ] vm : Option < & dyn hypervisor:: Vm > ,
567568) -> super :: Result < Vec < CpuIdEntry > > {
568569 #[ allow( unused_unsafe) ]
569570 // SAFETY: cpuid called with valid leaves
@@ -634,6 +635,16 @@ pub fn generate_common_cpuid(
634635
635636 CpuidPatch :: patch_cpuid ( & mut cpuid, & cpuid_patches) ;
636637
638+ #[ cfg( feature = "tdx" ) ]
639+ if config. tdx {
640+ let tdx_vm = vm. ok_or_else ( || {
641+ Error :: TdxCapabilities ( HypervisorVmError :: InitializeTdx ( std:: io:: Error :: other (
642+ "Missing VM instance for TDX CPUID generation" ,
643+ ) ) )
644+ } ) ?;
645+ common_cpuid_tdx_configuration ( & mut cpuid, tdx_vm) ?;
646+ }
647+
637648 // Update some existing CPUID
638649 for entry in cpuid. as_mut_slice ( ) . iter_mut ( ) {
639650 #[ allow( unused_unsafe) ]
@@ -648,9 +659,6 @@ pub fn generate_common_cpuid(
648659 entry. edx &= !( 1 << AMX_COMPLEX ) ;
649660 }
650661 }
651- 0xd =>
652- {
653- }
654662 // Tile Information (purely AMX related).
655663 0x1d if !config. amx => {
656664 entry. eax = 0 ;
@@ -792,6 +800,35 @@ pub fn generate_common_cpuid(
792800 Ok ( cpuid)
793801}
794802
803+ #[ cfg( feature = "tdx" ) ]
804+ fn common_cpuid_tdx_configuration (
805+ cpuid : & mut [ CpuIdEntry ] ,
806+ vm : & dyn hypervisor:: Vm ,
807+ ) -> super :: Result < ( ) > {
808+ let caps = vm. tdx_capabilities ( ) . map_err ( Error :: TdxCapabilities ) ?;
809+ debug ! ( "TDX capabilities supported_attrs={:#x} supported_xfam={:#x}" ,
810+ caps. supported_attrs, caps. supported_xfam) ;
811+
812+ // XCR0-managed (user) XSAVE state components. Must include the AMX
813+ // tile state components (XTILECFG bit 17, XTILEDATA bit 18); otherwise
814+ // AMX is stripped from CPUID.0xD.0 and never makes it into the TD XFAM.
815+ // Bits: x87(0) SSE(1) AVX(2) BNDREG(3) BNDCSR(4) OPMASK(5) ZMM_Hi256(6)
816+ // Hi16_ZMM(7) PKRU(9) XTILECFG(17) XTILEDATA(18).
817+ let xcr0_mask: u64 = 0x602ff ;
818+ let xss_mask: u64 = !xcr0_mask;
819+ for entry in cpuid. iter_mut ( ) . filter ( |entry| entry. function == 0xd ) {
820+ if entry. index == 0 {
821+ entry. eax &= ( caps. supported_xfam as u32 ) & ( xcr0_mask as u32 ) ;
822+ entry. edx &= ( ( caps. supported_xfam & xcr0_mask) >> 32 ) as u32 ;
823+ } else if entry. index == 1 {
824+ entry. ecx &= ( caps. supported_xfam as u32 ) & ( xss_mask as u32 ) ;
825+ entry. edx &= ( ( caps. supported_xfam & xss_mask) >> 32 ) as u32 ;
826+ }
827+ }
828+
829+ Ok ( ( ) )
830+ }
831+
795832#[ allow( clippy:: too_many_arguments) ]
796833pub fn configure_vcpu (
797834 vcpu : & dyn hypervisor:: Vcpu ,
0 commit comments