xen: SMP guest support

This is a fairly straightforward Xen implementation of smp_ops.

Xen has its own IPI mechanisms, and has no dependency on any
APIC-based IPI.  The smp_ops hooks and the flush_tlb_others pv_op
allow a Xen guest to avoid all APIC code in arch/i386 (the only apic
operation is a single apic_read for the apic version number).

One subtle point which needs to be addressed is unpinning pagetables
when another cpu may have a lazy tlb reference to the pagetable. Xen
will not allow an in-use pagetable to be unpinned, so we must find any
other cpus with a reference to the pagetable and get them to shoot
down their references.

Signed-off-by: Jeremy Fitzhardinge <jeremy@xensource.com>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
Cc: Benjamin LaHaise <bcrl@kvack.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Andi Kleen <ak@suse.de>
diff --git a/arch/i386/xen/time.c b/arch/i386/xen/time.c
index 2aab44b..aeb04cf 100644
--- a/arch/i386/xen/time.c
+++ b/arch/i386/xen/time.c
@@ -519,7 +519,7 @@
 	return ret;
 }
 
-static void xen_setup_timer(int cpu)
+void xen_setup_timer(int cpu)
 {
 	const char *name;
 	struct clock_event_device *evt;
@@ -535,16 +535,20 @@
 				      IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
 				      name, NULL);
 
-	evt = &get_cpu_var(xen_clock_events);
+	evt = &per_cpu(xen_clock_events, cpu);
 	memcpy(evt, xen_clockevent, sizeof(*evt));
 
 	evt->cpumask = cpumask_of_cpu(cpu);
 	evt->irq = irq;
-	clockevents_register_device(evt);
 
 	setup_runstate_info(cpu);
+}
 
-	put_cpu_var(xen_clock_events);
+void xen_setup_cpu_clockevents(void)
+{
+	BUG_ON(preemptible());
+
+	clockevents_register_device(&__get_cpu_var(xen_clock_events));
 }
 
 __init void xen_time_init(void)
@@ -570,4 +574,5 @@
 	tsc_disable = 0;
 
 	xen_setup_timer(cpu);
+	xen_setup_cpu_clockevents();
 }