Skip to content

Commit 61d1ea9

Browse files
committed
Merge tag 'x86-apic-2024-09-17' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 APIC updates from Thomas Gleixner: - Handle an allocation failure in the IO/APIC code gracefully instead of crashing the machine. - Remove support for APIC local destination mode on 64bit Logical destination mode of the local APIC is used for systems with up to 8 CPUs. It has an advantage over physical destination mode as it allows to target multiple CPUs at once with IPIs. That advantage was definitely worth it when systems with up to 8 CPUs were state of the art for servers and workstations, but that's history. In the recent past there were quite some reports of new laptops failing to boot with logical destination mode, but they work fine with physical destination mode. That's not a suprise because physical destination mode is guaranteed to work as it's the only way to get a CPU up and running via the INIT/INIT/STARTUP sequence. Some of the affected systems were cured by BIOS updates, but not all OEMs provide them. As the number of CPUs keep increasing, logical destination mode becomes less used and the benefit for small systems, like laptops, is not really worth the trouble. So just remove logical destination mode support for 64bit and be done with it. - Code and comment cleanups in the APIC area. * tag 'x86-apic-2024-09-17' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/irq: Fix comment on IRQ vector layout x86/apic: Remove unused extern declarations x86/apic: Remove logical destination mode for 64-bit x86/apic: Remove unused inline function apic_set_eoi_cb() x86/ioapic: Cleanup remaining coding style issues x86/ioapic: Cleanup line breaks x86/ioapic: Cleanup bracket usage x86/ioapic: Cleanup comments x86/ioapic: Move replace_pin_at_irq_node() to the call site iommu/vt-d: Cleanup apic_printk() x86/mpparse: Cleanup apic_printk()s x86/ioapic: Cleanup guarded debug printk()s x86/ioapic: Cleanup apic_printk()s x86/apic: Cleanup apic_printk()s x86/apic: Provide apic_printk() helpers x86/ioapic: Use guard() for locking where applicable x86/ioapic: Cleanup structs x86/ioapic: Mark mp_alloc_timer_irq() __init x86/ioapic: Handle allocation failures gracefully
2 parents 0279aa7 + a1fab3e commit 61d1ea9

File tree

7 files changed

+378
-647
lines changed

7 files changed

+378
-647
lines changed

arch/x86/include/asm/apic.h

Lines changed: 19 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -18,29 +18,34 @@
1818

1919
#define ARCH_APICTIMER_STOPS_ON_C3 1
2020

21+
/* Macros for apic_extnmi which controls external NMI masking */
22+
#define APIC_EXTNMI_BSP 0 /* Default */
23+
#define APIC_EXTNMI_ALL 1
24+
#define APIC_EXTNMI_NONE 2
25+
2126
/*
2227
* Debugging macros
2328
*/
2429
#define APIC_QUIET 0
2530
#define APIC_VERBOSE 1
2631
#define APIC_DEBUG 2
2732

28-
/* Macros for apic_extnmi which controls external NMI masking */
29-
#define APIC_EXTNMI_BSP 0 /* Default */
30-
#define APIC_EXTNMI_ALL 1
31-
#define APIC_EXTNMI_NONE 2
32-
3333
/*
34-
* Define the default level of output to be very little
35-
* This can be turned up by using apic=verbose for more
36-
* information and apic=debug for _lots_ of information.
37-
* apic_verbosity is defined in apic.c
34+
* Define the default level of output to be very little This can be turned
35+
* up by using apic=verbose for more information and apic=debug for _lots_
36+
* of information. apic_verbosity is defined in apic.c
3837
*/
39-
#define apic_printk(v, s, a...) do { \
40-
if ((v) <= apic_verbosity) \
41-
printk(s, ##a); \
42-
} while (0)
43-
38+
#define apic_printk(v, s, a...) \
39+
do { \
40+
if ((v) <= apic_verbosity) \
41+
printk(s, ##a); \
42+
} while (0)
43+
44+
#define apic_pr_verbose(s, a...) apic_printk(APIC_VERBOSE, KERN_INFO s, ##a)
45+
#define apic_pr_debug(s, a...) apic_printk(APIC_DEBUG, KERN_DEBUG s, ##a)
46+
#define apic_pr_debug_cont(s, a...) apic_printk(APIC_DEBUG, KERN_CONT s, ##a)
47+
/* Unconditional debug prints for code which is guarded by apic_verbosity already */
48+
#define apic_dbg(s, a...) printk(KERN_DEBUG s, ##a)
4449

4550
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32)
4651
extern void x86_32_probe_apic(void);
@@ -122,8 +127,6 @@ static inline bool apic_is_x2apic_enabled(void)
122127

