Skip to content

Commit 007faec

Browse files
Tianyu Lansuryasaimadhu
authored andcommitted
x86/sev: Expose sev_es_ghcb_hv_call() for use by HyperV
Hyper-V needs to issue the GHCB HV call in order to read/write MSRs in Isolation VMs. For that, expose sev_es_ghcb_hv_call(). The Hyper-V Isolation VMs are unenlightened guests and run a paravisor at VMPL0 for communicating. GHCB pages are being allocated and set up by that paravisor. Linux gets the GHCB page's physical address via MSR_AMD64_SEV_ES_GHCB from the paravisor and should not change it. Add a @set_ghcb_msr parameter to sev_es_ghcb_hv_call() to control whether the function should set the GHCB's address prior to the call or not and export that function for use by HyperV. [ bp: - Massage commit message - add a struct ghcb forward declaration to fix randconfig builds. ] Signed-off-by: Tianyu Lan <[email protected]> Signed-off-by: Borislav Petkov <[email protected]> Reviewed-by: Michael Kelley <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent ce47d0c commit 007faec

File tree

3 files changed

+29
-15
lines changed

3 files changed

+29
-15
lines changed

arch/x86/include/asm/sev.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ static inline u64 lower_bits(u64 val, unsigned int bits)
5353

5454
struct real_mode_header;
5555
enum stack_type;
56+
struct ghcb;
5657

5758
/* Early IDT entry points for #VC handler */
5859
extern void vc_no_ghcb(void);
@@ -81,6 +82,11 @@ static __always_inline void sev_es_nmi_complete(void)
8182
__sev_es_nmi_complete();
8283
}
8384
extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd);
85+
extern enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb,
86+
bool set_ghcb_msr,
87+
struct es_em_ctxt *ctxt,
88+
u64 exit_code, u64 exit_info_1,
89+
u64 exit_info_2);
8490
#else
8591
static inline void sev_es_ist_enter(struct pt_regs *regs) { }
8692
static inline void sev_es_ist_exit(void) { }

arch/x86/kernel/sev-shared.c

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,9 @@ static enum es_result verify_exception_info(struct ghcb *ghcb, struct es_em_ctxt
125125
return ES_VMM_ERROR;
126126
}
127127

128-
static enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb,
129-
struct es_em_ctxt *ctxt,
130-
u64 exit_code, u64 exit_info_1,
131-
u64 exit_info_2)
128+
enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb, bool set_ghcb_msr,
129+
struct es_em_ctxt *ctxt, u64 exit_code,
130+
u64 exit_info_1, u64 exit_info_2)
132131
{
133132
/* Fill in protocol and format specifiers */
134133
ghcb->protocol_version = GHCB_PROTOCOL_MAX;
@@ -138,7 +137,14 @@ static enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb,
138137
ghcb_set_sw_exit_info_1(ghcb, exit_info_1);
139138
ghcb_set_sw_exit_info_2(ghcb, exit_info_2);
140139

141-
sev_es_wr_ghcb_msr(__pa(ghcb));
140+
/*
141+
* Hyper-V unenlightened guests use a paravisor for communicating and
142+
* GHCB pages are being allocated and set up by that paravisor. Linux
143+
* should not change the GHCB page's physical address.
144+
*/
145+
if (set_ghcb_msr)
146+
sev_es_wr_ghcb_msr(__pa(ghcb));
147+
142148
VMGEXIT();
143149

144150
return verify_exception_info(ghcb, ctxt);
@@ -418,7 +424,7 @@ static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
418424
*/
419425
sw_scratch = __pa(ghcb) + offsetof(struct ghcb, shared_buffer);
420426
ghcb_set_sw_scratch(ghcb, sw_scratch);
421-
ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_IOIO,
427+
ret = sev_es_ghcb_hv_call(ghcb, true, ctxt, SVM_EXIT_IOIO,
422428
exit_info_1, exit_info_2);
423429
if (ret != ES_OK)
424430
return ret;
@@ -460,7 +466,8 @@ static enum es_result vc_handle_ioio(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
460466

461467
ghcb_set_rax(ghcb, rax);
462468

463-
ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_IOIO, exit_info_1, 0);
469+
ret = sev_es_ghcb_hv_call(ghcb, true, ctxt,
470+
SVM_EXIT_IOIO, exit_info_1, 0);
464471
if (ret != ES_OK)
465472
return ret;
466473

@@ -491,7 +498,7 @@ static enum es_result vc_handle_cpuid(struct ghcb *ghcb,
491498
/* xgetbv will cause #GP - use reset value for xcr0 */
492499
ghcb_set_xcr0(ghcb, 1);
493500

494-
ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_CPUID, 0, 0);
501+
ret = sev_es_ghcb_hv_call(ghcb, true, ctxt, SVM_EXIT_CPUID, 0, 0);
495502
if (ret != ES_OK)
496503
return ret;
497504

@@ -516,7 +523,7 @@ static enum es_result vc_handle_rdtsc(struct ghcb *ghcb,
516523
bool rdtscp = (exit_code == SVM_EXIT_RDTSCP);
517524
enum es_result ret;
518525

519-
ret = sev_es_ghcb_hv_call(ghcb, ctxt, exit_code, 0, 0);
526+
ret = sev_es_ghcb_hv_call(ghcb, true, ctxt, exit_code, 0, 0);
520527
if (ret != ES_OK)
521528
return ret;
522529

arch/x86/kernel/sev.c

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -648,7 +648,8 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
648648
ghcb_set_rdx(ghcb, regs->dx);
649649
}
650650

651-
ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_MSR, exit_info_1, 0);
651+
ret = sev_es_ghcb_hv_call(ghcb, true, ctxt, SVM_EXIT_MSR,
652+
exit_info_1, 0);
652653

