From: Joerg Roedel <jroedel@xxxxxxx> Add a play_dead handler when running under SEV-ES. This is needed because the hypervisor can't deliver an SIPI request to restart the AP. Instead the kernel has to issue a VMGEXIT to halt the VCPU. When the hypervisor would deliver and SIPI is wakes up the VCPU instead. Signed-off-by: Joerg Roedel <jroedel@xxxxxxx> --- arch/x86/include/uapi/asm/svm.h | 1 + arch/x86/kernel/sev-es.c | 46 +++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/arch/x86/include/uapi/asm/svm.h b/arch/x86/include/uapi/asm/svm.h index a19ce9681ec2..20a05839dd9a 100644 --- a/arch/x86/include/uapi/asm/svm.h +++ b/arch/x86/include/uapi/asm/svm.h @@ -84,6 +84,7 @@ /* SEV-ES software-defined VMGEXIT events */ #define SVM_VMGEXIT_MMIO_READ 0x80000001 #define SVM_VMGEXIT_MMIO_WRITE 0x80000002 +#define SVM_VMGEXIT_AP_HLT_LOOP 0x80000004 #define SVM_VMGEXIT_AP_JUMP_TABLE 0x80000005 #define SVM_VMGEXIT_SET_AP_JUMP_TABLE 0 #define SVM_VMGEXIT_GET_AP_JUMP_TABLE 1 diff --git a/arch/x86/kernel/sev-es.c b/arch/x86/kernel/sev-es.c index d8193d37ed2b..755708f72824 100644 --- a/arch/x86/kernel/sev-es.c +++ b/arch/x86/kernel/sev-es.c @@ -22,6 +22,8 @@ #include <asm/processor.h> #include <asm/traps.h> #include <asm/svm.h> +#include <asm/smp.h> +#include <asm/cpu.h> #define DR7_RESET_VALUE 0x400 @@ -252,6 +254,48 @@ static bool __init setup_ghcb(void) return true; } +#ifdef CONFIG_HOTPLUG_CPU +static void sev_es_ap_hlt_loop(void) +{ + struct ghcb *ghcb; + + ghcb = this_cpu_ptr(&ghcb_page); + + while (true) { + ghcb_invalidate(ghcb); + ghcb_set_sw_exit_code(ghcb, SVM_VMGEXIT_AP_HLT_LOOP); + ghcb_set_sw_exit_info_1(ghcb, 0); + ghcb_set_sw_exit_info_2(ghcb, 0); + + write_ghcb_msr(__pa(ghcb)); + VMGEXIT(); + + /* Wakup Signal? */ + if (ghcb_is_valid_sw_exit_info_2(ghcb) && + ghcb->save.sw_exit_info_2 != 0) + break; + } +} + +void sev_es_play_dead(void) +{ + play_dead_common(); + + /* IRQs now disabled */ + + sev_es_ap_hlt_loop(); + + /* + * If we get here, the VCPU was woken up again. Jump to CPU + * startup code to get it back online. + */ + + start_cpu(); +} +#else /* CONFIG_HOTPLUG_CPU */ +#define sev_es_play_dead native_play_dead +#endif /* CONFIG_HOTPLUG_CPU */ + void encrypted_state_init_ghcbs(void) { int cpu; @@ -267,6 +311,8 @@ void encrypted_state_init_ghcbs(void) sizeof(ghcb_page) >> PAGE_SHIFT); memset(ghcb, 0, sizeof(*ghcb)); } + + smp_ops.play_dead = sev_es_play_dead; } static void __init early_forward_exception(struct es_em_ctxt *ctxt) -- 2.17.1 _______________________________________________ Virtualization mailing list Virtualization@xxxxxxxxxxxxxxxxxxxxxxxxxx https://lists.linuxfoundation.org/mailman/listinfo/virtualization