123128
extern void enable_IR_x2apic(void);
124129

125-
extern int get_physical_broadcast(void);
126-
127130
extern int lapic_get_maxlvt(void);
128131
extern void clear_local_APIC(void);
129132
extern void disconnect_bsp_APIC(int virt_wire_setup);
@@ -345,20 +348,12 @@ extern struct apic *apic;
345348
* APIC drivers are probed based on how they are listed in the .apicdrivers
346349
* section. So the order is important and enforced by the ordering
347350
* of different apic driver files in the Makefile.
348-
*
349-
* For the files having two apic drivers, we use apic_drivers()
350-
* to enforce the order with in them.
351351
*/
352352
#define apic_driver(sym) \
353353
static const struct apic *__apicdrivers_##sym __used \
354354
__aligned(sizeof(struct apic *)) \
355355
__section(".apicdrivers") = { &sym }
356356

357-
#define apic_drivers(sym1, sym2) \
358-
static struct apic *__apicdrivers_##sym1##sym2[2] __used \
359-
__aligned(sizeof(struct apic *)) \
360-
__section(".apicdrivers") = { &sym1, &sym2 }
361-
362357
extern struct apic *__apicdrivers[], *__apicdrivers_end[];
363358

364359
/*
@@ -484,7 +479,6 @@ static inline u64 apic_icr_read(void) { return 0; }
484479
static inline void apic_icr_write(u32 low, u32 high) { }
485480
static inline void apic_wait_icr_idle(void) { }
486481
static inline u32 safe_apic_wait_icr_idle(void) { return 0; }
487-
static inline void apic_set_eoi_cb(void (*eoi)(void)) {}
488482
static inline void apic_native_eoi(void) { WARN_ON_ONCE(1); }
489483
static inline void apic_setup_apic_calls(void) { }
490484

@@ -512,8 +506,6 @@ static inline bool is_vector_pending(unsigned int vector)
512506
#define TRAMPOLINE_PHYS_LOW 0x467
513507
#define TRAMPOLINE_PHYS_HIGH 0x469
514508

515-
extern void generic_bigsmp_probe(void);
516-
517509
#ifdef CONFIG_X86_LOCAL_APIC
518510

519511
#include <asm/smp.h>
@@ -536,8 +528,6 @@ static inline int default_acpi_madt_oem_check(char *a, char *b) { return 0; }
536528
static inline void x86_64_probe_apic(void) { }
537529
#endif
538530

539-
extern int default_apic_id_valid(u32 apicid);
540-
541531
extern u32 apic_default_calc_apicid(unsigned int cpu);
542532
extern u32 apic_flat_calc_apicid(unsigned int cpu);
543533

arch/x86/include/asm/irq_vectors.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@
1818
* Vectors 0 ... 31 : system traps and exceptions - hardcoded events
1919
* Vectors 32 ... 127 : device interrupts
2020
* Vector 128 : legacy int80 syscall interface
21-
* Vectors 129 ... LOCAL_TIMER_VECTOR-1
22-
* Vectors LOCAL_TIMER_VECTOR ... 255 : special interrupts
21+
* Vectors 129 ... FIRST_SYSTEM_VECTOR-1 : device interrupts
22+
* Vectors FIRST_SYSTEM_VECTOR ... 255 : special interrupts
2323
*
2424
* 64-bit x86 has per CPU IDT tables, 32-bit has one shared IDT table.
2525
*

arch/x86/kernel/apic/apic.c

Lines changed: 35 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -677,7 +677,7 @@ calibrate_by_pmtimer(u32 deltapm, long *delta, long *deltatsc)
677677
return -1;
678678
#endif
679679

680-
apic_printk(APIC_VERBOSE, "... PM-Timer delta = %u\n", deltapm);
680+
apic_pr_verbose("... PM-Timer delta = %u\n", deltapm);
681681

682682
/* Check, if the PM timer is available */
683683
if (!deltapm)
@@ -687,14 +687,14 @@ calibrate_by_pmtimer(u32 deltapm, long *delta, long *deltatsc)
687687

688688
if (deltapm > (pm_100ms - pm_thresh) &&
689689
deltapm < (pm_100ms + pm_thresh)) {
690-
apic_printk(APIC_VERBOSE, "... PM-Timer result ok\n");
690+
apic_pr_verbose("... PM-Timer result ok\n");
691691
return 0;
692692
}
693693

694694
res = (((u64)deltapm) * mult) >> 22;
695695
do_div(res, 1000000);
696-
pr_warn("APIC calibration not consistent "
697-
"with PM-Timer: %ldms instead of 100ms\n", (long)res);
696+
pr_warn("APIC calibration not consistent with PM-Timer: %ldms instead of 100ms\n",
697+
(long)res);
698698

