On Mon, Aug 25, 2025 at 05:33:12PM +0000, Yazen Ghannam wrote: > Scalable MCA systems have a per-CPU register that gives the APIC LVT > offset for the thresholding and deferred error interrupts. > > Currently, this register is read once to set up the deferred error > interrupt and then read again for each thresholding block. Furthermore, > the APIC LVT registers are configured each time, but they only need to > be configured once per-CPU. > > Move the APIC LVT setup to the early part of CPU init, so that the > registers are set up once. Also, this ensures that the kernel is ready > to service the interrupts before the individual error sources (each MCA > bank) are enabled. > > Apply this change only to SMCA systems to avoid breaking any legacy > behavior. The deferred error interrupt is technically advertised by the > SUCCOR feature. However, this was first made available on SMCA systems. > Therefore, only set up the deferred error interrupt on SMCA systems and > simplify the code. > > Guidance from hardware designers is that the LVT offsets provided from > the platform should be used. The kernel should not try to enforce > specific values. However, the kernel should check that an LVT offset is > not reused for multiple sources. > > Therefore, remove the extra checking and value enforcement from the MCE > code. The "reuse/conflict" case is already handled in > setup_APIC_eilvt(). > > Tested-by: Tony Luck <tony.luck@xxxxxxxxx> > Reviewed-by: Tony Luck <tony.luck@xxxxxxxxx> > Signed-off-by: Yazen Ghannam <yazen.ghannam@xxxxxxx> Some touchups ontop: diff --git a/arch/x86/kernel/cpu/mce/amd.c b/arch/x86/kernel/cpu/mce/amd.c index c05d9c6f07d1..5722806ccaa5 100644 --- a/arch/x86/kernel/cpu/mce/amd.c +++ b/arch/x86/kernel/cpu/mce/amd.c @@ -54,8 +54,10 @@ static bool thresholding_irq_en; struct mce_amd_cpu_data { mce_banks_t thr_intr_banks; mce_banks_t dfr_intr_banks; - bool thr_intr_en; - bool dfr_intr_en; + + u32 thr_intr_en: 1, + dfr_intr_en: 1, + __resv: 30; }; static DEFINE_PER_CPU_READ_MOSTLY(struct mce_amd_cpu_data, mce_amd_data); @@ -508,9 +510,8 @@ static u32 get_block_address(u32 current_addr, u32 low, u32 high, return addr; } -static int -prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr, - int offset, u32 misc_high) +static int prepare_threshold_block(unsigned int bank, unsigned int block, u32 addr, + int offset, u32 misc_high) { unsigned int cpu = smp_processor_id(); struct threshold_block b; @@ -652,11 +653,11 @@ static void smca_enable_interrupt_vectors(void) offset = (mca_intr_cfg & SMCA_THR_LVT_OFF) >> 12; if (!setup_APIC_eilvt(offset, THRESHOLD_APIC_VECTOR, APIC_EILVT_MSG_FIX, 0)) - data->thr_intr_en = true; + data->thr_intr_en = 1; offset = (mca_intr_cfg & MASK_DEF_LVTOFF) >> 4; if (!setup_APIC_eilvt(offset, DEFERRED_ERROR_VECTOR, APIC_EILVT_MSG_FIX, 0)) - data->dfr_intr_en = true; + data->dfr_intr_en = 1; } /* cpu init entry point, called from mce.c with preempt off */ @@ -669,6 +670,7 @@ void mce_amd_feature_init(struct cpuinfo_x86 *c) amd_apply_cpu_quirks(c); mce_flags.amd_threshold = 1; + smca_enable_interrupt_vectors(); for (bank = 0; bank < this_cpu_read(mce_num_banks); ++bank) { -- Regards/Gruss, Boris. https://people.kernel.org/tglx/notes-about-netiquette