mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-12-04 01:24:12 +08:00
Updates for the x86 APIC code:
- 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. -----BEGIN PGP SIGNATURE----- iQJHBAABCgAxFiEEQp8+kY+LLUocC4bMphj1TA10mKEFAmbpL0gTHHRnbHhAbGlu dXRyb25peC5kZQAKCRCmGPVMDXSYob/VD/984H4Ku5/Djq9HkhBO11hfRTIVz/uf 1/b5ogd3eN0dK5nAv79/Gj7E/zntVsvCjuCYckXz51xPxkQH2LxUhDKqeUwg5lmz xQV0mKK4fIS/g5yymQGplKc7FfjRAnVL9ZZRRvMkvtqbr1+dA665XrfjFAPkp929 zLaBUbNC6YxYfSddsV+fE8711QP6NzCYdeEBIdZ3NuBrlGfiLy1g1OWCk8za7zjM cLJfGnU63MNXI4smrZWrQwJDBOiQl1wPbJYWL216OPHofLzLNGNZFXm4y8OJcyN0 WPWn1TliAwpRYx18Z/cEPgkoES8mXqqpPcoo0yBjOmPLl31J6QYU7QQhDb3HOnM/ ALgnnuhoWll5YjNBPJkONAa7lpnmfTbEg82WxaipEscz9CyEBoeOLvYBGPl/YqV+ B8wMOZHDH+BchJ6rYXDA1AmkD+9q86F+ddbiVOKj09dVm/QeLrGjwox1O7yGALGZ hZPQx9MsTOJqQIh40PsqFko6OiMKuMBIebacFb4NqmVA2/WbRbcmkzRyxk+kkBFv UMZX5O6sQhat615WZkxTnjmdnXETTIlv4nRQURBd/LF6ECRkXXG11dWaZfTXZ9iW 8NNlHw8mIbGmzn7wWXHlhk7N7vuhWCikAf7V2y+eZUVtE56qGM2volJNCmTZacP2 rrjmltwEGR+5gg== =Y3a/ -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
61d1ea914b
@ -18,6 +18,11 @@
|
||||
|
||||
#define ARCH_APICTIMER_STOPS_ON_C3 1
|
||||
|
||||
/* Macros for apic_extnmi which controls external NMI masking */
|
||||
#define APIC_EXTNMI_BSP 0 /* Default */
|
||||
#define APIC_EXTNMI_ALL 1
|
||||
#define APIC_EXTNMI_NONE 2
|
||||
|
||||
/*
|
||||
* Debugging macros
|
||||
*/
|
||||
@ -25,22 +30,22 @@
|
||||
#define APIC_VERBOSE 1
|
||||
#define APIC_DEBUG 2
|
||||
|
||||
/* Macros for apic_extnmi which controls external NMI masking */
|
||||
#define APIC_EXTNMI_BSP 0 /* Default */
|
||||
#define APIC_EXTNMI_ALL 1
|
||||
#define APIC_EXTNMI_NONE 2
|
||||
|
||||
/*
|
||||
* Define the default level of output to be very little
|
||||
* This can be turned up by using apic=verbose for more
|
||||
* information and apic=debug for _lots_ of information.
|
||||
* apic_verbosity is defined in apic.c
|
||||
* Define the default level of output to be very little This can be turned
|
||||
* up by using apic=verbose for more information and apic=debug for _lots_
|
||||
* of information. apic_verbosity is defined in apic.c
|
||||
*/
|
||||
#define apic_printk(v, s, a...) do { \
|
||||
if ((v) <= apic_verbosity) \
|
||||
printk(s, ##a); \
|
||||
} while (0)
|
||||
#define apic_printk(v, s, a...) \
|
||||
do { \
|
||||
if ((v) <= apic_verbosity) \
|
||||
printk(s, ##a); \
|
||||
} while (0)
|
||||
|
||||
#define apic_pr_verbose(s, a...) apic_printk(APIC_VERBOSE, KERN_INFO s, ##a)
|
||||
#define apic_pr_debug(s, a...) apic_printk(APIC_DEBUG, KERN_DEBUG s, ##a)
|
||||
#define apic_pr_debug_cont(s, a...) apic_printk(APIC_DEBUG, KERN_CONT s, ##a)
|
||||
/* Unconditional debug prints for code which is guarded by apic_verbosity already */
|
||||
#define apic_dbg(s, a...) printk(KERN_DEBUG s, ##a)
|
||||
|
||||
#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32)
|
||||
extern void x86_32_probe_apic(void);
|
||||
@ -122,8 +127,6 @@ static inline bool apic_is_x2apic_enabled(void)
|
||||
|
||||
extern void enable_IR_x2apic(void);
|
||||
|
||||
extern int get_physical_broadcast(void);
|
||||
|
||||
extern int lapic_get_maxlvt(void);
|
||||
extern void clear_local_APIC(void);
|
||||
extern void disconnect_bsp_APIC(int virt_wire_setup);
|
||||
@ -345,20 +348,12 @@ extern struct apic *apic;
|
||||
* APIC drivers are probed based on how they are listed in the .apicdrivers
|
||||
* section. So the order is important and enforced by the ordering
|
||||
* of different apic driver files in the Makefile.
|
||||
*
|
||||
* For the files having two apic drivers, we use apic_drivers()
|
||||
* to enforce the order with in them.
|
||||
*/
|
||||
#define apic_driver(sym) \
|
||||
static const struct apic *__apicdrivers_##sym __used \
|
||||
__aligned(sizeof(struct apic *)) \
|
||||
__section(".apicdrivers") = { &sym }
|
||||
|
||||
#define apic_drivers(sym1, sym2) \
|
||||
static struct apic *__apicdrivers_##sym1##sym2[2] __used \
|
||||
__aligned(sizeof(struct apic *)) \
|
||||
__section(".apicdrivers") = { &sym1, &sym2 }
|
||||
|
||||
extern struct apic *__apicdrivers[], *__apicdrivers_end[];
|
||||
|
||||
/*
|
||||
@ -484,7 +479,6 @@ static inline u64 apic_icr_read(void) { return 0; }
|
||||
static inline void apic_icr_write(u32 low, u32 high) { }
|
||||
static inline void apic_wait_icr_idle(void) { }
|
||||
static inline u32 safe_apic_wait_icr_idle(void) { return 0; }
|
||||
static inline void apic_set_eoi_cb(void (*eoi)(void)) {}
|
||||
static inline void apic_native_eoi(void) { WARN_ON_ONCE(1); }
|
||||
static inline void apic_setup_apic_calls(void) { }
|
||||
|
||||
@ -512,8 +506,6 @@ static inline bool is_vector_pending(unsigned int vector)
|
||||
#define TRAMPOLINE_PHYS_LOW 0x467
|
||||
#define TRAMPOLINE_PHYS_HIGH 0x469
|
||||
|
||||
extern void generic_bigsmp_probe(void);
|
||||
|
||||
#ifdef CONFIG_X86_LOCAL_APIC
|
||||
|
||||
#include <asm/smp.h>
|
||||
@ -536,8 +528,6 @@ static inline int default_acpi_madt_oem_check(char *a, char *b) { return 0; }
|
||||
static inline void x86_64_probe_apic(void) { }
|
||||
#endif
|
||||
|
||||
extern int default_apic_id_valid(u32 apicid);
|
||||
|
||||
extern u32 apic_default_calc_apicid(unsigned int cpu);
|
||||
extern u32 apic_flat_calc_apicid(unsigned int cpu);
|
||||
|
||||
|
@ -18,8 +18,8 @@
|
||||
* Vectors 0 ... 31 : system traps and exceptions - hardcoded events
|
||||
* Vectors 32 ... 127 : device interrupts
|
||||
* Vector 128 : legacy int80 syscall interface
|
||||
* Vectors 129 ... LOCAL_TIMER_VECTOR-1
|
||||
* Vectors LOCAL_TIMER_VECTOR ... 255 : special interrupts
|
||||
* Vectors 129 ... FIRST_SYSTEM_VECTOR-1 : device interrupts
|
||||
* Vectors FIRST_SYSTEM_VECTOR ... 255 : special interrupts
|
||||
*
|
||||
* 64-bit x86 has per CPU IDT tables, 32-bit has one shared IDT table.
|
||||
*
|
||||
|
@ -677,7 +677,7 @@ calibrate_by_pmtimer(u32 deltapm, long *delta, long *deltatsc)
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
apic_printk(APIC_VERBOSE, "... PM-Timer delta = %u\n", deltapm);
|
||||
apic_pr_verbose("... PM-Timer delta = %u\n", deltapm);
|
||||
|
||||
/* Check, if the PM timer is available */
|
||||
if (!deltapm)
|
||||
@ -687,14 +687,14 @@ calibrate_by_pmtimer(u32 deltapm, long *delta, long *deltatsc)
|
||||
|
||||
if (deltapm > (pm_100ms - pm_thresh) &&
|
||||
deltapm < (pm_100ms + pm_thresh)) {
|
||||
apic_printk(APIC_VERBOSE, "... PM-Timer result ok\n");
|
||||
apic_pr_verbose("... PM-Timer result ok\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
res = (((u64)deltapm) * mult) >> 22;
|
||||
do_div(res, 1000000);
|
||||
pr_warn("APIC calibration not consistent "
|
||||
"with PM-Timer: %ldms instead of 100ms\n", (long)res);
|
||||
pr_warn("APIC calibration not consistent with PM-Timer: %ldms instead of 100ms\n",
|
||||
(long)res);
|
||||
|
||||
/* Correct the lapic counter value */
|
||||
res = (((u64)(*delta)) * pm_100ms);
|
||||
@ -707,9 +707,8 @@ calibrate_by_pmtimer(u32 deltapm, long *delta, long *deltatsc)
|
||||
if (boot_cpu_has(X86_FEATURE_TSC)) {
|
||||
res = (((u64)(*deltatsc)) * pm_100ms);
|
||||
do_div(res, deltapm);
|
||||
apic_printk(APIC_VERBOSE, "TSC delta adjusted to "
|
||||
"PM-Timer: %lu (%ld)\n",
|
||||
(unsigned long)res, *deltatsc);
|
||||
apic_pr_verbose("TSC delta adjusted to PM-Timer: %lu (%ld)\n",
|
||||
(unsigned long)res, *deltatsc);
|
||||
*deltatsc = (long)res;
|
||||
}
|
||||
|
||||
@ -792,8 +791,7 @@ static int __init calibrate_APIC_clock(void)
|
||||
* in the clockevent structure and return.
|
||||
*/
|
||||
if (!lapic_init_clockevent()) {
|
||||
apic_printk(APIC_VERBOSE, "lapic timer already calibrated %d\n",
|
||||
lapic_timer_period);
|
||||
apic_pr_verbose("lapic timer already calibrated %d\n", lapic_timer_period);
|
||||
/*
|
||||
* Direct calibration methods must have an always running
|
||||
* local APIC timer, no need for broadcast timer.
|
||||
@ -802,8 +800,7 @@ static int __init calibrate_APIC_clock(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
apic_printk(APIC_VERBOSE, "Using local APIC timer interrupts.\n"
|
||||
"calibrating APIC timer ...\n");
|
||||
apic_pr_verbose("Using local APIC timer interrupts. Calibrating APIC timer ...\n");
|
||||
|
||||
/*
|
||||
* There are platforms w/o global clockevent devices. Instead of
|
||||
@ -866,7 +863,7 @@ static int __init calibrate_APIC_clock(void)
|
||||
|
||||
/* Build delta t1-t2 as apic timer counts down */
|
||||
delta = lapic_cal_t1 - lapic_cal_t2;
|
||||
apic_printk(APIC_VERBOSE, "... lapic delta = %ld\n", delta);
|
||||
apic_pr_verbose("... lapic delta = %ld\n", delta);
|
||||
|
||||
deltatsc = (long)(lapic_cal_tsc2 - lapic_cal_tsc1);
|
||||
|
||||
@ -877,22 +874,19 @@ static int __init calibrate_APIC_clock(void)
|
||||
lapic_timer_period = (delta * APIC_DIVISOR) / LAPIC_CAL_LOOPS;
|
||||
lapic_init_clockevent();
|
||||
|
||||
apic_printk(APIC_VERBOSE, "..... delta %ld\n", delta);
|
||||
apic_printk(APIC_VERBOSE, "..... mult: %u\n", lapic_clockevent.mult);
|
||||
apic_printk(APIC_VERBOSE, "..... calibration result: %u\n",
|
||||
lapic_timer_period);
|
||||
apic_pr_verbose("..... delta %ld\n", delta);
|
||||
apic_pr_verbose("..... mult: %u\n", lapic_clockevent.mult);
|
||||
apic_pr_verbose("..... calibration result: %u\n", lapic_timer_period);
|
||||
|
||||
if (boot_cpu_has(X86_FEATURE_TSC)) {
|
||||
apic_printk(APIC_VERBOSE, "..... CPU clock speed is "
|
||||
"%ld.%04ld MHz.\n",
|
||||
(deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ),
|
||||
(deltatsc / LAPIC_CAL_LOOPS) % (1000000 / HZ));
|
||||
apic_pr_verbose("..... CPU clock speed is %ld.%04ld MHz.\n",
|
||||
(deltatsc / LAPIC_CAL_LOOPS) / (1000000 / HZ),
|
||||
(deltatsc / LAPIC_CAL_LOOPS) % (1000000 / HZ));
|
||||
}
|
||||
|
||||
apic_printk(APIC_VERBOSE, "..... host bus clock speed is "
|
||||
"%u.%04u MHz.\n",
|
||||
lapic_timer_period / (1000000 / HZ),
|
||||
lapic_timer_period % (1000000 / HZ));
|
||||
apic_pr_verbose("..... host bus clock speed is %u.%04u MHz.\n",
|
||||
lapic_timer_period / (1000000 / HZ),
|
||||
lapic_timer_period % (1000000 / HZ));
|
||||
|
||||
/*
|
||||
* Do a sanity check on the APIC calibration result
|
||||
@ -911,7 +905,7 @@ static int __init calibrate_APIC_clock(void)
|
||||
* available.
|
||||
*/
|
||||
if (!pm_referenced && global_clock_event) {
|
||||
apic_printk(APIC_VERBOSE, "... verify APIC timer\n");
|
||||
apic_pr_verbose("... verify APIC timer\n");
|
||||
|
||||
/*
|
||||
* Setup the apic timer manually
|
||||
@ -932,11 +926,11 @@ static int __init calibrate_APIC_clock(void)
|
||||
|
||||
/* Jiffies delta */
|
||||
deltaj = lapic_cal_j2 - lapic_cal_j1;
|
||||
apic_printk(APIC_VERBOSE, "... jiffies delta = %lu\n", deltaj);
|
||||
apic_pr_verbose("... jiffies delta = %lu\n", deltaj);
|
||||
|
||||
/* Check, if the jiffies result is consistent */
|
||||
if (deltaj >= LAPIC_CAL_LOOPS-2 && deltaj <= LAPIC_CAL_LOOPS+2)
|
||||
apic_printk(APIC_VERBOSE, "... jiffies result ok\n");
|
||||
apic_pr_verbose("... jiffies result ok\n");
|
||||
else
|
||||
levt->features |= CLOCK_EVT_FEAT_DUMMY;
|
||||
}
|
||||
@ -1221,9 +1215,8 @@ void __init sync_Arb_IDs(void)
|
||||
*/
|
||||
apic_wait_icr_idle();
|
||||
|
||||
apic_printk(APIC_DEBUG, "Synchronizing Arb IDs.\n");
|
||||
apic_write(APIC_ICR, APIC_DEST_ALLINC |
|
||||
APIC_INT_LEVELTRIG | APIC_DM_INIT);
|
||||
apic_pr_debug("Synchronizing Arb IDs.\n");
|
||||
apic_write(APIC_ICR, APIC_DEST_ALLINC | APIC_INT_LEVELTRIG | APIC_DM_INIT);
|
||||
}
|
||||
|
||||
enum apic_intr_mode_id apic_intr_mode __ro_after_init;
|
||||
@ -1409,10 +1402,10 @@ static void lapic_setup_esr(void)
|
||||
if (maxlvt > 3)
|
||||
apic_write(APIC_ESR, 0);
|
||||
value = apic_read(APIC_ESR);
|
||||
if (value != oldvalue)
|
||||
apic_printk(APIC_VERBOSE, "ESR value before enabling "
|
||||
"vector: 0x%08x after: 0x%08x\n",
|
||||
oldvalue, value);
|
||||
if (value != oldvalue) {
|
||||
apic_pr_verbose("ESR value before enabling vector: 0x%08x after: 0x%08x\n",
|
||||
oldvalue, value);
|
||||
}
|
||||
}
|
||||
|
||||
#define APIC_IR_REGS APIC_ISR_NR
|
||||
@ -1599,10 +1592,10 @@ static void setup_local_APIC(void)
|
||||
value = apic_read(APIC_LVT0) & APIC_LVT_MASKED;
|
||||
if (!cpu && (pic_mode || !value || ioapic_is_disabled)) {
|
||||
value = APIC_DM_EXTINT;
|
||||
apic_printk(APIC_VERBOSE, "enabled ExtINT on CPU#%d\n", cpu);
|
||||
apic_pr_verbose("Enabled ExtINT on CPU#%d\n", cpu);
|
||||
} else {
|
||||
value = APIC_DM_EXTINT | APIC_LVT_MASKED;
|
||||
apic_printk(APIC_VERBOSE, "masked ExtINT on CPU#%d\n", cpu);
|
||||
apic_pr_verbose("Masked ExtINT on CPU#%d\n", cpu);
|
||||
}
|
||||
apic_write(APIC_LVT0, value);
|
||||
|
||||
@ -2067,8 +2060,7 @@ static __init void apic_set_fixmap(bool read_apic)
|
||||
{
|
||||
set_fixmap_nocache(FIX_APIC_BASE, mp_lapic_addr);
|
||||
apic_mmio_base = APIC_BASE;
|
||||
apic_printk(APIC_VERBOSE, "mapped APIC to %16lx (%16lx)\n",
|
||||
apic_mmio_base, mp_lapic_addr);
|
||||
apic_pr_verbose("Mapped APIC to %16lx (%16lx)\n", apic_mmio_base, mp_lapic_addr);
|
||||
if (read_apic)
|
||||
apic_read_boot_cpu_id(false);
|
||||
}
|
||||
@ -2171,18 +2163,17 @@ DEFINE_IDTENTRY_SYSVEC(sysvec_error_interrupt)
|
||||
apic_eoi();
|
||||
atomic_inc(&irq_err_count);
|
||||
|
||||
apic_printk(APIC_DEBUG, KERN_DEBUG "APIC error on CPU%d: %02x",
|
||||
smp_processor_id(), v);
|
||||
apic_pr_debug("APIC error on CPU%d: %02x", smp_processor_id(), v);
|
||||
|
||||
v &= 0xff;
|
||||
while (v) {
|
||||
if (v & 0x1)
|
||||
apic_printk(APIC_DEBUG, KERN_CONT " : %s", error_interrupt_reason[i]);
|
||||
apic_pr_debug_cont(" : %s", error_interrupt_reason[i]);
|
||||
i++;
|
||||
v >>= 1;
|
||||
}
|
||||
|
||||
apic_printk(APIC_DEBUG, KERN_CONT "\n");
|
||||
apic_pr_debug_cont("\n");
|
||||
|
||||
trace_error_apic_exit(ERROR_APIC_VECTOR);
|
||||
}
|
||||
@ -2202,8 +2193,7 @@ static void __init connect_bsp_APIC(void)
|
||||
* PIC mode, enable APIC mode in the IMCR, i.e. connect BSP's
|
||||
* local APIC to INT and NMI lines.
|
||||
*/
|
||||
apic_printk(APIC_VERBOSE, "leaving PIC mode, "
|
||||
"enabling APIC mode.\n");
|
||||
apic_pr_verbose("Leaving PIC mode, enabling APIC mode.\n");
|
||||
imcr_pic_to_apic();
|
||||
}
|
||||
#endif
|
||||
@ -2228,8 +2218,7 @@ void disconnect_bsp_APIC(int virt_wire_setup)
|
||||
* IPIs, won't work beyond this point! The only exception are
|
||||
* INIT IPIs.
|
||||
*/
|
||||
apic_printk(APIC_VERBOSE, "disabling APIC mode, "
|
||||
"entering PIC mode.\n");
|
||||
apic_pr_verbose("Disabling APIC mode, entering PIC mode.\n");
|
||||
imcr_apic_to_pic();
|
||||
return;
|
||||
}
|
||||
|
@ -8,129 +8,25 @@
|
||||
* Martin Bligh, Andi Kleen, James Bottomley, John Stultz, and
|
||||
* James Cleverdon.
|
||||
*/
|
||||
#include <linux/cpumask.h>
|
||||
#include <linux/export.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#include <asm/jailhouse_para.h>
|
||||
#include <asm/apic.h>
|
||||
|
||||
#include "local.h"
|
||||
|
||||
static struct apic apic_physflat;
|
||||
static struct apic apic_flat;
|
||||
|
||||
struct apic *apic __ro_after_init = &apic_flat;
|
||||
EXPORT_SYMBOL_GPL(apic);
|
||||
|
||||
static int flat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _flat_send_IPI_mask(unsigned long mask, int vector)
|
||||
{
|
||||
unsigned long flags;
|
||||
|
||||
local_irq_save(flags);
|
||||
__default_send_IPI_dest_field(mask, vector, APIC_DEST_LOGICAL);
|
||||
local_irq_restore(flags);
|
||||
}
|
||||
|
||||
static void flat_send_IPI_mask(const struct cpumask *cpumask, int vector)
|
||||
{
|
||||
unsigned long mask = cpumask_bits(cpumask)[0];
|
||||
|
||||
_flat_send_IPI_mask(mask, vector);
|
||||
}
|
||||
|
||||
static void
|
||||
flat_send_IPI_mask_allbutself(const struct cpumask *cpumask, int vector)
|
||||
{
|
||||
unsigned long mask = cpumask_bits(cpumask)[0];
|
||||
int cpu = smp_processor_id();
|
||||
|
||||
if (cpu < BITS_PER_LONG)
|
||||
__clear_bit(cpu, &mask);
|
||||
|
||||
_flat_send_IPI_mask(mask, vector);
|
||||
}
|
||||
|
||||
static u32 flat_get_apic_id(u32 x)
|
||||
static u32 physflat_get_apic_id(u32 x)
|
||||
{
|
||||
return (x >> 24) & 0xFF;
|
||||
}
|
||||
|
||||
static int flat_probe(void)
|
||||
static int physflat_probe(void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct apic apic_flat __ro_after_init = {
|
||||
.name = "flat",
|
||||
.probe = flat_probe,
|
||||
.acpi_madt_oem_check = flat_acpi_madt_oem_check,
|
||||
|
||||
.dest_mode_logical = true,
|
||||
|
||||
.disable_esr = 0,
|
||||
|
||||
.init_apic_ldr = default_init_apic_ldr,
|
||||
.cpu_present_to_apicid = default_cpu_present_to_apicid,
|
||||
|
||||
.max_apic_id = 0xFE,
|
||||
.get_apic_id = flat_get_apic_id,
|
||||
|
||||
.calc_dest_apicid = apic_flat_calc_apicid,
|
||||
|
||||
.send_IPI = default_send_IPI_single,
|
||||
.send_IPI_mask = flat_send_IPI_mask,
|
||||
.send_IPI_mask_allbutself = flat_send_IPI_mask_allbutself,
|
||||
.send_IPI_allbutself = default_send_IPI_allbutself,
|
||||
.send_IPI_all = default_send_IPI_all,
|
||||
.send_IPI_self = default_send_IPI_self,
|
||||
.nmi_to_offline_cpu = true,
|
||||
|
||||
.read = native_apic_mem_read,
|
||||
.write = native_apic_mem_write,
|
||||
.eoi = native_apic_mem_eoi,
|
||||
.icr_read = native_apic_icr_read,
|
||||
.icr_write = native_apic_icr_write,
|
||||
.wait_icr_idle = apic_mem_wait_icr_idle,
|
||||
.safe_wait_icr_idle = apic_mem_wait_icr_idle_timeout,
|
||||
};
|
||||
|
||||
/*
|
||||
* Physflat mode is used when there are more than 8 CPUs on a system.
|
||||
* We cannot use logical delivery in this case because the mask
|
||||
* overflows, so use physical mode.
|
||||
*/
|
||||
static int physflat_acpi_madt_oem_check(char *oem_id, char *oem_table_id)
|
||||
{
|
||||
#ifdef CONFIG_ACPI
|
||||
/*
|
||||
* Quirk: some x86_64 machines can only use physical APIC mode
|
||||
* regardless of how many processors are present (x86_64 ES7000
|
||||
* is an example).
|
||||
*/
|
||||
if (acpi_gbl_FADT.header.revision >= FADT2_REVISION_ID &&
|
||||
(acpi_gbl_FADT.flags & ACPI_FADT_APIC_PHYSICAL)) {
|
||||
printk(KERN_DEBUG "system APIC only can use physical flat");
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (!strncmp(oem_id, "IBM", 3) && !strncmp(oem_table_id, "EXA", 3)) {
|
||||
printk(KERN_DEBUG "IBM Summit detected, will use apic physical");
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int physflat_probe(void)
|
||||
{
|
||||
return apic == &apic_physflat || num_possible_cpus() > 8 || jailhouse_paravirt();
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct apic apic_physflat __ro_after_init = {
|
||||
@ -146,7 +42,7 @@ static struct apic apic_physflat __ro_after_init = {
|
||||
.cpu_present_to_apicid = default_cpu_present_to_apicid,
|
||||
|
||||
.max_apic_id = 0xFE,
|
||||
.get_apic_id = flat_get_apic_id,
|
||||
.get_apic_id = physflat_get_apic_id,
|
||||
|
||||
.calc_dest_apicid = apic_default_calc_apicid,
|
||||
|
||||
@ -166,8 +62,7 @@ static struct apic apic_physflat __ro_after_init = {
|
||||
.wait_icr_idle = apic_mem_wait_icr_idle,
|
||||
.safe_wait_icr_idle = apic_mem_wait_icr_idle_timeout,
|
||||
};
|
||||
apic_driver(apic_physflat);
|
||||
|
||||
/*
|
||||
* We need to check for physflat first, so this order is important.
|
||||
*/
|
||||
apic_drivers(apic_physflat, apic_flat);
|
||||
struct apic *apic __ro_after_init = &apic_physflat;
|
||||
EXPORT_SYMBOL_GPL(apic);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -68,7 +68,7 @@ static void __init mpc_oem_bus_info(struct mpc_bus *m, char *str)
|
||||
{
|
||||
memcpy(str, m->bustype, 6);
|
||||
str[6] = 0;
|
||||
apic_printk(APIC_VERBOSE, "Bus #%d is %s\n", m->busid, str);
|
||||
apic_pr_verbose("Bus #%d is %s\n", m->busid, str);
|
||||
}
|
||||
|
||||
static void __init MP_bus_info(struct mpc_bus *m)
|
||||
@ -417,7 +417,7 @@ static unsigned long __init get_mpc_size(unsigned long physptr)
|
||||
mpc = early_memremap(physptr, PAGE_SIZE);
|
||||
size = mpc->length;
|
||||
early_memunmap(mpc, PAGE_SIZE);
|
||||
apic_printk(APIC_VERBOSE, " mpc: %lx-%lx\n", physptr, physptr + size);
|
||||
apic_pr_verbose(" mpc: %lx-%lx\n", physptr, physptr + size);
|
||||
|
||||
return size;
|
||||
}
|
||||
@ -560,8 +560,7 @@ static int __init smp_scan_config(unsigned long base, unsigned long length)
|
||||
struct mpf_intel *mpf;
|
||||
int ret = 0;
|
||||
|
||||
apic_printk(APIC_VERBOSE, "Scan for SMP in [mem %#010lx-%#010lx]\n",
|
||||
base, base + length - 1);
|
||||
apic_pr_verbose("Scan for SMP in [mem %#010lx-%#010lx]\n", base, base + length - 1);
|
||||
BUILD_BUG_ON(sizeof(*mpf) != 16);
|
||||
|
||||
while (length > 0) {
|
||||
@ -683,13 +682,13 @@ static void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare)
|
||||
{
|
||||
int i;
|
||||
|
||||
apic_printk(APIC_VERBOSE, "OLD ");
|
||||
apic_pr_verbose("OLD ");
|
||||
print_mp_irq_info(m);
|
||||
|
||||
i = get_MP_intsrc_index(m);
|
||||
if (i > 0) {
|
||||
memcpy(m, &mp_irqs[i], sizeof(*m));
|
||||
apic_printk(APIC_VERBOSE, "NEW ");
|
||||
apic_pr_verbose("NEW ");
|
||||
print_mp_irq_info(&mp_irqs[i]);
|
||||
return;
|
||||
}
|
||||
@ -772,7 +771,7 @@ static int __init replace_intsrc_all(struct mpc_table *mpc,
|
||||
continue;
|
||||
|
||||
if (nr_m_spare > 0) {
|
||||
apic_printk(APIC_VERBOSE, "*NEW* found\n");
|
||||
apic_pr_verbose("*NEW* found\n");
|
||||
nr_m_spare--;
|
||||
memcpy(m_spare[nr_m_spare], &mp_irqs[i], sizeof(mp_irqs[i]));
|
||||
m_spare[nr_m_spare] = NULL;
|
||||
|
@ -1352,12 +1352,11 @@ static void intel_irq_remapping_prepare_irte(struct intel_ir_data *data,
|
||||
case X86_IRQ_ALLOC_TYPE_IOAPIC:
|
||||
/* Set source-id of interrupt request */
|
||||
set_ioapic_sid(irte, info->devid);
|
||||
apic_printk(APIC_VERBOSE, KERN_DEBUG "IOAPIC[%d]: Set IRTE entry (P:%d FPD:%d Dst_Mode:%d Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X Avail:%X Vector:%02X Dest:%08X SID:%04X SQ:%X SVT:%X)\n",
|
||||
info->devid, irte->present, irte->fpd,
|
||||
irte->dst_mode, irte->redir_hint,
|
||||
irte->trigger_mode, irte->dlvry_mode,
|
||||
irte->avail, irte->vector, irte->dest_id,
|
||||
irte->sid, irte->sq, irte->svt);
|
||||
apic_pr_verbose("IOAPIC[%d]: Set IRTE entry (P:%d FPD:%d Dst_Mode:%d Redir_hint:%d Trig_Mode:%d Dlvry_Mode:%X Avail:%X Vector:%02X Dest:%08X SID:%04X SQ:%X SVT:%X)\n",
|
||||
info->devid, irte->present, irte->fpd, irte->dst_mode,
|
||||
irte->redir_hint, irte->trigger_mode, irte->dlvry_mode,
|
||||
irte->avail, irte->vector, irte->dest_id, irte->sid,
|
||||
irte->sq, irte->svt);
|
||||
sub_handle = info->ioapic.pin;
|
||||
break;
|
||||
case X86_IRQ_ALLOC_TYPE_HPET:
|
||||
|
Loading…
Reference in New Issue
Block a user