SMP pre2-2.3.43 is pretty unstable due to the x86 SMP TLB flush changes.
This patch fixes these bugs and cleans up the TLB changes so that it fits
nicer into the existing x86/SMP framework.
Changes in smp-2.3.43-B5:
- send IPIs only to CPUs which are affected. This ment that
send_IPI_single() was replaced by send_IPI_mask() (no slowdown at all
in smp_send_reschedule()), and that send_IPI_mask() from now on can
send IPIs to an arbitrary group of CPUs. This change was enabled by
the mm->cpu_vm_mask & recent TLB-changes and by the transition to
logical APIC addressing mode. Quad and 8-way systems should see a
noticeable cross-CPU TLB-flush cost reduction from this.
- got rid of the cpu_online_mask check - with the above change it's
unnecessery. (not online CPUs cannot have bits set in any
mm->cpu_vm_mask.)
- exported the check for cpu_mask into the global flush functions.
!cpu_mask is actually the common case, no need to call
flush_tlb_others() just to discover in 99% of the cases that we have
to return immediately. (inlining flush_tlb_others() is not good
either, it's a rather long function and is called from several
functions.)
- (small cleanups)
pre2-2.3.43 is now completely stable here.
-- mingo
Changes in smp-2.3.43-B1:
- reverses parts of the pgtable.h flush_tlb optimization. It's just too
complex to try to be too smart about flushing TLBs in an IRQ context.
This bug causes frequent SMP crashes on vanilla 2.3.42 and
pre2-2.3.43.
- adds Linus' suggested 'fuzzy parsing' fix to
IO_APIC_get_PCI_irq_vector() - this should fix some of the SMP + USB
problems reported. It might also introduce problems on other systems
so we'll see.
-- mingo
--- linux/include/asm-i386/pgtable.h.orig2 Tue Feb 8 02:30:13 2000
+++ linux/include/asm-i386/pgtable.h Tue Feb 8 02:56:32 2000
@@ -29,12 +29,13 @@
#define __flush_tlb() \
do { \
- __asm__ __volatile__ \
- ("movl %0, %%cr3;" \
- : \
- : "r" __pa(current->active_mm->pgd) \
- : "memory" \
- ); \
+ unsigned int tmpreg; \
+ \
+ __asm__ __volatile__( \
+ "movl %%cr3, %0; # flush TLB \n" \
+ "movl %0, %%cr3; \n" \
+ : "=r" (tmpreg) \
+ :: "memory"); \
} while (0)
/*
@@ -43,14 +44,16 @@
*/
#define __flush_tlb_global() \
do { \
+ unsigned int tmpreg; \
+ \
__asm__ __volatile__( \
- "movl %0, %%cr4; # turn off PGE \n" \
- "mov %2, %%cr3; # flush TLB \n" \
- "mov %1, %%cr4; # turn PGE back on \n" \
- : \
- : "r" (mmu_cr4_features), \
- "r" (mmu_cr4_features & ~X86_CR4_PGE), \
- "r" (__pa(current->active_mm->pgd)) \
+ "movl %1, %%cr4; # turn off PGE \n" \
+ "movl %%cr3, %0; # flush TLB \n" \
+ "movl %0, %%cr3; \n" \
+ "movl %2, %%cr4; # turn PGE back on \n" \
+ : "=r" (tmpreg) \
+ : "r" (mmu_cr4_features & ~X86_CR4_PGE), \
+ "r" (mmu_cr4_features) \
: "memory"); \
} while (0)
--- linux/arch/i386/kernel/io_apic.c.orig2 Tue Feb 8 02:26:07 2000
+++ linux/arch/i386/kernel/io_apic.c Tue Feb 8 02:31:26 2000
@@ -223,7 +223,7 @@
static int __init pin_2_irq(int idx, int apic, int pin);
int IO_APIC_get_PCI_irq_vector(int bus, int slot, int pci_pin)
{
- int apic, i;
+ int apic, i, best_guess = -1;
for (i = 0; i < mp_irq_entries; i++) {
int lbus = mp_irqs[i].mpc_srcbus;
@@ -236,10 +236,18 @@
(mp_bus_id_to_type[lbus] == MP_BUS_PCI) &&
!mp_irqs[i].mpc_irqtype &&
(bus == mp_bus_id_to_pci_bus[mp_irqs[i].mpc_srcbus]) &&
- (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f)) &&
- (pci_pin == (mp_irqs[i].mpc_srcbusirq & 3)))
+ (slot == ((mp_irqs[i].mpc_srcbusirq >> 2) & 0x1f))) {
+ int irq = pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
- return pin_2_irq(i,apic,mp_irqs[i].mpc_dstirq);
+ if (pci_pin == (mp_irqs[i].mpc_srcbusirq & 3))
+ return irq;
+ /*
+ * Use the first all-but-pin matching entry as a
+ * best-guess fuzzy result for broken mptables.
+ */
+ if (best_guess < 0)
+ best_guess = irq;
+ }
}
return -1;
}
--- linux/arch/i386/kernel/pci-pc.c.orig2 Tue Feb 8 02:25:45 2000
+++ linux/arch/i386/kernel/pci-pc.c Tue Feb 8 02:29:55 2000
@@ -1132,6 +1132,10 @@
if (pin) {
pin--; /* interrupt pins are numbered
starting from 1 */
irq = IO_APIC_get_PCI_irq_vector(dev->bus->number,
PCI_SLOT(dev->devfn), pin);
+/*
+ * Will be removed completely if things work out well with fuzzy parsing
+ */
+#if 0
if (irq < 0 && dev->bus->parent) { /* go back to the
bridge */
struct pci_dev * bridge = dev->bus->self;
@@ -1142,6 +1146,7 @@
printk(KERN_WARNING "PCI: using
PPB(B%d,I%d,P%d) to get irq %d\n",
bridge->bus->number,
PCI_SLOT(bridge->devfn), pin, irq);
}
+#endif
if (irq >= 0) {
printk("PCI->APIC IRQ transform: (B%d,I%d,P%d)
-> %d\n",
dev->bus->number,
PCI_SLOT(dev->devfn), pin, irq);