patch-2.3.12 linux/arch/i386/kernel/smp.c
Next file: linux/arch/i386/math-emu/fpu_entry.c
Previous file: linux/arch/i386/kernel/signal.c
Back to the patch index
Back to the overall index
- Lines: 241
- Date:
Wed Jul 28 10:45:39 1999
- Orig file:
v2.3.11/linux/arch/i386/kernel/smp.c
- Orig date:
Wed Jul 21 15:46:48 1999
diff -u --recursive --new-file v2.3.11/linux/arch/i386/kernel/smp.c linux/arch/i386/kernel/smp.c
@@ -128,6 +128,8 @@
const char lk_lockmsg[] = "lock from interrupt context at %p\n";
int mp_bus_id_to_type [MAX_MP_BUSSES] = { -1, };
+extern int nr_ioapics;
+extern struct mpc_config_ioapic mp_apics [MAX_IO_APICS];
extern int mp_irq_entries;
extern struct mpc_config_intsrc mp_irqs [MAX_IRQ_SOURCES];
extern int mpc_default_type;
@@ -258,12 +260,10 @@
}
memcpy(str,mpc->mpc_oem,8);
str[8]=0;
- memcpy(ioapic_OEM_ID,str,9);
printk("OEM ID: %s ",str);
memcpy(str,mpc->mpc_productid,12);
str[12]=0;
- memcpy(ioapic_Product_ID,str,13);
printk("Product ID: %s ",str);
printk("APIC at: 0x%lX\n",mpc->mpc_lapic);
@@ -368,11 +368,9 @@
printk("I/O APIC #%d Version %d at 0x%lX.\n",
m->mpc_apicid,m->mpc_apicver,
m->mpc_apicaddr);
- /*
- * we use the first one only currently
- */
- if (ioapics == 1)
- mp_ioapic_addr = m->mpc_apicaddr;
+ mp_apics [nr_ioapics] = *m;
+ if (++nr_ioapics > MAX_IO_APICS)
+ --nr_ioapics;
}
mpt+=sizeof(*m);
count+=sizeof(*m);
@@ -404,9 +402,9 @@
}
}
}
- if (ioapics > 1)
+ if (ioapics > MAX_IO_APICS)
{
- printk("Warning: Multiple IO-APICs not yet supported.\n");
+ printk("Warning: Max I/O APICs exceeded (max %d, found %d).\n", MAX_IO_APICS, ioapics);
printk("Warning: switching to non APIC mode.\n");
skip_ioapic_setup=1;
}
@@ -774,18 +772,22 @@
#ifdef CONFIG_X86_IO_APIC
{
- unsigned long ioapic_phys;
+ unsigned long ioapic_phys, idx = FIX_IO_APIC_BASE_0;
+ int i;
- if (smp_found_config) {
- ioapic_phys = mp_ioapic_addr;
- } else {
- ioapic_phys = __pa(memory_start);
- memset((void *)memory_start, 0, PAGE_SIZE);
- memory_start += PAGE_SIZE;
+ for (i = 0; i < nr_ioapics; i++) {
+ if (smp_found_config) {
+ ioapic_phys = mp_apics[i].mpc_apicaddr;
+ } else {
+ ioapic_phys = __pa(memory_start);
+ memset((void *)memory_start, 0, PAGE_SIZE);
+ memory_start += PAGE_SIZE;
+ }
+ set_fixmap(idx,ioapic_phys);
+ printk("mapped IOAPIC to %08lx (%08lx)\n",
+ __fix_to_virt(idx), ioapic_phys);
+ idx++;
}
- set_fixmap(FIX_IO_APIC_BASE,ioapic_phys);
- printk("mapped IOAPIC to %08lx (%08lx)\n",
- fix_to_virt(FIX_IO_APIC_BASE), ioapic_phys);
}
#endif
@@ -1382,12 +1384,6 @@
printk(KERN_WARNING "WARNING: SMP operation may be unreliable with B stepping processors.\n");
SMP_PRINTK(("Boot done.\n"));
- /*
- * now we know the other CPUs have fired off and we know our
- * APIC ID, so we can go init the TSS and stuff:
- */
- cpu_init();
-
cache_APIC_registers();
#ifndef CONFIG_VISWS
/*
@@ -1399,6 +1395,11 @@
#endif
smp_done:
+ /*
+ * now we know the other CPUs have fired off and we know our
+ * APIC ID, so we can go init the TSS and stuff:
+ */
+ cpu_init();
}
@@ -1578,8 +1579,7 @@
* bad as in the early days of SMP, so we might ease some of the
* paranoia here.
*/
-
-void smp_flush_tlb(void)
+static void flush_tlb_others(unsigned int cpumask)
{
int cpu = smp_processor_id();
int stuck;
@@ -1589,17 +1589,9 @@
* it's important that we do not generate any APIC traffic
* until the AP CPUs have booted up!
*/
- if (cpu_online_map) {
- /*
- * The assignment is safe because it's volatile so the
- * compiler cannot reorder it, because the i586 has
- * strict memory ordering and because only the kernel
- * lock holder may issue a tlb flush. If you break any
- * one of those three change this to an atomic bus
- * locked or.
- */
-
- smp_invalidate_needed = cpu_online_map;
+ cpumask &= cpu_online_map;
+ if (cpumask) {
+ atomic_set_mask(cpumask, &smp_invalidate_needed);
/*
* Processors spinning on some lock with IRQs disabled
@@ -1622,8 +1614,10 @@
/*
* Take care of "crossing" invalidates
*/
- if (test_bit(cpu, &smp_invalidate_needed))
- clear_bit(cpu, &smp_invalidate_needed);
+ if (test_bit(cpu, &smp_invalidate_needed)) {
+ clear_bit(cpu, &smp_invalidate_needed);
+ local_flush_tlb();
+ }
--stuck;
if (!stuck) {
printk("stuck on TLB IPI wait (CPU#%d)\n",cpu);
@@ -1632,12 +1626,58 @@
}
__restore_flags(flags);
}
+}
- /*
- * Flush the local TLB
- */
+/*
+ * Smarter SMP flushing macros.
+ * c/o Linus Torvalds.
+ *
+ * These mean you can really definitely utterly forget about
+ * writing to user space from interrupts. (Its not allowed anyway).
+ */
+void flush_tlb_current_task(void)
+{
+ unsigned long vm_mask = 1 << current->processor;
+ struct mm_struct *mm = current->mm;
+
+ if (mm->cpu_vm_mask != vm_mask) {
+ flush_tlb_others(mm->cpu_vm_mask & ~vm_mask);
+ mm->cpu_vm_mask = vm_mask;
+ }
local_flush_tlb();
+}
+
+void flush_tlb_mm(struct mm_struct * mm)
+{
+ unsigned long vm_mask = 1 << current->processor;
+ unsigned long cpu_mask = mm->cpu_vm_mask & ~vm_mask;
+
+ mm->cpu_vm_mask = 0;
+ if (current->active_mm == mm) {
+ mm->cpu_vm_mask = vm_mask;
+ local_flush_tlb();
+ }
+ flush_tlb_others(cpu_mask);
+}
+void flush_tlb_page(struct vm_area_struct * vma, unsigned long va)
+{
+ unsigned long vm_mask = 1 << current->processor;
+ struct mm_struct *mm = vma->vm_mm;
+ unsigned long cpu_mask = mm->cpu_vm_mask & ~vm_mask;
+
+ mm->cpu_vm_mask = 0;
+ if (current->active_mm == mm) {
+ __flush_tlb_one(va);
+ mm->cpu_vm_mask = vm_mask;
+ }
+ flush_tlb_others(cpu_mask);
+}
+
+void flush_tlb_all(void)
+{
+ flush_tlb_others(~(1 << current->processor));
+ local_flush_tlb();
}
@@ -1860,13 +1900,24 @@
}
/*
- * Invalidate call-back
+ * Invalidate call-back.
+ *
+ * Mark the CPU as a VM user if there is a active
+ * thread holding on to an mm at this time. This
+ * allows us to optimize CPU cross-calls even in the
+ * presense of lazy TLB handling.
*/
asmlinkage void smp_invalidate_interrupt(void)
{
- if (test_and_clear_bit(smp_processor_id(), &smp_invalidate_needed))
- local_flush_tlb();
+ struct task_struct *tsk = current;
+ unsigned int cpu = tsk->processor;
+ if (test_and_clear_bit(cpu, &smp_invalidate_needed)) {
+ struct mm_struct *mm = tsk->mm;
+ if (mm)
+ atomic_set_mask(1 << cpu, &mm->cpu_vm_mask);
+ local_flush_tlb();
+ }
ack_APIC_irq();
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)