mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-28 11:18:45 +07:00
x86/sev-es: Support CPU offline/online
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 until the hypervisor wakes it up again. Signed-off-by: Joerg Roedel <jroedel@suse.de> Signed-off-by: Borislav Petkov <bp@suse.de> Link: https://lkml.kernel.org/r/20200907131613.12703-70-joro@8bytes.org
This commit is contained in:
parent
3ecacdbd23
commit
094794f597
@ -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
|
||||
|
@ -29,6 +29,8 @@
|
||||
#include <asm/realmode.h>
|
||||
#include <asm/traps.h>
|
||||
#include <asm/svm.h>
|
||||
#include <asm/smp.h>
|
||||
#include <asm/cpu.h>
|
||||
|
||||
#define DR7_RESET_VALUE 0x400
|
||||
|
||||
@ -518,6 +520,65 @@ static bool __init sev_es_setup_ghcb(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_HOTPLUG_CPU
|
||||
static void sev_es_ap_hlt_loop(void)
|
||||
{
|
||||
struct ghcb_state state;
|
||||
struct ghcb *ghcb;
|
||||
|
||||
ghcb = sev_es_get_ghcb(&state);
|
||||
|
||||
while (true) {
|
||||
vc_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);
|
||||
|
||||
sev_es_wr_ghcb_msr(__pa(ghcb));
|
||||
VMGEXIT();
|
||||
|
||||
/* Wakeup signal? */
|
||||
if (ghcb_sw_exit_info_2_is_valid(ghcb) &&
|
||||
ghcb->save.sw_exit_info_2)
|
||||
break;
|
||||
}
|
||||
|
||||
sev_es_put_ghcb(&state);
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 until the
|
||||
* hypervisor wakes it up again.
|
||||
*/
|
||||
static 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_cpu0();
|
||||
}
|
||||
#else /* CONFIG_HOTPLUG_CPU */
|
||||
#define sev_es_play_dead native_play_dead
|
||||
#endif /* CONFIG_HOTPLUG_CPU */
|
||||
|
||||
#ifdef CONFIG_SMP
|
||||
static void __init sev_es_setup_play_dead(void)
|
||||
{
|
||||
smp_ops.play_dead = sev_es_play_dead;
|
||||
}
|
||||
#else
|
||||
static inline void sev_es_setup_play_dead(void) { }
|
||||
#endif
|
||||
|
||||
static void __init alloc_runtime_data(int cpu)
|
||||
{
|
||||
struct sev_es_runtime_data *data;
|
||||
@ -566,6 +627,8 @@ void __init sev_es_init_vc_handling(void)
|
||||
setup_vc_stacks(cpu);
|
||||
}
|
||||
|
||||
sev_es_setup_play_dead();
|
||||
|
||||
/* Secondary CPUs use the runtime #VC handler */
|
||||
initial_vc_handler = (unsigned long)safe_stack_exc_vmm_communication;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user