1212// See the License for the specific language governing permissions and
1313// limitations under the License.
1414
15+ use std:: arch:: x86_64:: CpuidResult ;
16+ use std:: collections:: HashMap ;
17+ use std:: mem:: MaybeUninit ;
18+
19+ use crate :: arch:: cpuid:: CpuidIn ;
20+ use crate :: arch:: tdx:: TdAttr ;
1521use crate :: hv:: Result ;
22+ use crate :: hv:: kvm:: tdx:: tdx_op;
1623use crate :: hv:: kvm:: vm:: KvmVm ;
17- use crate :: sys:: kvm:: { KvmCap , KvmHypercall } ;
24+ use crate :: sys:: kvm:: { KvmCap , KvmCpuid2Flag , KvmCpuidEntry2 , KvmHypercall } ;
25+ use crate :: sys:: tdx:: { KvmTdxCapabilities , KvmTdxCmdId , KvmTdxInitVm } ;
1826
1927impl KvmVm {
2028 pub fn tdx_init ( & self ) -> Result < ( ) > {
@@ -23,4 +31,55 @@ impl KvmVm {
2331 self . vm . enable_cap ( KvmCap :: X86_APIC_BUS_CYCLES_NS , 40 ) ?;
2432 Ok ( ( ) )
2533 }
34+
35+ fn tdx_get_capabilities ( & self ) -> Result < Box < KvmTdxCapabilities > > {
36+ let mut caps: Box < KvmTdxCapabilities > =
37+ Box :: new ( unsafe { MaybeUninit :: zeroed ( ) . assume_init ( ) } ) ;
38+ caps. cpuid . nent = caps. cpuid . entries . len ( ) as u32 ;
39+ tdx_op ( & self . vm . fd , KvmTdxCmdId :: CAPABILITIES , 0 , Some ( & mut * caps) ) ?;
40+ Ok ( caps)
41+ }
42+
43+ pub fn tdx_init_vm ( & self , attr : TdAttr , cpuids : & HashMap < CpuidIn , CpuidResult > ) -> Result < ( ) > {
44+ let mut init: Box < KvmTdxInitVm > = Box :: new ( unsafe { MaybeUninit :: zeroed ( ) . assume_init ( ) } ) ;
45+ init. attributes = attr;
46+
47+ let caps = self . tdx_get_capabilities ( ) ?;
48+ let convert = |e : & KvmCpuidEntry2 | {
49+ let ( mut in_, out) = From :: from ( * e) ;
50+ if in_. index . is_none ( ) {
51+ in_. index = Some ( 0 )
52+ }
53+ ( in_, out)
54+ } ;
55+ let caps_cpuid = caps. cpuid . entries . iter ( ) . take ( caps. cpuid . nent as usize ) ;
56+ let caps_cpuid: HashMap < _ , _ > = caps_cpuid. map ( convert) . collect ( ) ;
57+ for ( in_, out) in cpuids {
58+ let cap_cpuid_in = CpuidIn {
59+ func : in_. func ,
60+ index : in_. index . or ( Some ( 0 ) ) ,
61+ } ;
62+ let Some ( cap_out) = caps_cpuid. get ( & cap_cpuid_in) else {
63+ continue ;
64+ } ;
65+
66+ let entry = & mut init. cpuid . entries [ init. cpuid . nent as usize ] ;
67+ entry. function = in_. func ;
68+ entry. index = in_. index . unwrap_or ( 0 ) ;
69+ entry. flags = if in_. index . is_some ( ) {
70+ KvmCpuid2Flag :: SIGNIFCANT_INDEX
71+ } else {
72+ KvmCpuid2Flag :: empty ( )
73+ } ;
74+ entry. eax = out. eax & cap_out. eax ;
75+ entry. ebx = out. ebx & cap_out. ebx ;
76+ entry. ecx = out. ecx & cap_out. ecx ;
77+ entry. edx = out. edx & cap_out. edx ;
78+
79+ init. cpuid . nent += 1 ;
80+ }
81+
82+ tdx_op ( & self . vm . fd , KvmTdxCmdId :: INIT_VM , 0 , Some ( & mut * init) ) ?;
83+ Ok ( ( ) )
84+ }
2685}
0 commit comments