From f4926eabc28bb720438c1be5820b7aa21f1ef4d3 Mon Sep 17 00:00:00 2001 From: Marcel Moolenaar Date: Fri, 26 Mar 2010 02:29:15 +0000 Subject: [PATCH] Only use the interval timer for clock interrupts on the BSP and have the BSP use IPIs to trigger clock interrupts on the APs. This allows us to run on hardware configurations for which the ITC has non-uniform frequencies across CPUs. While here, change the clock XIV to type IPI so as to protect the interrupt delivery against CPU re-balancing once that's implemented. --- sys/ia64/ia64/clock.c | 98 +++++++++++++++++++++----------------- sys/ia64/ia64/mp_machdep.c | 5 +- sys/ia64/include/pcpu.h | 2 - 3 files changed, 55 insertions(+), 50 deletions(-) diff --git a/sys/ia64/ia64/clock.c b/sys/ia64/ia64/clock.c index 2e7f2d87972..33dbb2e3c1e 100644 --- a/sys/ia64/ia64/clock.c +++ b/sys/ia64/ia64/clock.c @@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include SYSCTL_NODE(_debug, OID_AUTO, clock, CTLFLAG_RW, 0, "clock statistics"); @@ -91,60 +92,63 @@ ia64_ih_clock(struct thread *td, u_int xiv, struct trapframe *tf) int count; PCPU_INC(md.stats.pcs_nclks); - intrcnt[INTRCNT_CLOCK]++; - itc = ia64_get_itc(); + if (PCPU_GET(cpuid) == 0) { + /* + * Clock processing on the BSP. + */ + intrcnt[INTRCNT_CLOCK]++; - adj = PCPU_GET(md.clockadj); - clk = PCPU_GET(md.clock); + itc = ia64_get_itc(); - delta = itc - clk; - count = 0; - while (delta >= ia64_clock_reload) { - /* Only the BSP runs the real clock */ - if (PCPU_GET(cpuid) == 0) + adj = PCPU_GET(md.clockadj); + clk = PCPU_GET(md.clock); + + delta = itc - clk; + count = 0; + while (delta >= ia64_clock_reload) { +#ifdef SMP + ipi_all_but_self(ia64_clock_xiv); +#endif hardclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); - else - hardclock_cpu(TRAPF_USERMODE(tf)); + if (profprocs != 0) + profclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); + statclock(TRAPF_USERMODE(tf)); + delta -= ia64_clock_reload; + clk += ia64_clock_reload; + if (adj != 0) + adjust_ticks++; + count++; + } + ia64_set_itm(ia64_get_itc() + ia64_clock_reload - adj); + ia64_srlz_d(); + if (count > 0) { + adjust_lost += count - 1; + if (delta > (ia64_clock_reload >> 3)) { + if (adj == 0) + adjust_edges++; + adj = ia64_clock_reload >> 4; + } else + adj = 0; + } else { + adj = 0; + adjust_excess++; + } + PCPU_SET(md.clock, clk); + PCPU_SET(md.clockadj, adj); + } else { + /* + * Clock processing on the BSP. + */ + hardclock_cpu(TRAPF_USERMODE(tf)); if (profprocs != 0) profclock(TRAPF_USERMODE(tf), TRAPF_PC(tf)); statclock(TRAPF_USERMODE(tf)); - delta -= ia64_clock_reload; - clk += ia64_clock_reload; - if (adj != 0) - adjust_ticks++; - count++; } - ia64_set_itm(ia64_get_itc() + ia64_clock_reload - adj); - ia64_srlz_d(); - if (count > 0) { - adjust_lost += count - 1; - if (delta > (ia64_clock_reload >> 3)) { - if (adj == 0) - adjust_edges++; - adj = ia64_clock_reload >> 4; - } else - adj = 0; - } else { - adj = 0; - adjust_excess++; - } - PCPU_SET(md.clock, clk); - PCPU_SET(md.clockadj, adj); + return (0); } -void -pcpu_initclock(void) -{ - - PCPU_SET(md.clockadj, 0); - PCPU_SET(md.clock, ia64_get_itc()); - ia64_set_itm(PCPU_GET(md.clock) + ia64_clock_reload); - ia64_set_itv(ia64_clock_xiv); - ia64_srlz_d(); -} - /* * Start the real-time and statistics clocks. We use ar.itc and cr.itm * to implement a 1000hz clock. @@ -154,7 +158,7 @@ cpu_initclocks() { u_long itc_freq; - ia64_clock_xiv = ia64_xiv_alloc(PI_REALTIME, IA64_XIV_IRQ, + ia64_clock_xiv = ia64_xiv_alloc(PI_REALTIME, IA64_XIV_IPI, ia64_ih_clock); if (ia64_clock_xiv == 0) panic("No XIV for clock interrupts"); @@ -169,7 +173,11 @@ cpu_initclocks() tc_init(&ia64_timecounter); #endif - pcpu_initclock(); + PCPU_SET(md.clockadj, 0); + PCPU_SET(md.clock, ia64_get_itc()); + ia64_set_itm(PCPU_GET(md.clock) + ia64_clock_reload); + ia64_set_itv(ia64_clock_xiv); + ia64_srlz_d(); } void diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c index 05a655d8aec..f8d9f6f0c1f 100644 --- a/sys/ia64/ia64/mp_machdep.c +++ b/sys/ia64/ia64/mp_machdep.c @@ -206,9 +206,8 @@ ia64_ap_startup(void) CTR1(KTR_SMP, "SMP: cpu%d launched", PCPU_GET(cpuid)); - /* kick off the clock on this AP */ - pcpu_initclock(); - + /* Mask interval timer interrupts on APs. */ + ia64_set_itv(0x10000); ia64_set_tpr(0); ia64_srlz_d(); enable_intr(); diff --git a/sys/ia64/include/pcpu.h b/sys/ia64/include/pcpu.h index 9eb8efba017..3c6e6a762af 100644 --- a/sys/ia64/include/pcpu.h +++ b/sys/ia64/include/pcpu.h @@ -91,8 +91,6 @@ __curthread(void) #define PCPU_PTR(member) (&pcpup->pc_ ## member) #define PCPU_SET(member,value) (pcpup->pc_ ## member = (value)) -void pcpu_initclock(void); - #endif /* _KERNEL */ #endif /* !_MACHINE_PCPU_H_ */