@@ -33,6 +33,8 @@ static enum cpuhp_state tdx_cpuhp_state;
33
33
34
34
static const struct tdx_sys_info * tdx_sysinfo ;
35
35
36
+ #define KVM_SUPPORTED_TD_ATTRS (TDX_TD_ATTR_SEPT_VE_DISABLE)
37
+
36
38
static __always_inline struct kvm_tdx * to_kvm_tdx (struct kvm * kvm )
37
39
{
38
40
return container_of (kvm , struct kvm_tdx , kvm );
@@ -43,6 +45,129 @@ static __always_inline struct vcpu_tdx *to_tdx(struct kvm_vcpu *vcpu)
43
45
return container_of (vcpu , struct vcpu_tdx , vcpu );
44
46
}
45
47
48
+ static u64 tdx_get_supported_attrs (const struct tdx_sys_info_td_conf * td_conf )
49
+ {
50
+ u64 val = KVM_SUPPORTED_TD_ATTRS ;
51
+
52
+ if ((val & td_conf -> attributes_fixed1 ) != td_conf -> attributes_fixed1 )
53
+ return 0 ;
54
+
55
+ val &= td_conf -> attributes_fixed0 ;
56
+
57
+ return val ;
58
+ }
59
+
60
+ static u64 tdx_get_supported_xfam (const struct tdx_sys_info_td_conf * td_conf )
61
+ {
62
+ u64 val = kvm_caps .supported_xcr0 | kvm_caps .supported_xss ;
63
+
64
+ if ((val & td_conf -> xfam_fixed1 ) != td_conf -> xfam_fixed1 )
65
+ return 0 ;
66
+
67
+ val &= td_conf -> xfam_fixed0 ;
68
+
69
+ return val ;
70
+ }
71
+
72
+ static u32 tdx_set_guest_phys_addr_bits (const u32 eax , int addr_bits )
73
+ {
74
+ return (eax & ~GENMASK (23 , 16 )) | (addr_bits & 0xff ) << 16 ;
75
+ }
76
+
77
+ #define KVM_TDX_CPUID_NO_SUBLEAF ((__u32)-1)
78
+
79
+ static void td_init_cpuid_entry2 (struct kvm_cpuid_entry2 * entry , unsigned char idx )
80
+ {
81
+ const struct tdx_sys_info_td_conf * td_conf = & tdx_sysinfo -> td_conf ;
82
+
83
+ entry -> function = (u32 )td_conf -> cpuid_config_leaves [idx ];
84
+ entry -> index = td_conf -> cpuid_config_leaves [idx ] >> 32 ;
85
+ entry -> eax = (u32 )td_conf -> cpuid_config_values [idx ][0 ];
86
+ entry -> ebx = td_conf -> cpuid_config_values [idx ][0 ] >> 32 ;
87
+ entry -> ecx = (u32 )td_conf -> cpuid_config_values [idx ][1 ];
88
+ entry -> edx = td_conf -> cpuid_config_values [idx ][1 ] >> 32 ;
89
+
90
+ if (entry -> index == KVM_TDX_CPUID_NO_SUBLEAF )
91
+ entry -> index = 0 ;
92
+
93
+ /*
94
+ * The TDX module doesn't allow configuring the guest phys addr bits
95
+ * (EAX[23:16]). However, KVM uses it as an interface to the userspace
96
+ * to configure the GPAW. Report these bits as configurable.
97
+ */
98
+ if (entry -> function == 0x80000008 )
99
+ entry -> eax = tdx_set_guest_phys_addr_bits (entry -> eax , 0xff );
100
+ }
101
+
102
+ static int init_kvm_tdx_caps (const struct tdx_sys_info_td_conf * td_conf ,
103
+ struct kvm_tdx_capabilities * caps )
104
+ {
105
+ int i ;
106
+
107
+ caps -> supported_attrs = tdx_get_supported_attrs (td_conf );
108
+ if (!caps -> supported_attrs )
109
+ return - EIO ;
110
+
111
+ caps -> supported_xfam = tdx_get_supported_xfam (td_conf );
112
+ if (!caps -> supported_xfam )
113
+ return - EIO ;
114
+
115
+ caps -> cpuid .nent = td_conf -> num_cpuid_config ;
116
+
117
+ for (i = 0 ; i < td_conf -> num_cpuid_config ; i ++ )
118
+ td_init_cpuid_entry2 (& caps -> cpuid .entries [i ], i );
119
+
120
+ return 0 ;
121
+ }
122
+
123
+ static int tdx_get_capabilities (struct kvm_tdx_cmd * cmd )
124
+ {
125
+ const struct tdx_sys_info_td_conf * td_conf = & tdx_sysinfo -> td_conf ;
126
+ struct kvm_tdx_capabilities __user * user_caps ;
127
+ struct kvm_tdx_capabilities * caps = NULL ;
128
+ int ret = 0 ;
129
+
130
+ /* flags is reserved for future use */
131
+ if (cmd -> flags )
132
+ return - EINVAL ;
133
+
134
+ caps = kmalloc (sizeof (* caps ) +
135
+ sizeof (struct kvm_cpuid_entry2 ) * td_conf -> num_cpuid_config ,
136
+ GFP_KERNEL );
137
+ if (!caps )
138
+ return - ENOMEM ;
139
+
140
+ user_caps = u64_to_user_ptr (cmd -> data );
141
+ if (copy_from_user (caps , user_caps , sizeof (* caps ))) {
142
+ ret = - EFAULT ;
143
+ goto out ;
144
+ }
145
+
146
+ if (caps -> cpuid .nent < td_conf -> num_cpuid_config ) {
147
+ ret = - E2BIG ;
148
+ goto out ;
149
+ }
150
+
151
+ ret = init_kvm_tdx_caps (td_conf , caps );
152
+ if (ret )
153
+ goto out ;
154
+
155
+ if (copy_to_user (user_caps , caps , sizeof (* caps ))) {
156
+ ret = - EFAULT ;
157
+ goto out ;
158
+ }
159
+
160
+ if (copy_to_user (user_caps -> cpuid .entries , caps -> cpuid .entries ,
161
+ caps -> cpuid .nent *
162
+ sizeof (caps -> cpuid .entries [0 ])))
163
+ ret = - EFAULT ;
164
+
165
+ out :
166
+ /* kfree() accepts NULL. */
167
+ kfree (caps );
168
+ return ret ;
169
+ }
170
+
46
171
int tdx_vm_ioctl (struct kvm * kvm , void __user * argp )
47
172
{
48
173
struct kvm_tdx_cmd tdx_cmd ;
@@ -61,6 +186,9 @@ int tdx_vm_ioctl(struct kvm *kvm, void __user *argp)
61
186
mutex_lock (& kvm -> lock );
62
187
63
188
switch (tdx_cmd .id ) {
189
+ case KVM_TDX_CAPABILITIES :
190
+ r = tdx_get_capabilities (& tdx_cmd );
191
+ break ;
64
192
default :
65
193
r = - EINVAL ;
66
194
goto out ;
@@ -160,11 +288,20 @@ static int __init __tdx_bringup(void)
160
288
goto get_sysinfo_err ;
161
289
}
162
290
291
+ /* Check TDX module and KVM capabilities */
292
+ if (!tdx_get_supported_attrs (& tdx_sysinfo -> td_conf ) ||
293
+ !tdx_get_supported_xfam (& tdx_sysinfo -> td_conf ))
294
+ goto get_sysinfo_err ;
295
+
296
+ if (!(tdx_sysinfo -> features .tdx_features0 & MD_FIELD_ID_FEATURES0_TOPOLOGY_ENUM ))
297
+ goto get_sysinfo_err ;
298
+
163
299
/*
164
300
* Leave hardware virtualization enabled after TDX is enabled
165
301
* successfully. TDX CPU hotplug depends on this.
166
302
*/
167
303
return 0 ;
304
+
168
305
get_sysinfo_err :
169
306
__tdx_cleanup ();
170
307
tdx_bringup_err :
0 commit comments