Commit 0ca77f8d authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge branch 'x86/apic' into x86/sev, to resolve conflict



 Conflicts:
	arch/x86/include/asm/sev-internal.h

Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 9f8d92a1 d4bc3b11
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -483,6 +483,19 @@ config X86_X2APIC

	  If in doubt, say Y.

config AMD_SECURE_AVIC
	bool "AMD Secure AVIC"
	depends on AMD_MEM_ENCRYPT && X86_X2APIC
	help
	  Enable this to get AMD Secure AVIC support on guests that have this feature.

	  AMD Secure AVIC provides hardware acceleration for performance sensitive
	  APIC accesses and support for managing guest owned APIC state for SEV-SNP
	  guests. Secure AVIC does not support xAPIC mode. It has functional
	  dependency on x2apic being enabled in the guest.

	  If you don't know what to do here, say N.

config X86_POSTED_MSI
	bool "Enable MSI and MSI-x delivery by posted interrupts"
	depends on X86_64 && IRQ_REMAP
+9 −1
Original line number Diff line number Diff line
@@ -186,15 +186,23 @@ bool sev_es_check_ghcb_fault(unsigned long address)
				 MSR_AMD64_SNP_VMSA_REG_PROT |		\
				 MSR_AMD64_SNP_RESERVED_BIT13 |		\
				 MSR_AMD64_SNP_RESERVED_BIT15 |		\
				 MSR_AMD64_SNP_SECURE_AVIC |		\
				 MSR_AMD64_SNP_RESERVED_MASK)

#ifdef CONFIG_AMD_SECURE_AVIC
#define SNP_FEATURE_SECURE_AVIC		MSR_AMD64_SNP_SECURE_AVIC
#else
#define SNP_FEATURE_SECURE_AVIC		0
#endif

/*
 * SNP_FEATURES_PRESENT is the mask of SNP features that are implemented
 * by the guest kernel. As and when a new feature is implemented in the
 * guest kernel, a corresponding bit should be added to the mask.
 */
#define SNP_FEATURES_PRESENT	(MSR_AMD64_SNP_DEBUG_SWAP |	\
				 MSR_AMD64_SNP_SECURE_TSC)
				 MSR_AMD64_SNP_SECURE_TSC |	\
				 SNP_FEATURE_SECURE_AVIC)

u64 snp_get_unsupported_features(u64 status)
{
+3 −0
Original line number Diff line number Diff line
@@ -104,6 +104,9 @@ static bool noinstr amd_cc_platform_has(enum cc_attr attr)
	case CC_ATTR_HOST_SEV_SNP:
		return cc_flags.host_sev_snp;

	case CC_ATTR_SNP_SECURE_AVIC:
		return sev_status & MSR_AMD64_SNP_SECURE_AVIC;

	default:
		return false;
	}
+103 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ static const char * const sev_status_feat_names[] = {
	[MSR_AMD64_SNP_IBS_VIRT_BIT]		= "IBSVirt",
	[MSR_AMD64_SNP_VMSA_REG_PROT_BIT]	= "VMSARegProt",
	[MSR_AMD64_SNP_SMT_PROT_BIT]		= "SMTProt",
	[MSR_AMD64_SNP_SECURE_AVIC_BIT]		= "SecureAVIC",
};

/*
@@ -1105,6 +1106,9 @@ static int wakeup_cpu_via_vmgexit(u32 apic_id, unsigned long start_ip, unsigned
	vmsa->x87_ftw		= AP_INIT_X87_FTW_DEFAULT;
	vmsa->x87_fcw		= AP_INIT_X87_FCW_DEFAULT;

	if (cc_platform_has(CC_ATTR_SNP_SECURE_AVIC))
		vmsa->vintr_ctrl |= V_GIF_MASK | V_NMI_ENABLE_MASK;

	/* SVME must be set. */
	vmsa->efer		= EFER_SVME;

@@ -1239,6 +1243,105 @@ int __init sev_es_efi_map_ghcbs_cas(pgd_t *pgd)
	return 0;
}

u64 savic_ghcb_msr_read(u32 reg)
{
	u64 msr = APIC_BASE_MSR + (reg >> 4);
	struct pt_regs regs = { .cx = msr };
	struct es_em_ctxt ctxt = { .regs = &regs };
	struct ghcb_state state;
	enum es_result res;
	struct ghcb *ghcb;

	guard(irqsave)();

	ghcb = __sev_get_ghcb(&state);
	vc_ghcb_invalidate(ghcb);

	res = sev_es_ghcb_handle_msr(ghcb, &ctxt, false);
	if (res != ES_OK) {
		pr_err("Secure AVIC MSR (0x%llx) read returned error (%d)\n", msr, res);
		/* MSR read failures are treated as fatal errors */
		sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_SAVIC_FAIL);
	}

	__sev_put_ghcb(&state);

	return regs.ax | regs.dx << 32;
}