653654
if ((ret == ES_OK) && (!exit_info_1)) {
654655
regs->ax = ghcb->save.rax;
@@ -867,7 +868,7 @@ static enum es_result vc_do_mmio(struct ghcb *ghcb, struct es_em_ctxt *ctxt,
867868

868869
ghcb_set_sw_scratch(ghcb, ghcb_pa + offsetof(struct ghcb, shared_buffer));
869870

870-
return sev_es_ghcb_hv_call(ghcb, ctxt, exit_code, exit_info_1, exit_info_2);
871+
return sev_es_ghcb_hv_call(ghcb, true, ctxt, exit_code, exit_info_1, exit_info_2);
871872
}
872873

873874
static enum es_result vc_handle_mmio_twobyte_ops(struct ghcb *ghcb,
@@ -1117,7 +1118,7 @@ static enum es_result vc_handle_dr7_write(struct ghcb *ghcb,
11171118

11181119
/* Using a value of 0 for ExitInfo1 means RAX holds the value */
11191120
ghcb_set_rax(ghcb, val);
1120-
ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_WRITE_DR7, 0, 0);
1121+
ret = sev_es_ghcb_hv_call(ghcb, true, ctxt, SVM_EXIT_WRITE_DR7, 0, 0);
11211122
if (ret != ES_OK)
11221123
return ret;
11231124

@@ -1147,7 +1148,7 @@ static enum es_result vc_handle_dr7_read(struct ghcb *ghcb,
11471148
static enum es_result vc_handle_wbinvd(struct ghcb *ghcb,
11481149
struct es_em_ctxt *ctxt)
11491150
{
1150-
return sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_WBINVD, 0, 0);
1151+
return sev_es_ghcb_hv_call(ghcb, true, ctxt, SVM_EXIT_WBINVD, 0, 0);
11511152
}
11521153

11531154
static enum es_result vc_handle_rdpmc(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
@@ -1156,7 +1157,7 @@ static enum es_result vc_handle_rdpmc(struct ghcb *ghcb, struct es_em_ctxt *ctxt
11561157

11571158
ghcb_set_rcx(ghcb, ctxt->regs->cx);
11581159

1159-
ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_RDPMC, 0, 0);
1160+
ret = sev_es_ghcb_hv_call(ghcb, true, ctxt, SVM_EXIT_RDPMC, 0, 0);
11601161
if (ret != ES_OK)
11611162
return ret;
11621163

@@ -1197,7 +1198,7 @@ static enum es_result vc_handle_vmmcall(struct ghcb *ghcb,
11971198
if (x86_platform.hyper.sev_es_hcall_prepare)
11981199
x86_platform.hyper.sev_es_hcall_prepare(ghcb, ctxt->regs);
11991200

1200-
ret = sev_es_ghcb_hv_call(ghcb, ctxt, SVM_EXIT_VMMCALL, 0, 0);
1201+
ret = sev_es_ghcb_hv_call(ghcb, true, ctxt, SVM_EXIT_VMMCALL, 0, 0);
12011202
if (ret != ES_OK)
12021203
return ret;
12031204

0 commit comments

Comments
 (0)