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
 
          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
 
 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
 
                                                 * 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
 #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 */
 
 #include <asm/cpu_device_id.h>
 #include <asm/intel-family.h>
 #include <asm/irq_regs.h>
+#include <asm/cpu.h>
 
 unsigned int num_processors;
 
 
 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;
                                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();
        }
 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;
        }
        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);
 }
        if (x2apic_enabled()) {
                pr_info("x2apic: enabled by BIOS, switching to x2apic ops\n");
                x2apic_mode = 1;
-               x2apic_state = X2APIC_ON;
+               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;
        }