Skip to content

Commit 68f2f2b

Browse files
dcuiliuw
authored andcommitted
Drivers: hv: vmbus: Support fully enlightened TDX guests
Add Hyper-V specific code so that a fully enlightened TDX guest (i.e. without the paravisor) can run on Hyper-V: Don't use hv_vp_assist_page. Use GHCI instead. Don't try to use the unsupported HV_REGISTER_CRASH_CTL. Don't trust (use) Hyper-V's TLB-flushing hypercalls. Don't use lazy EOI. Share the SynIC Event/Message pages with the hypervisor. Don't use the Hyper-V TSC page for now, because non-trivial work is required to share the page with the hypervisor. Reviewed-by: Michael Kelley <mikelley@microsoft.com> Signed-off-by: Dexuan Cui <decui@microsoft.com> Signed-off-by: Wei Liu <wei.liu@kernel.org> Link: https://lore.kernel.org/r/20230824080712.30327-4-decui@microsoft.com
1 parent d6e0228 commit 68f2f2b

File tree

4 files changed

+48
-9
lines changed

4 files changed

+48
-9
lines changed

arch/x86/hyperv/hv_apic.c

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -177,8 +177,11 @@ static bool __send_ipi_mask(const struct cpumask *mask, int vector,
177177
(exclude_self && weight == 1 && cpumask_test_cpu(this_cpu, mask)))
178178
return true;
179179

180-
if (!hv_hypercall_pg)
181-
return false;
180+
/* A fully enlightened TDX VM uses GHCI rather than hv_hypercall_pg. */
181+
if (!hv_hypercall_pg) {
182+
if (ms_hyperv.paravisor_present || !hv_isolation_type_tdx())
183+
return false;
184+
}
182185

183186
if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
184187
return false;
@@ -231,9 +234,15 @@ static bool __send_ipi_one(int cpu, int vector)
231234

232235
trace_hyperv_send_ipi_one(cpu, vector);
233236

234-
if (!hv_hypercall_pg || (vp == VP_INVAL))
237+
if (vp == VP_INVAL)
235238
return false;
236239

240+
/* A fully enlightened TDX VM uses GHCI rather than hv_hypercall_pg. */
241+
if (!hv_hypercall_pg) {
242+
if (ms_hyperv.paravisor_present || !hv_isolation_type_tdx())
243+
return false;
244+
}
245+
237246
if ((vector < HV_IPI_LOW_VECTOR) || (vector > HV_IPI_HIGH_VECTOR))
238247
return false;
239248

arch/x86/hyperv/hv_init.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ static int hyperv_init_ghcb(void)
8080
static int hv_cpu_init(unsigned int cpu)
8181
{
8282
union hv_vp_assist_msr_contents msr = { 0 };
83-
struct hv_vp_assist_page **hvp = &hv_vp_assist_page[cpu];
83+
struct hv_vp_assist_page **hvp;
8484
int ret;
8585

8686
ret = hv_common_cpu_init(cpu);
@@ -90,6 +90,7 @@ static int hv_cpu_init(unsigned int cpu)
9090
if (!hv_vp_assist_page)
9191
return 0;
9292

93+
hvp = &hv_vp_assist_page[cpu];
9394
if (hv_root_partition) {
9495
/*
9596
* For root partition we get the hypervisor provided VP assist
@@ -442,11 +443,21 @@ void __init hyperv_init(void)
442443
if (hv_common_init())
443444
return;
444445

445-
hv_vp_assist_page = kcalloc(num_possible_cpus(),
446-
sizeof(*hv_vp_assist_page), GFP_KERNEL);
446+
/*
447+
* The VP assist page is useless to a TDX guest: the only use we
448+
* would have for it is lazy EOI, which can not be used with TDX.
449+
*/
450+
if (hv_isolation_type_tdx())
451+
hv_vp_assist_page = NULL;
452+
else
453+
hv_vp_assist_page = kcalloc(num_possible_cpus(),
454+
sizeof(*hv_vp_assist_page),
455+
GFP_KERNEL);
447456
if (!hv_vp_assist_page) {
448457
ms_hyperv.hints &= ~HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
449-
goto common_free;
458+
459+
if (!hv_isolation_type_tdx())
460+
goto common_free;
450461
}
451462

452463
if (hv_isolation_type_snp()) {

arch/x86/kernel/cpu/mshyperv.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -420,6 +420,20 @@ static void __init ms_hyperv_init_platform(void)
420420
static_branch_enable(&isolation_type_en_snp);
421421
} else if (hv_get_isolation_type() == HV_ISOLATION_TYPE_TDX) {
422422
static_branch_enable(&isolation_type_tdx);
423+
424+
/* A TDX VM must use x2APIC and doesn't use lazy EOI. */
425+
ms_hyperv.hints &= ~HV_X64_APIC_ACCESS_RECOMMENDED;
426+
427+
if (!ms_hyperv.paravisor_present) {
428+
/* To be supported: more work is required. */
429+
ms_hyperv.features &= ~HV_MSR_REFERENCE_TSC_AVAILABLE;
430+
431+
/* HV_REGISTER_CRASH_CTL is unsupported. */
432+
ms_hyperv.misc_features &= ~HV_FEATURE_GUEST_CRASH_MSR_AVAILABLE;
433+
434+
/* Don't trust Hyper-V's TLB-flushing hypercalls. */
435+
ms_hyperv.hints &= ~HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED;
436+
}
423437
}
424438
}
425439

drivers/hv/hv.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,15 @@ int hv_synic_alloc(void)
121121
(void *)get_zeroed_page(GFP_ATOMIC);
122122
if (hv_cpu->synic_event_page == NULL) {
123123
pr_err("Unable to allocate SYNIC event page\n");
124+
125+
free_page((unsigned long)hv_cpu->synic_message_page);
126+
hv_cpu->synic_message_page = NULL;
124127
goto err;
125128
}
126129
}
127130

128-
if (hv_isolation_type_en_snp()) {
131+
if (!ms_hyperv.paravisor_present &&
132+
(hv_isolation_type_en_snp() || hv_isolation_type_tdx())) {
129133
ret = set_memory_decrypted((unsigned long)
130134
hv_cpu->synic_message_page, 1);
131135
if (ret) {
@@ -174,7 +178,8 @@ void hv_synic_free(void)
174178
= per_cpu_ptr(hv_context.cpu_context, cpu);
175179

176180
/* It's better to leak the page if the encryption fails. */
177-
if (hv_isolation_type_en_snp()) {
181+
if (!ms_hyperv.paravisor_present &&
182+
(hv_isolation_type_en_snp() || hv_isolation_type_tdx())) {
178183
if (hv_cpu->synic_message_page) {
179184
ret = set_memory_encrypted((unsigned long)
180185
hv_cpu->synic_message_page, 1);

0 commit comments

Comments
 (0)