699699
/* Correct the lapic counter value */
700700
res = (((u64)(*delta)) * pm_100ms);
@@ -707,9 +707,8 @@ calibrate_by_pmtimer(u32 deltapm, long *delta, long *deltatsc)
707707
if (boot_cpu_has(X86_FEATURE_TSC)) {
708708
res = (((u64)(*deltatsc)) * pm_100ms);
709709
do_div(res, deltapm);
710-
apic_printk(APIC_VERBOSE, "TSC delta adjusted to "
711-
"PM-Timer: %lu (%ld)\n",
712-
(unsigned long)res, *deltatsc);
710+
apic_pr_verbose("TSC delta adjusted to PM-Timer: %lu (%ld)\n",
711+
(unsigned long)res, *deltatsc);
713712
*deltatsc = (long)res;
714713
}
715714

@@ -792,8 +791,7 @@ static int __init calibrate_APIC_clock(void)
792791
* in the clockevent structure and return.
793792
*/
794793
if (!lapic_init_clockevent()) {
795-
apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
796-
lapic_timer_period);
794+
apic_pr_verbose("lapic timer already calibrated %d\n", lapic_timer_period);
797795
/*
798796
* Direct calibration methods must have an always running
799797
* local APIC timer, no need for broadcast timer.
@@ -802,8 +800,7 @@ static int __init calibrate_APIC_clock(void)
802800
return 0;
803801
}
804802

805-
apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
806-
"calibrating APIC timer ...\n");
803+
apic_pr_verbose("Using local APIC timer interrupts. Calibrating APIC timer ...\n");
807804

808805
/*
809806
* There are platforms w/o global clockevent devices. Instead of
@@ -866,7 +863,7 @@ static int __init calibrate_APIC_clock(void)
866863

867864
/* Build delta t1-t2 as apic timer counts down */
868865
delta = lapic_cal_t1 - lapic_cal_t2;
869-
apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta);
866+
apic_pr_verbose("... lapic delta = %ld\n", delta);
870867

871868
deltatsc = (long)(lapic_cal_tsc2 - lapic_cal_tsc1);
872869

@@ -877,22 +874,19 @@ static int __init calibrate_APIC_clock(void)
877874
lapic_timer_period = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
878875
lapic_init_clockevent();
879876

880-
apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta);
881-
apic_printk(APIC_VERBOSE, "..... mult: %u\n", lapic_clockevent.mult);
882-
apic_printk(APIC_VERBOSE, "..... calibration result: %u\n",
883-
lapic_timer_period);
877+
apic_pr_verbose("..... delta %ld\n", delta);
878+
apic_pr_verbose("..... mult: %u\n", lapic_clockevent.mult);
879+
apic_pr_verbose("..... calibration result: %u\n", lapic_timer_period);
884880

885881
if (boot_cpu_has(X86_FEATURE_TSC)) {
886-
apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
887-
"%ld.%04ld MHz.\n",
888-
(deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ),
889-
(deltatsc / LAPIC_CAL_LOOPS) % (1000000 / HZ));
882+
apic_pr_verbose("..... CPU clock speed is %ld.%04ld MHz.\n",
883+
(deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ),
884+
(deltatsc / LAPIC_CAL_LOOPS) % (1000000 / HZ));
890885
}
891886

892-
apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
893-
"%u.%04u MHz.\n",
894-
lapic_timer_period / (1000000 / HZ),
895-
lapic_timer_period % (1000000 / HZ));
887+
apic_pr_verbose("..... host bus clock speed is %u.%04u MHz.\n",
888+
lapic_timer_period / (1000000 / HZ),
889+
lapic_timer_period % (1000000 / HZ));
896890

897891
/*
898892
* Do a sanity check on the APIC calibration result
@@ -911,7 +905,7 @@ static int __init calibrate_APIC_clock(void)
911905
* available.
912906
*/
913907
if (!pm_referenced && global_clock_event) {
914-
apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
908+
apic_pr_verbose("... verify APIC timer\n");
915909

916910
/*
917911
* Setup the apic timer manually
@@ -932,11 +926,11 @@ static int __init calibrate_APIC_clock(void)
932926

933927
/* Jiffies delta */
934928
deltaj = lapic_cal_j2 - lapic_cal_j1;
935-
apic_printk(APIC_VERBOSE, "... jiffies delta = %lu\n", deltaj);
929+
apic_pr_verbose("... jiffies delta = %lu\n", deltaj);
936930

937931
/* Check, if the jiffies result is consistent */
938932
if (deltaj >= LAPIC_CAL_LOOPS-2 && deltaj <= LAPIC_CAL_LOOPS+2)
939-
apic_printk(APIC_VERBOSE, "... jiffies result ok\n");
933+
apic_pr_verbose("... jiffies result ok\n");
940934
else
941935
levt->features |= CLOCK_EVT_FEAT_DUMMY;
942936
}
@@ -1221,9 +1215,8 @@ void __init sync_Arb_IDs(void)
12211215
*/
12221216
apic_wait_icr_idle();
12231217

