aboutsummaryrefslogtreecommitdiffstats
path: root/arch/i386/xen/time.c
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@xensource.com>2007-07-17 21:37:06 -0400
committerJeremy Fitzhardinge <jeremy@goop.org>2007-07-18 11:47:44 -0400
commitf87e4cac4f4e940b328d3deb5b53e642e3881f43 (patch)
tree7409f86561e5f97459378abd2ae21e9a5c82bfea /arch/i386/xen/time.c
parentab55028886dd1dd54585f22bf19a00eb23869340 (diff)
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>
Diffstat (limited to 'arch/i386/xen/time.c')
-rw-r--r--arch/i386/xen/time.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/arch/i386/xen/time.c b/arch/i386/xen/time.c
index 2aab44bec2a5..aeb04cf5dbf1 100644
--- a/arch/i386/xen/time.c
+++ b/arch/i386/xen/time.c
@@ -519,7 +519,7 @@ static irqreturn_t xen_timer_interrupt(int irq, void *dev_id)
519 return ret; 519 return ret;
520} 520}
521 521
522static void xen_setup_timer(int cpu) 522void xen_setup_timer(int cpu)
523{ 523{
524 const char *name; 524 const char *name;
525 struct clock_event_device *evt; 525 struct clock_event_device *evt;
@@ -535,16 +535,20 @@ static void xen_setup_timer(int cpu)
535 IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING, 535 IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING,
536 name, NULL); 536 name, NULL);
537 537
538 evt = &get_cpu_var(xen_clock_events); 538 evt = &per_cpu(xen_clock_events, cpu);
539 memcpy(evt, xen_clockevent, sizeof(*evt)); 539 memcpy(evt, xen_clockevent, sizeof(*evt));
540 540
541 evt->cpumask = cpumask_of_cpu(cpu); 541 evt->cpumask = cpumask_of_cpu(cpu);
542 evt->irq = irq; 542 evt->irq = irq;
543 clockevents_register_device(evt);
544 543
545 setup_runstate_info(cpu); 544 setup_runstate_info(cpu);
545}
546
547void xen_setup_cpu_clockevents(void)
548{
549 BUG_ON(preemptible());
546 550
547 put_cpu_var(xen_clock_events); 551 clockevents_register_device(&__get_cpu_var(xen_clock_events));
548} 552}
549 553
550__init void xen_time_init(void) 554__init void xen_time_init(void)
@@ -570,4 +574,5 @@ __init void xen_time_init(void)
570 tsc_disable = 0; 574 tsc_disable = 0;
571 575
572 xen_setup_timer(cpu); 576 xen_setup_timer(cpu);
577 xen_setup_cpu_clockevents();
573} 578}