summaryrefslogtreecommitdiffstats
path: root/sys/ia64
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2010-03-26 02:29:15 +0000
committermarcel <marcel@FreeBSD.org>2010-03-26 02:29:15 +0000
commita8e65314630b2f05c14dd732578c1c381ff74567 (patch)
tree91bb2c98825e43f9e785e874b29c20a06285796d /sys/ia64
parentd67e4cffdd6e55f3bc9f77eea58fc0cea6e8fc08 (diff)
downloadFreeBSD-src-a8e65314630b2f05c14dd732578c1c381ff74567.zip
FreeBSD-src-a8e65314630b2f05c14dd732578c1c381ff74567.tar.gz
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.
Diffstat (limited to 'sys/ia64')
-rw-r--r--sys/ia64/ia64/clock.c98
-rw-r--r--sys/ia64/ia64/mp_machdep.c5
-rw-r--r--sys/ia64/include/pcpu.h2
3 files changed, 55 insertions, 50 deletions
diff --git a/sys/ia64/ia64/clock.c b/sys/ia64/ia64/clock.c
index 2e7f2d8..33dbb2e 100644
--- a/sys/ia64/ia64/clock.c
+++ b/sys/ia64/ia64/clock.c
@@ -43,6 +43,7 @@ __FBSDID("$FreeBSD$");
#include <machine/intr.h>
#include <machine/intrcnt.h>
#include <machine/md_var.h>
+#include <machine/smp.h>
SYSCTL_NODE(_debug, OID_AUTO, clock, CTLFLAG_RW, 0, "clock statistics");
@@ -91,58 +92,61 @@ 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();
+ return (0);
}
/*
@@ -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 05a655d..f8d9f6f 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 9eb8efb..3c6e6a7 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_ */
OpenPOWER on IntegriCloud