1224-
apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n");
1225-
apic_write(APIC_ICR, APIC_DEST_ALLINC |
1226-
APIC_INT_LEVELTRIG | APIC_DM_INIT);
1218+
apic_pr_debug("Synchronizing Arb IDs.\n");
1219+
apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT);
12271220
}
12281221

12291222
enum apic_intr_mode_id apic_intr_mode __ro_after_init;
@@ -1409,10 +1402,10 @@ static void lapic_setup_esr(void)
14091402
if (maxlvt > 3)
14101403
apic_write(APIC_ESR, 0);
14111404
value = apic_read(APIC_ESR);
1412-
if (value != oldvalue)
1413-
apic_printk(APIC_VERBOSE, "ESR value before enabling "
1414-
"vector: 0x%08x after: 0x%08x\n",
1415-
oldvalue, value);
1405+
if (value != oldvalue) {
1406+
apic_pr_verbose("ESR value before enabling vector: 0x%08x after: 0x%08x\n",
1407+
oldvalue, value);
1408+
}
14161409
}
14171410

14181411
#define APIC_IR_REGS APIC_ISR_NR
@@ -1599,10 +1592,10 @@ static void setup_local_APIC(void)
15991592
value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
16001593
if (!cpu && (pic_mode || !value || ioapic_is_disabled)) {
16011594
value = APIC_DM_EXTINT;
1602-
apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", cpu);
1595+
apic_pr_verbose("Enabled ExtINT on CPU#%d\n", cpu);
16031596
} else {
16041597
value = APIC_DM_EXTINT | APIC_LVT_MASKED;
1605-
apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", cpu);
1598+
apic_pr_verbose("Masked ExtINT on CPU#%d\n", cpu);
16061599
}
16071600
apic_write(APIC_LVT0, value);
16081601

@@ -2067,8 +2060,7 @@ static __init void apic_set_fixmap(bool read_apic)
20672060
{
20682061
set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
20692062
apic_mmio_base = APIC_BASE;
2070-
apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
2071-
apic_mmio_base, mp_lapic_addr);
2063+
apic_pr_verbose("Mapped APIC to %16lx (%16lx)\n", apic_mmio_base, mp_lapic_addr);
20722064
if (read_apic)
20732065
apic_read_boot_cpu_id(false);
20742066
}
@@ -2171,18 +2163,17 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_error_interrupt)
21712163
apic_eoi();
21722164
atomic_inc(&irq_err_count);
21732165

2174-
apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x",
2175-
smp_processor_id(), v);
2166+
apic_pr_debug("APIC error on CPU%d: %02x", smp_processor_id(), v);
21762167

21772168
v &= 0xff;
21782169
while (v) {
21792170
if (v & 0x1)
2180-
apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]);
2171+
apic_pr_debug_cont(" : %s", error_interrupt_reason[i]);
21812172
i++;
21822173
v >>= 1;
21832174
}
21842175

2185-
apic_printk(APIC_DEBUG, KERN_CONT "\n");
2176+
apic_pr_debug_cont("\n");
21862177

21872178
trace_error_apic_exit(ERROR_APIC_VECTOR);
21882179
}
@@ -2202,8 +2193,7 @@ static void __init connect_bsp_APIC(void)
22022193
* PIC mode, enable APIC mode in the IMCR, i.e. connect BSP's
22032194
* local APIC to INT and NMI lines.
22042195
*/
2205-
apic_printk(APIC_VERBOSE, "leaving PIC mode, "
2206-
"enabling APIC mode.\n");
2196+
apic_pr_verbose("Leaving PIC mode, enabling APIC mode.\n");
22072197
imcr_pic_to_apic();
22082198
}
22092199
#endif
@@ -2228,8 +2218,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
22282218
* IPIs, won't work beyond this point! The only exception are
22292219
* INIT IPIs.
22302220
*/
2231-
apic_printk(APIC_VERBOSE, "disabling APIC mode, "
2232-
"entering PIC mode.\n");
2221+
apic_pr_verbose("Disabling APIC mode, entering PIC mode.\n");
22332222
imcr_apic_to_pic();
22342223
return;
22352224
}

0 commit comments

Comments
 (0)