--- 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/smp.c.orig2 Tue Feb 8 03:19:24 2000 +++ linux/arch/i386/kernel/smp.c Tue Feb 8 04:02:28 2000 @@ -185,15 +185,15 @@ return cfg; } -static inline int __prepare_ICR2 (unsigned int dest) +static inline int __prepare_ICR2 (unsigned int mask) { unsigned int cfg; cfg = __get_ICR2(); #if LOGICAL_DELIVERY - cfg |= SET_APIC_DEST_FIELD((1< */ -#define TLB_PARANOIA 1 static volatile unsigned long flush_cpumask; static struct mm_struct * flush_mm; static unsigned long flush_va; -#define FLUSH_ALL 0xFFFFffff +static spinlock_t tlbstate_lock = SPIN_LOCK_UNLOCKED; +#define FLUSH_ALL 0xffffffff -static void inline leave_mm(unsigned long cpu) +static void inline leave_mm (unsigned long cpu) { -#ifdef TLB_PARANOIA - if(cpu_tlbstate[cpu].state == TLBSTATE_OK) + if (cpu_tlbstate[cpu].state == TLBSTATE_OK) BUG(); -#endif clear_bit(cpu, &cpu_tlbstate[cpu].active_mm->cpu_vm_mask); cpu_tlbstate[cpu].state = TLBSTATE_OLD; } @@ -335,109 +333,91 @@ * instead update cpu_tlbstate. */ -asmlinkage void smp_invalidate_interrupt(void) +asmlinkage void smp_invalidate_interrupt (void) { unsigned long cpu = smp_processor_id(); if (flush_mm == cpu_tlbstate[cpu].active_mm) { if (cpu_tlbstate[cpu].state == TLBSTATE_OK) { - if(flush_va == FLUSH_ALL) + if (flush_va == FLUSH_ALL) local_flush_tlb(); - else - __flush_tlb_one(flush_va); - } else { + else + __flush_tlb_one(flush_va); + } else leave_mm(cpu); - } } ack_APIC_irq(); clear_bit(cpu, &flush_cpumask); } -static void flush_tlb_others(unsigned long cpumask, struct mm_struct *mm, unsigned long va) +static void flush_tlb_others (unsigned long cpumask, struct mm_struct *mm, + unsigned long va) { -#ifdef TLB_PARANOIA - if(in_interrupt()) { - printk(KERN_EMERG "tlb flush from interrupt: %d,%d", - local_bh_count[smp_processor_id()], - local_irq_count[smp_processor_id()]); - } - if(cpumask & (1< 0) { - limit--; - printk(KERN_EMERG "flush_tlb_others: possible lock-up, broken!(%d)", - flags); -/* show_stack(NULL);*/ - } - sti(); - } - } -#endif - cpumask &= cpu_online_map; + /* + * A couple of (to be removed) sanity checks: + * + * - we do not send IPIs to not-yet booted CPUs. + * - current CPU must not be in mask + * - mask must exist :) + */ + if (!cpumask) + BUG(); + if ((cpumask & cpu_online_map) != cpumask) + BUG(); + if (cpumask & (1 << smp_processor_id())) + BUG(); /* - * it's important that we do not generate any APIC traffic - * until the AP CPUs have booted up! + * i'm not happy about this global shared spinlock in the + * MM hot path, but we'll see how contended it is. */ - if (cpumask) { -static spinlock_t lock = SPIN_LOCK_UNLOCKED; - spin_lock(&lock); - - flush_mm = mm; - flush_va = va; - atomic_set_mask(cpumask, &flush_cpumask); - send_IPI_allbutself(INVALIDATE_TLB_VECTOR); - - while (flush_cpumask) { - /* FIXME: lockup-detection, print backtrace on - * lock-up - */ - } - flush_mm = NULL; - flush_va = 0; - spin_unlock(&lock); - } + spin_lock(&tlbstate_lock); + + flush_mm = mm; + flush_va = va; + atomic_set_mask(cpumask, &flush_cpumask); + /* + * We have to send the IPI only to + * CPUs affected. + */ + send_IPI_mask(cpumask, INVALIDATE_TLB_VECTOR); + + while (flush_cpumask) + /* nothing. lockup detection does not belong here */; + + flush_mm = NULL; + flush_va = 0; + spin_unlock(&tlbstate_lock); } void flush_tlb_current_task(void) { - unsigned long vm_mask = 1 << smp_processor_id(); struct mm_struct *mm = current->mm; - unsigned long cpu_mask = mm->cpu_vm_mask & ~vm_mask; + unsigned long cpu_mask = mm->cpu_vm_mask & ~(1 << smp_processor_id()); local_flush_tlb(); - flush_tlb_others(cpu_mask, mm, FLUSH_ALL); + if (cpu_mask) + flush_tlb_others(cpu_mask, mm, FLUSH_ALL); } -void flush_tlb_mm(struct mm_struct * mm) +void flush_tlb_mm (struct mm_struct * mm) { - unsigned long vm_mask = 1 << smp_processor_id(); - unsigned long cpu_mask = mm->cpu_vm_mask & ~vm_mask; + unsigned long cpu_mask = mm->cpu_vm_mask & ~(1 << smp_processor_id()); if (current->active_mm == mm) { - if(current->mm) + if (current->mm) local_flush_tlb(); - else + else leave_mm(smp_processor_id()); } - - flush_tlb_others(cpu_mask, mm, FLUSH_ALL); + if (cpu_mask) + flush_tlb_others(cpu_mask, mm, FLUSH_ALL); } void flush_tlb_page(struct vm_area_struct * vma, unsigned long va) { - unsigned long vm_mask = 1 << smp_processor_id(); struct mm_struct *mm = vma->vm_mm; - unsigned long cpu_mask = mm->cpu_vm_mask & ~vm_mask; + unsigned long cpu_mask = mm->cpu_vm_mask & ~(1 << smp_processor_id()); if (current->active_mm == mm) { if(current->mm) @@ -446,12 +426,14 @@ leave_mm(smp_processor_id()); } - flush_tlb_others(cpu_mask, mm, va); + if (cpu_mask) + flush_tlb_others(cpu_mask, mm, va); } static inline void do_flush_tlb_all_local(void) { unsigned long cpu = smp_processor_id(); + __flush_tlb_all(); if (cpu_tlbstate[cpu].state == TLBSTATE_LAZY) leave_mm(cpu); @@ -477,7 +459,7 @@ void smp_send_reschedule(int cpu) { - send_IPI_single(cpu, RESCHEDULE_VECTOR); + send_IPI_mask(1 << cpu, RESCHEDULE_VECTOR); } /* --- 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);