From 843d8c9ebda1158a7dfab9356fe1447c2ec6e4d9 Mon Sep 17 00:00:00 2001 From: "Richard Relph (AMD)" Date: Mon, 20 Oct 2025 19:19:56 -0500 Subject: [PATCH] Add support for SVSM Reboot capability SVSM has added a Reboot protocol (Protocol 5) that has a single command (SVSM_REBOOT_EXECUTE, command 0) that will cause the guest to be rebooted. The current command does nothing to any guest state EXCEPT invalidating any pages that had been validated by SVSM at the request of the SVSM guest. Signed-off-by: Richard Relph (AMD) --- arch/x86/coco/sev/core.c | 28 ++++++++++++++++++++++++++++ arch/x86/include/asm/sev.h | 5 +++++ arch/x86/kernel/reboot.c | 10 ++++++++++ 3 files changed, 43 insertions(+) diff --git a/arch/x86/coco/sev/core.c b/arch/x86/coco/sev/core.c index 14ef5908fb2735..aba75d2aa4fc68 100644 --- a/arch/x86/coco/sev/core.c +++ b/arch/x86/coco/sev/core.c @@ -1425,6 +1425,34 @@ int snp_issue_svsm_attest_req(u64 call_id, struct svsm_call *call, } EXPORT_SYMBOL_GPL(snp_issue_svsm_attest_req); +void snp_issue_svsm_reboot_req(void) +{ + struct svsm_call call; + unsigned long flags; + + if (!snp_vmpl) + return; + + local_irq_save(flags); + + /* + * Set input registers for the request and set RDX and R8 to known + * values in order to detect length values being returned in them. + */ + call.caa = svsm_get_caa(); + call.rax = SVSM_REBOOT_CALL(SVSM_REBOOT_EXECUTE); + call.rcx = 0; + svsm_perform_call_protocol(&call); + /* + * If SVSM_REBOOT_EXECUTE is supported in the underlying SVSM, + * it will NOT return here. If it is not supported, return to + * the caller to try other reboot schemes. + */ + + local_irq_restore(flags); +} +EXPORT_SYMBOL_GPL(snp_issue_svsm_reboot_req); + static int snp_issue_guest_request(struct snp_guest_req *req) { struct snp_req_data *input = &req->input; diff --git a/arch/x86/include/asm/sev.h b/arch/x86/include/asm/sev.h index 465b19fd1a2db8..92d11056391c22 100644 --- a/arch/x86/include/asm/sev.h +++ b/arch/x86/include/asm/sev.h @@ -435,6 +435,9 @@ struct svsm_call { #define SVSM_VTPM_QUERY 0 #define SVSM_VTPM_CMD 1 +#define SVSM_REBOOT_CALL(x) ((5ULL << 32) | (x)) +#define SVSM_REBOOT_EXECUTE 0 + #ifdef CONFIG_AMD_MEM_ENCRYPT extern u8 snp_vmpl; @@ -523,6 +526,7 @@ int prepare_pte_enc(struct pte_enc_desc *d); void set_pte_enc_mask(pte_t *kpte, unsigned long pfn, pgprot_t new_prot); void snp_kexec_finish(void); void snp_kexec_begin(void); +void snp_issue_svsm_reboot_req(void); int snp_msg_init(struct snp_msg_desc *mdesc, int vmpck_id); struct snp_msg_desc *snp_msg_alloc(void); @@ -615,6 +619,7 @@ static inline int prepare_pte_enc(struct pte_enc_desc *d) { return 0; } static inline void set_pte_enc_mask(pte_t *kpte, unsigned long pfn, pgprot_t new_prot) { } static inline void snp_kexec_finish(void) { } static inline void snp_kexec_begin(void) { } +static inline void snp_issue_svsm_reboot_req(void) { } static inline int snp_msg_init(struct snp_msg_desc *mdesc, int vmpck_id) { return -1; } static inline struct snp_msg_desc *snp_msg_alloc(void) { return NULL; } static inline void snp_msg_free(struct snp_msg_desc *mdesc) { } diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index 964f6b0a3d68c3..8b106673b29e9c 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include @@ -650,6 +651,15 @@ static void native_machine_emergency_restart(void) reboot_type = BOOT_EFI; } + /* + * If we're running under SVSM, try to reboot using SVSM. + */ + if (snp_vmpl) { + pr_emerg("Trying SVSM Reboot\n"); + snp_issue_svsm_reboot_req(); + pr_emerg("SVSM Reboot returned.\n"); + } + for (;;) { /* Could also try the reset bit in the Hammer NB */ switch (reboot_type) {