Skip to content

Commit b9b4fe3

Browse files
dcuiliuw
authored andcommitted
x86/hyperv: Use TDX GHCI to access some MSRs in a TDX VM with the paravisor
When the paravisor is present, a SNP VM must use GHCB to access some special MSRs, including HV_X64_MSR_GUEST_OS_ID and some SynIC MSRs. Similarly, when the paravisor is present, a TDX VM must use TDX GHCI to access the same MSRs. Implement hv_tdx_msr_write() and hv_tdx_msr_read(), and use the helper functions hv_ivm_msr_read() and hv_ivm_msr_write() to access the MSRs in a unified way for SNP/TDX VMs with the paravisor. Do not export hv_tdx_msr_write() and hv_tdx_msr_read(), because we never really used hv_ghcb_msr_write() and hv_ghcb_msr_read() in any module. Update arch/x86/include/asm/mshyperv.h so that the kernel can still build if CONFIG_AMD_MEM_ENCRYPT or CONFIG_INTEL_TDX_GUEST is not set, or neither is set. Signed-off-by: Dexuan Cui <decui@microsoft.com> Reviewed-by: Tianyu Lan <tiala@microsoft.com> Reviewed-by: Michael Kelley <mikelley@microsoft.com> Signed-off-by: Wei Liu <wei.liu@kernel.org> Link: https://lore.kernel.org/r/20230824080712.30327-9-decui@microsoft.com
1 parent 2337829 commit b9b4fe3

File tree

4 files changed

+77
-16
lines changed

4 files changed

+77
-16
lines changed

arch/x86/hyperv/hv_init.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -500,8 +500,8 @@ void __init hyperv_init(void)
500500
guest_id = hv_generate_guest_id(LINUX_VERSION_CODE);
501501
wrmsrl(HV_X64_MSR_GUEST_OS_ID, guest_id);
502502

503-
/* Hyper-V requires to write guest os id via ghcb in SNP IVM. */
504-
hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID, guest_id);
503+
/* With the paravisor, the VM must also write the ID via GHCB/GHCI */
504+
hv_ivm_msr_write(HV_X64_MSR_GUEST_OS_ID, guest_id);
505505

506506
/* A TDX VM with no paravisor only uses TDX GHCI rather than hv_hypercall_pg */
507507
if (hv_isolation_type_tdx() && !ms_hyperv.paravisor_present)
@@ -590,7 +590,7 @@ void __init hyperv_init(void)
590590

591591
clean_guest_os_id:
592592
wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
593-
hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID, 0);
593+
hv_ivm_msr_write(HV_X64_MSR_GUEST_OS_ID, 0);
594594
cpuhp_remove_state(cpuhp);
595595
free_ghcb_page:
596596
free_percpu(hv_ghcb_pg);
@@ -611,7 +611,7 @@ void hyperv_cleanup(void)
611611

612612
/* Reset our OS id */
613613
wrmsrl(HV_X64_MSR_GUEST_OS_ID, 0);
614-
hv_ghcb_msr_write(HV_X64_MSR_GUEST_OS_ID, 0);
614+
hv_ivm_msr_write(HV_X64_MSR_GUEST_OS_ID, 0);
615615

616616
/*
617617
* Reset hypercall page reference before reset the page,

arch/x86/hyperv/ivm.c

Lines changed: 65 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include <asm/realmode.h>
2525
#include <asm/e820/api.h>
2626
#include <asm/desc.h>
27+
#include <uapi/asm/vmx.h>
2728

2829
#ifdef CONFIG_AMD_MEM_ENCRYPT
2930

@@ -186,7 +187,7 @@ bool hv_ghcb_negotiate_protocol(void)
186187
return true;
187188
}
188189

189-
void hv_ghcb_msr_write(u64 msr, u64 value)
190+
static void hv_ghcb_msr_write(u64 msr, u64 value)
190191
{
191192
union hv_ghcb *hv_ghcb;
192193
void **ghcb_base;
@@ -214,9 +215,8 @@ void hv_ghcb_msr_write(u64 msr, u64 value)
214215

215216
local_irq_restore(flags);
216217
}
217-
EXPORT_SYMBOL_GPL(hv_ghcb_msr_write);
218218

219-
void hv_ghcb_msr_read(u64 msr, u64 *value)
219+
static void hv_ghcb_msr_read(u64 msr, u64 *value)
220220
{
221221
union hv_ghcb *hv_ghcb;
222222
void **ghcb_base;
@@ -246,10 +246,71 @@ void hv_ghcb_msr_read(u64 msr, u64 *value)
246246
| ((u64)lower_32_bits(hv_ghcb->ghcb.save.rdx) << 32);
247247
local_irq_restore(flags);
248248
}
249-
EXPORT_SYMBOL_GPL(hv_ghcb_msr_read);
250249

250+
#else
251+
static inline void hv_ghcb_msr_write(u64 msr, u64 value) {}
252+
static inline void hv_ghcb_msr_read(u64 msr, u64 *value) {}
251253
#endif /* CONFIG_AMD_MEM_ENCRYPT */
252254

