upgrade to fedora-2.6.12-1.1398.FC4 + vserver 2.0.rc7
[linux-2.6.git] / arch / x86_64 / kernel / smp.c
index a9f9b17..008d712 100644 (file)
@@ -25,6 +25,9 @@
 #include <asm/pgalloc.h>
 #include <asm/tlbflush.h>
 #include <asm/mach_apic.h>
+#include <asm/mmu_context.h>
+#include <asm/proto.h>
+#include <asm/apicdef.h>
 
 /*
  *     Smarter SMP flushing macros. 
@@ -39,8 +42,8 @@
 static cpumask_t flush_cpumask;
 static struct mm_struct * flush_mm;
 static unsigned long flush_va;
-static spinlock_t tlbstate_lock = SPIN_LOCK_UNLOCKED;
-#define FLUSH_ALL      0xffffffff
+static DEFINE_SPINLOCK(tlbstate_lock);
+#define FLUSH_ALL      -1ULL
 
 /*
  * We cannot call mmdrop() because we are in interrupt context, 
@@ -51,7 +54,7 @@ static inline void leave_mm (unsigned long cpu)
        if (read_pda(mmu_state) == TLBSTATE_OK)
                BUG();
        clear_bit(cpu, &read_pda(active_mm)->cpu_vm_mask);
-       __flush_tlb();
+       load_cr3(swapper_pg_dir);
 }
 
 /*
@@ -268,7 +271,7 @@ void smp_send_reschedule(int cpu)
  * Structure and data for smp_call_function(). This is designed to minimise
  * static memory requirements. It also looks cleaner.
  */
-static spinlock_t call_lock = SPIN_LOCK_UNLOCKED;
+static DEFINE_SPINLOCK(call_lock);
 
 struct call_data_struct {
        void (*func) (void *info);
@@ -377,6 +380,8 @@ static void smp_really_stop_cpu(void *dummy)
 void smp_send_stop(void)
 {
        int nolock = 0;
+       if (reboot_force)
+               return;
        /* Don't deadlock on the call lock in panic */
        if (!spin_trylock(&call_lock)) {
                /* ignore locking because we have paniced anyways */
@@ -385,7 +390,10 @@ void smp_send_stop(void)
        __smp_call_function(smp_really_stop_cpu, NULL, 0, 0);
        if (!nolock)
                spin_unlock(&call_lock);
-       smp_stop_cpu();
+
+       local_irq_disable();
+       disable_local_APIC();
+       local_irq_enable();
 }
 
 /*
@@ -422,3 +430,27 @@ asmlinkage void smp_call_function_interrupt(void)
                atomic_inc(&call_data->finished);
        }
 }
+
+int safe_smp_processor_id(void)
+{
+       int apicid, i;
+
+       if (disable_apic)
+               return 0;
+
+       apicid = hard_smp_processor_id();
+       if (x86_cpu_to_apicid[apicid] == apicid)
+               return apicid;
+
+       for (i = 0; i < NR_CPUS; ++i) {
+               if (x86_cpu_to_apicid[i] == apicid)
+                       return i;
+       }
+
+       /* No entries in x86_cpu_to_apicid?  Either no MPS|ACPI,
+        * or called too early.  Either way, we must be CPU 0. */
+       if (x86_cpu_to_apicid[0] == BAD_APICID)
+               return 0;
+
+       return 0; /* Should not happen */
+}