Commit 5bb3a16d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86_apic_for_v6.1_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 APIC update from Borislav Petkov:

 - Add support for locking the APIC in X2APIC mode to prevent SGX
   enclave leaks

* tag 'x86_apic_for_v6.1_rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/apic: Don't disable x2APIC if locked
parents 51eaa866 b8d1d163
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -3805,6 +3805,10 @@

	nox2apic	[X86-64,APIC] Do not enable x2APIC mode.

			NOTE: this parameter will be ignored on systems with the
			LEGACY_XAPIC_DISABLED bit set in the
			IA32_XAPIC_DISABLE_STATUS MSR.

	nps_mtm_hs_ctr=	[KNL,ARC]
			This parameter sets the maximum duration, in
			cycles, each HW thread of the CTOP can run
+6 −1
Original line number Diff line number Diff line
@@ -451,6 +451,11 @@ config X86_X2APIC
	  This allows 32-bit apic IDs (so it can support very large systems),
	  and accesses the local apic via MSRs not via mmio.

	  Some Intel systems circa 2022 and later are locked into x2APIC mode
	  and can not fall back to the legacy APIC modes if SGX or TDX are
	  enabled in the BIOS.  They will be unable to boot without enabling
	  this option.

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

config X86_MPPARSE
@@ -1922,7 +1927,7 @@ endchoice

config X86_SGX
	bool "Software Guard eXtensions (SGX)"
	depends on X86_64 && CPU_SUP_INTEL
	depends on X86_64 && CPU_SUP_INTEL && X86_X2APIC
	depends on CRYPTO=y
	depends on CRYPTO_SHA256=y
	select SRCU
+2 −0
Original line number Diff line number Diff line
@@ -94,4 +94,6 @@ static inline bool intel_cpu_signatures_match(unsigned int s1, unsigned int p1,
	return p1 & p2;
}

extern u64 x86_read_arch_cap_msr(void);

#endif /* _ASM_X86_CPU_H */
+13 −0
Original line number Diff line number Diff line
@@ -155,6 +155,11 @@
						 * Return Stack Buffer Predictions.
						 */

#define ARCH_CAP_XAPIC_DISABLE		BIT(21)	/*
						 * IA32_XAPIC_DISABLE_STATUS MSR
						 * supported
						 */

#define MSR_IA32_FLUSH_CMD		0x0000010b
#define L1D_FLUSH			BIT(0)	/*
						 * Writeback and invalidate the
@@ -1054,4 +1059,12 @@
#define MSR_IA32_HW_FEEDBACK_PTR        0x17d0
#define MSR_IA32_HW_FEEDBACK_CONFIG     0x17d1

/* x2APIC locked status */
#define MSR_IA32_XAPIC_DISABLE_STATUS	0xBD
#define LEGACY_XAPIC_DISABLED		BIT(0) /*
						* x2APIC mode is locked and
						* disabling x2APIC will cause
						* a #GP
						*/

#endif /* _ASM_X86_MSR_INDEX_H */
+40 −4
Original line number Diff line number Diff line
@@ -61,6 +61,7 @@
#include <asm/cpu_device_id.h>
#include <asm/intel-family.h>
#include <asm/irq_regs.h>
#include <asm/cpu.h>

unsigned int num_processors;

@@ -1751,11 +1752,26 @@ EXPORT_SYMBOL_GPL(x2apic_mode);

enum {
	X2APIC_OFF,
	X2APIC_ON,
	X2APIC_DISABLED,
	/* All states below here have X2APIC enabled */
	X2APIC_ON,
	X2APIC_ON_LOCKED
};
static int x2apic_state;

static bool x2apic_hw_locked(void)
{
	u64 ia32_cap;
	u64 msr;

	ia32_cap = x86_read_arch_cap_msr();
	if (ia32_cap & ARCH_CAP_XAPIC_DISABLE) {
		rdmsrl(MSR_IA32_XAPIC_DISABLE_STATUS, msr);
		return (msr & LEGACY_XAPIC_DISABLED);
	}
	return false;
}

static void __x2apic_disable(void)
{
	u64 msr;
@@ -1793,6 +1809,10 @@ static int __init setup_nox2apic(char *str)
				apicid);
			return 0;
		}
		if (x2apic_hw_locked()) {
			pr_warn("APIC locked in x2apic mode, can't disable\n");
			return 0;
		}
		pr_warn("x2apic already enabled.\n");
		__x2apic_disable();
	}
@@ -1807,10 +1827,18 @@ early_param("nox2apic", setup_nox2apic);
void x2apic_setup(void)
{
	/*
	 * If x2apic is not in ON state, disable it if already enabled
	 * Try to make the AP's APIC state match that of the BSP,  but if the
	 * BSP is unlocked and the AP is locked then there is a state mismatch.
	 * Warn about the mismatch in case a GP fault occurs due to a locked AP
	 * trying to be turned off.
	 */
	if (x2apic_state != X2APIC_ON_LOCKED && x2apic_hw_locked())
		pr_warn("x2apic lock mismatch between BSP and AP.\n");
	/*
	 * If x2apic is not in ON or LOCKED state, disable it if already enabled
	 * from BIOS.
	 */
	if (x2apic_state != X2APIC_ON) {
	if (x2apic_state < X2APIC_ON) {
		__x2apic_disable();
		return;
	}
@@ -1831,6 +1859,11 @@ static __init void x2apic_disable(void)
	if (x2apic_id >= 255)
		panic("Cannot disable x2apic, id: %08x\n", x2apic_id);

	if (x2apic_hw_locked()) {
		pr_warn("Cannot disable locked x2apic, id: %08x\n", x2apic_id);
		return;
	}

	__x2apic_disable();
	register_lapic_address(mp_lapic_addr);
}
@@ -1889,6 +1922,9 @@ void __init check_x2apic(void)
	if (x2apic_enabled()) {
		pr_info("x2apic: enabled by BIOS, switching to x2apic ops\n");
		x2apic_mode = 1;
		if (x2apic_hw_locked())
			x2apic_state = X2APIC_ON_LOCKED;
		else
			x2apic_state = X2APIC_ON;
	} else if (!boot_cpu_has(X86_FEATURE_X2APIC)) {
		x2apic_state = X2APIC_DISABLED;