Skip to content

Commit

Permalink
x86/sev: Define the Linux-specific guest termination reasons
Browse files Browse the repository at this point in the history
The GHCB specification defines the reason code for reason set 0. The
reason codes defined in the set 0 do not cover all possible causes for a
guest to request termination.

The reason sets 1 to 255 are reserved for the vendor-specific codes.
Reserve the reason set 1 for the Linux guest. Define the error codes for
reason set 1 so that one can have meaningful termination reasons and thus
better guest failure diagnosis.

While at it, change sev_es_terminate() to accept a reason set parameter.

  [ bp: Massage commit message. ]

Signed-off-by: Brijesh Singh <brijesh.singh@amd.com>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Venu Busireddy <venu.busireddy@oracle.com>
Link: https://lore.kernel.org/r/20220307213356.2797205-11-brijesh.singh@amd.com
  • Loading branch information
Brijesh Singh authored and Borislav Petkov committed Apr 6, 2022
1 parent f742b90 commit 6c0f74d
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 12 deletions.
6 changes: 3 additions & 3 deletions arch/x86/boot/compressed/sev.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ static enum es_result vc_read_mem(struct es_em_ctxt *ctxt,
static bool early_setup_sev_es(void)
{
if (!sev_es_negotiate_protocol())
sev_es_terminate(GHCB_SEV_ES_PROT_UNSUPPORTED);
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_PROT_UNSUPPORTED);

if (set_page_decrypted((unsigned long)&boot_ghcb_page))
return false;
Expand Down Expand Up @@ -172,7 +172,7 @@ void do_boot_stage2_vc(struct pt_regs *regs, unsigned long exit_code)
enum es_result result;

if (!boot_ghcb && !early_setup_sev_es())
sev_es_terminate(GHCB_SEV_ES_GEN_REQ);
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);

vc_ghcb_invalidate(boot_ghcb);
result = vc_init_em_ctxt(&ctxt, regs, exit_code);
Expand All @@ -199,7 +199,7 @@ void do_boot_stage2_vc(struct pt_regs *regs, unsigned long exit_code)
if (result == ES_OK)
vc_finish_insn(&ctxt);
else if (result != ES_RETRY)
sev_es_terminate(GHCB_SEV_ES_GEN_REQ);
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
}

void sev_enable(struct boot_params *bp)
Expand Down
8 changes: 8 additions & 0 deletions arch/x86/include/asm/sev-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,17 @@
/* GHCBData[23:16] */ \
((((u64)reason_val) & 0xff) << 16))

/* Error codes from reason set 0 */
#define SEV_TERM_SET_GEN 0
#define GHCB_SEV_ES_GEN_REQ 0
#define GHCB_SEV_ES_PROT_UNSUPPORTED 1

/* Linux-specific reason codes (used with reason set 1) */
#define SEV_TERM_SET_LINUX 1
#define GHCB_TERM_REGISTER 0 /* GHCB GPA registration failure */
#define GHCB_TERM_PSC 1 /* Page State Change failure */
#define GHCB_TERM_PVALIDATE 2 /* Pvalidate failure */

#define GHCB_RESP_CODE(v) ((v) & GHCB_MSR_INFO_MASK)

/*
Expand Down
11 changes: 4 additions & 7 deletions arch/x86/kernel/sev-shared.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,12 @@ static bool __init sev_es_check_cpu_features(void)
return true;
}

static void __noreturn sev_es_terminate(unsigned int reason)
static void __noreturn sev_es_terminate(unsigned int set, unsigned int reason)
{
u64 val = GHCB_MSR_TERM_REQ;

/*
* Tell the hypervisor what went wrong - only reason-set 0 is
* currently supported.
*/
val |= GHCB_SEV_TERM_REASON(0, reason);
/* Tell the hypervisor what went wrong. */
val |= GHCB_SEV_TERM_REASON(set, reason);

/* Request Guest Termination from Hypvervisor */
sev_es_wr_ghcb_msr(val);
Expand Down Expand Up @@ -221,7 +218,7 @@ void __init do_vc_no_ghcb(struct pt_regs *regs, unsigned long exit_code)

fail:
/* Terminate the guest */
sev_es_terminate(GHCB_SEV_ES_GEN_REQ);
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);
}

static enum es_result vc_insn_string_read(struct es_em_ctxt *ctxt,
Expand Down
4 changes: 2 additions & 2 deletions arch/x86/kernel/sev.c
Original file line number Diff line number Diff line change
Expand Up @@ -1337,7 +1337,7 @@ DEFINE_IDTENTRY_VC_KERNEL(exc_vmm_communication)
show_regs(regs);

/* Ask hypervisor to sev_es_terminate */
sev_es_terminate(GHCB_SEV_ES_GEN_REQ);
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);

/* If that fails and we get here - just panic */
panic("Returned from Terminate-Request to Hypervisor\n");
Expand Down Expand Up @@ -1385,7 +1385,7 @@ bool __init handle_vc_boot_ghcb(struct pt_regs *regs)

/* Do initial setup or terminate the guest */
if (unlikely(boot_ghcb == NULL && !sev_es_setup_ghcb()))
sev_es_terminate(GHCB_SEV_ES_GEN_REQ);
sev_es_terminate(SEV_TERM_SET_GEN, GHCB_SEV_ES_GEN_REQ);

vc_ghcb_invalidate(boot_ghcb);

Expand Down

0 comments on commit 6c0f74d

Please sign in to comment.