From: Tianyu Lan <Tianyu.Lan@xxxxxxxxxxxxx> Hyper-V also needs to call ghcb hv call to write/read MSR in Isolation VM. So expose __sev_es_ghcb_hv_call() to call it in the Hyper-V code. Signed-off-by: Tianyu Lan <Tianyu.Lan@xxxxxxxxxxxxx> --- arch/x86/include/asm/sev.h | 10 +++++++++ arch/x86/kernel/sev-shared.c | 43 +++++++++++++++++++++++++----------- 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h index fa5cd05d3b5b..2e96869f3e9b 100644 --- a/arch/x86/include/asm/sev.h +++ b/arch/x86/include/asm/sev.h @@ -81,12 +81,22 @@ static __always_inline void sev_es_nmi_complete(void) __sev_es_nmi_complete(); } extern int __init sev_es_efi_map_ghcbs(pgd_t *pgd); +extern enum es_result __sev_es_ghcb_hv_call(struct ghcb *ghcb, + u64 exit_code, u64 exit_info_1, + u64 exit_info_2); #else static inline void sev_es_ist_enter(struct pt_regs *regs) { } static inline void sev_es_ist_exit(void) { } static inline int sev_es_setup_ap_jump_table(struct real_mode_header *rmh) { return 0; } static inline void sev_es_nmi_complete(void) { } static inline int sev_es_efi_map_ghcbs(pgd_t *pgd) { return 0; } +static inline enum es_result +__sev_es_ghcb_hv_call(struct ghcb *ghcb, + u64 exit_code, u64 exit_info_1, + u64 exit_info_2) +{ + return ES_VMM_ERROR; +} #endif #endif diff --git a/arch/x86/kernel/sev-shared.c b/arch/x86/kernel/sev-shared.c index 9f90f460a28c..946c203be08c 100644 --- a/arch/x86/kernel/sev-shared.c +++ b/arch/x86/kernel/sev-shared.c @@ -94,10 +94,13 @@ static void vc_finish_insn(struct es_em_ctxt *ctxt) ctxt->regs->ip += ctxt->insn.length; } -static enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb, - struct es_em_ctxt *ctxt, - u64 exit_code, u64 exit_info_1, - u64 exit_info_2) +/* + * __sev_es_ghcb_hv_call() is also used in the other platform code(e.g + * Hyper-V). + */ +enum es_result __sev_es_ghcb_hv_call(struct ghcb *ghcb, + u64 exit_code, u64 exit_info_1, + u64 exit_info_2) { enum es_result ret; @@ -109,15 +112,33 @@ static enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb, ghcb_set_sw_exit_info_1(ghcb, exit_info_1); ghcb_set_sw_exit_info_2(ghcb, exit_info_2); - sev_es_wr_ghcb_msr(__pa(ghcb)); VMGEXIT(); + if (ghcb->save.sw_exit_info_1 & 0xffffffff) + ret = ES_VMM_ERROR; + else + ret = ES_OK; + + return ret; +} + +static enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb, + struct es_em_ctxt *ctxt, + u64 exit_code, u64 exit_info_1, + u64 exit_info_2) +{ + enum es_result ret; + + sev_es_wr_ghcb_msr(__pa(ghcb)); + + ret = __sev_es_ghcb_hv_call(ghcb, exit_code, exit_info_1, + exit_info_2); + if (ret == ES_OK) + return ret; + if ((ghcb->save.sw_exit_info_1 & 0xffffffff) == 1) { u64 info = ghcb->save.sw_exit_info_2; - unsigned long v; - - info = ghcb->save.sw_exit_info_2; - v = info & SVM_EVTINJ_VEC_MASK; + unsigned long v = info & SVM_EVTINJ_VEC_MASK; /* Check if exception information from hypervisor is sane. */ if ((info & SVM_EVTINJ_VALID) && @@ -127,11 +148,7 @@ static enum es_result sev_es_ghcb_hv_call(struct ghcb *ghcb, if (info & SVM_EVTINJ_VALID_ERR) ctxt->fi.error_code = info >> 32; ret = ES_EXCEPTION; - } else { - ret = ES_VMM_ERROR; } - } else { - ret = ES_OK; } return ret; -- 2.25.1