void savic_ghcb_msr_write(u32 reg, u64 value)
{
	u64 msr = APIC_BASE_MSR + (reg >> 4);
	struct pt_regs regs = {
		.cx = msr,
		.ax = lower_32_bits(value),
		.dx = upper_32_bits(value)
	};
	struct es_em_ctxt ctxt = { .regs = &regs };
	struct ghcb_state state;
	enum es_result res;
	struct ghcb *ghcb;

	guard(irqsave)();

	ghcb = __sev_get_ghcb(&state);
	vc_ghcb_invalidate(ghcb);

	res = sev_es_ghcb_handle_msr(ghcb, &ctxt, true);
	if (res != ES_OK) {
		pr_err("Secure AVIC MSR (0x%llx) write returned error (%d)\n", msr, res);
		/* MSR writes should never fail. Any failure is fatal error for SNP guest */
		sev_es_terminate(SEV_TERM_SET_LINUX, GHCB_TERM_SAVIC_FAIL);
	}

	__sev_put_ghcb(&state);
}

enum es_result savic_register_gpa(u64 gpa)
{
	struct ghcb_state state;
	struct es_em_ctxt ctxt;
	enum es_result res;
	struct ghcb *ghcb;

	guard(irqsave)();

	ghcb = __sev_get_ghcb(&state);
	vc_ghcb_invalidate(ghcb);

	ghcb_set_rax(ghcb, SVM_VMGEXIT_SAVIC_SELF_GPA);
	ghcb_set_rbx(ghcb, gpa);
	res = sev_es_ghcb_hv_call(ghcb, &ctxt, SVM_VMGEXIT_SAVIC,
				  SVM_VMGEXIT_SAVIC_REGISTER_GPA, 0);

	__sev_put_ghcb(&state);

	return res;
}

enum es_result savic_unregister_gpa(u64 *gpa)
{
	struct ghcb_state state;
	struct es_em_ctxt ctxt;
	enum es_result res;
	struct ghcb *ghcb;

	guard(irqsave)();

	ghcb = __sev_get_ghcb(&state);
	vc_ghcb_invalidate(ghcb);

	ghcb_set_rax(ghcb, SVM_VMGEXIT_SAVIC_SELF_GPA);
	res = sev_es_ghcb_hv_call(ghcb, &ctxt, SVM_VMGEXIT_SAVIC,
				  SVM_VMGEXIT_SAVIC_UNREGISTER_GPA, 0);
	if (gpa && res == ES_OK)
		*gpa = ghcb->save.rbx;

	__sev_put_ghcb(&state);

	return res;
}

static void snp_register_per_cpu_ghcb(void)
{
	struct sev_es_runtime_data *data;
+15 −5
Original line number Diff line number Diff line
@@ -404,14 +404,10 @@ static enum es_result __vc_handle_secure_tsc_msrs(struct es_em_ctxt *ctxt, bool
	return ES_OK;
}

static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
enum es_result sev_es_ghcb_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt, bool write)
{
	struct pt_regs *regs = ctxt->regs;
	enum es_result ret;
	bool write;

	/* Is it a WRMSR? */
	write = ctxt->insn.opcode.bytes[1] == 0x30;

	switch (regs->cx) {
	case MSR_SVSM_CAA:
@@ -421,6 +417,15 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
		if (sev_status & MSR_AMD64_SNP_SECURE_TSC)
			return __vc_handle_secure_tsc_msrs(ctxt, write);
		break;
	case MSR_AMD64_SAVIC_CONTROL:
		/*
		 * AMD64_SAVIC_CONTROL should not be intercepted when
		 * Secure AVIC is enabled. Terminate the Secure AVIC guest
		 * if the interception is enabled.
		 */
		if (cc_platform_has(CC_ATTR_SNP_SECURE_AVIC))
			return ES_VMM_ERROR;
		break;
	default:
		break;
	}
@@ -441,6 +446,11 @@ static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
	return ret;
}

static enum es_result vc_handle_msr(struct ghcb *ghcb, struct es_em_ctxt *ctxt)
{
	return sev_es_ghcb_handle_msr(ghcb, ctxt, ctxt->insn.opcode.bytes[1] == 0x30);
}

static void __init vc_early_forward_exception(struct es_em_ctxt *ctxt)
{
	int trapnr = ctxt->fi.vector;
Loading