255+
#ifdef CONFIG_INTEL_TDX_GUEST
256+
static void hv_tdx_msr_write(u64 msr, u64 val)
257+
{
258+
struct tdx_hypercall_args args = {
259+
.r10 = TDX_HYPERCALL_STANDARD,
260+
.r11 = EXIT_REASON_MSR_WRITE,
261+
.r12 = msr,
262+
.r13 = val,
263+
};
264+
265+
u64 ret = __tdx_hypercall(&args);
266+
267+
WARN_ONCE(ret, "Failed to emulate MSR write: %lld\n", ret);
268+
}
269+
270+
static void hv_tdx_msr_read(u64 msr, u64 *val)
271+
{
272+
struct tdx_hypercall_args args = {
273+
.r10 = TDX_HYPERCALL_STANDARD,
274+
.r11 = EXIT_REASON_MSR_READ,
275+
.r12 = msr,
276+
};
277+
278+
u64 ret = __tdx_hypercall_ret(&args);
279+
280+
if (WARN_ONCE(ret, "Failed to emulate MSR read: %lld\n", ret))
281+
*val = 0;
282+
else
283+
*val = args.r11;
284+
}
285+
#else
286+
static inline void hv_tdx_msr_write(u64 msr, u64 value) {}
287+
static inline void hv_tdx_msr_read(u64 msr, u64 *value) {}
288+
#endif /* CONFIG_INTEL_TDX_GUEST */
289+
290+
#if defined(CONFIG_AMD_MEM_ENCRYPT) || defined(CONFIG_INTEL_TDX_GUEST)
291+
void hv_ivm_msr_write(u64 msr, u64 value)
292+
{
293+
if (!ms_hyperv.paravisor_present)
294+
return;
295+
296+
if (hv_isolation_type_tdx())
297+
hv_tdx_msr_write(msr, value);
298+
else if (hv_isolation_type_snp())
299+
hv_ghcb_msr_write(msr, value);
300+
}
301+
302+
void hv_ivm_msr_read(u64 msr, u64 *value)
303+
{
304+
if (!ms_hyperv.paravisor_present)
305+
return;
306+
307+
if (hv_isolation_type_tdx())
308+
hv_tdx_msr_read(msr, value);
309+
else if (hv_isolation_type_snp())
310+
hv_ghcb_msr_read(msr, value);
311+
}
312+
#endif
313+
253314
#if defined(CONFIG_AMD_MEM_ENCRYPT) || defined(CONFIG_INTEL_TDX_GUEST)
254315
/*
255316
* hv_mark_gpa_visibility - Set pages visible to host via hvcall.

arch/x86/include/asm/mshyperv.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -275,14 +275,10 @@ int hv_map_ioapic_interrupt(int ioapic_id, bool level, int vcpu, int vector,
275275
int hv_unmap_ioapic_interrupt(int ioapic_id, struct hv_interrupt_entry *entry);
276276

277277
#ifdef CONFIG_AMD_MEM_ENCRYPT
278-
void hv_ghcb_msr_write(u64 msr, u64 value);
279-
void hv_ghcb_msr_read(u64 msr, u64 *value);
280278
bool hv_ghcb_negotiate_protocol(void);
281279
void __noreturn hv_ghcb_terminate(unsigned int set, unsigned int reason);
282280
int hv_snp_boot_ap(int cpu, unsigned long start_ip);
283281
#else
284-
static inline void hv_ghcb_msr_write(u64 msr, u64 value) {}
285-
static inline void hv_ghcb_msr_read(u64 msr, u64 *value) {}
286282
static inline bool hv_ghcb_negotiate_protocol(void) { return false; }
287283
static inline void hv_ghcb_terminate(unsigned int set, unsigned int reason) {}
288284
static inline int hv_snp_boot_ap(int cpu, unsigned long start_ip) { return 0; }
@@ -292,8 +288,12 @@ extern bool hv_isolation_type_snp(void);
292288

293289
#if defined(CONFIG_AMD_MEM_ENCRYPT) || defined(CONFIG_INTEL_TDX_GUEST)
294290
void hv_vtom_init(void);
291+
void hv_ivm_msr_write(u64 msr, u64 value);
292+
void hv_ivm_msr_read(u64 msr, u64 *value);
295293
#else
296294
static inline void hv_vtom_init(void) {}
295+
static inline void hv_ivm_msr_write(u64 msr, u64 value) {}
296+
static inline void hv_ivm_msr_read(u64 msr, u64 *value) {}
297297
#endif
298298

299299
static inline bool hv_is_synic_reg(unsigned int reg)

arch/x86/kernel/cpu/mshyperv.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ u64 hv_get_non_nested_register(unsigned int reg)
7070
{
7171
u64 value;
7272

73-
if (hv_is_synic_reg(reg) && hv_isolation_type_snp())
74-
hv_ghcb_msr_read(reg, &value);
73+
if (hv_is_synic_reg(reg) && ms_hyperv.paravisor_present)
74+
hv_ivm_msr_read(reg, &value);
7575
else
7676
rdmsrl(reg, value);
7777
return value;
@@ -80,8 +80,8 @@ EXPORT_SYMBOL_GPL(hv_get_non_nested_register);
8080

8181
void hv_set_non_nested_register(unsigned int reg, u64 value)
8282
{
83-
if (hv_is_synic_reg(reg) && hv_isolation_type_snp()) {
84-
hv_ghcb_msr_write(reg, value);
83+
if (hv_is_synic_reg(reg) && ms_hyperv.paravisor_present) {
84+
hv_ivm_msr_write(reg, value);
8585

8686
/* Write proxy bit via wrmsl instruction */
8787
if (hv_is_sint_reg(reg))

0 commit comments

Comments
 (0)