summaryrefslogtreecommitdiffstats
path: root/sys/ia64
diff options
context:
space:
mode:
authormarcel <marcel@FreeBSD.org>2010-03-22 03:55:18 +0000
committermarcel <marcel@FreeBSD.org>2010-03-22 03:55:18 +0000
commit1d18613088fca02d496cae7fe980b20144f83995 (patch)
treef86201ae3bacda175278e356fd59b095c0451006 /sys/ia64
parent6b762ecd8b1f98319d288d3bd46afc5c624a5076 (diff)
downloadFreeBSD-src-1d18613088fca02d496cae7fe980b20144f83995.zip
FreeBSD-src-1d18613088fca02d496cae7fe980b20144f83995.tar.gz
Fix interrupt handling by extending the critical region so that
preemption doesn't happen until after all pending interrupt have been services. While here again, simplify the EOI handling by doing it after we call the XIV-specific handlers, rather than in each of them. The original thought was that we may want to do an EOI first and the actual IPI handling next, but that's mostly a micro-optimization.
Diffstat (limited to 'sys/ia64')
-rw-r--r--sys/ia64/ia64/clock.c8
-rw-r--r--sys/ia64/ia64/exception.S2
-rw-r--r--sys/ia64/ia64/interrupt.c33
-rw-r--r--sys/ia64/ia64/mp_machdep.c10
4 files changed, 19 insertions, 34 deletions
diff --git a/sys/ia64/ia64/clock.c b/sys/ia64/ia64/clock.c
index 0afbc87..2e7f2d8 100644
--- a/sys/ia64/ia64/clock.c
+++ b/sys/ia64/ia64/clock.c
@@ -90,13 +90,9 @@ ia64_ih_clock(struct thread *td, u_int xiv, struct trapframe *tf)
int64_t delta;
int count;
- ia64_set_eoi(0);
-
PCPU_INC(md.stats.pcs_nclks);
intrcnt[INTRCNT_CLOCK]++;
- ia64_srlz_d();
-
itc = ia64_get_itc();
adj = PCPU_GET(md.clockadj);
@@ -120,6 +116,7 @@ ia64_ih_clock(struct thread *td, u_int xiv, struct trapframe *tf)
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)) {
@@ -134,7 +131,6 @@ ia64_ih_clock(struct thread *td, u_int xiv, struct trapframe *tf)
}
PCPU_SET(md.clock, clk);
PCPU_SET(md.clockadj, adj);
- ia64_srlz_d();
return (0);
}
@@ -150,7 +146,7 @@ pcpu_initclock(void)
}
/*
- * Start the real-time and statistics clocks. We use cr.itc and cr.itm
+ * Start the real-time and statistics clocks. We use ar.itc and cr.itm
* to implement a 1000hz clock.
*/
void
diff --git a/sys/ia64/ia64/exception.S b/sys/ia64/ia64/exception.S
index 5e186f9..4464a88 100644
--- a/sys/ia64/ia64/exception.S
+++ b/sys/ia64/ia64/exception.S
@@ -1303,7 +1303,7 @@ IVT_END(Break_Instruction)
IVT_ENTRY(External_Interrupt, 0x3000)
{ .mib
- mov r17=cr.ivr // Put the XIV in the trapframe.
+ mov r17=ar.itc // Put the ITC in the trapframe.
mov r16=ip
br.sptk exception_save
;;
diff --git a/sys/ia64/ia64/interrupt.c b/sys/ia64/ia64/interrupt.c
index ad8a4e3..3376111 100644
--- a/sys/ia64/ia64/interrupt.c
+++ b/sys/ia64/ia64/interrupt.c
@@ -288,30 +288,32 @@ void
ia64_handle_intr(struct trapframe *tf)
{
struct thread *td;
- u_int rfi, xiv;
+ u_int xiv;
td = curthread;
ia64_set_fpsr(IA64_FPSR_DEFAULT);
PCPU_INC(cnt.v_intr);
- xiv = tf->tf_special.ifa;
+ xiv = ia64_get_ivr();
+ ia64_srlz_d();
if (xiv == 15) {
PCPU_INC(md.stats.pcs_nstrays);
goto out;
}
- while (xiv != 15) {
- CTR1(KTR_INTR, "INTR: XIV=%u", xiv);
- critical_enter();
- rfi = (ia64_handler[xiv])(td, xiv, tf);
- if (rfi) {
- critical_exit();
- return;
- }
+ critical_enter();
+
+ do {
+ CTR2(KTR_INTR, "INTR: ITC=%u, XIV=%u",
+ (u_int)tf->tf_special.ifa, xiv);
+ (ia64_handler[xiv])(td, xiv, tf);
+ ia64_set_eoi(0);
+ ia64_srlz_d();
xiv = ia64_get_ivr();
- critical_exit();
ia64_srlz_d();
- }
+ } while (xiv != 15);
+
+ critical_exit();
out:
if (TRAPF_USERMODE(tf)) {
@@ -327,10 +329,8 @@ static u_int
ia64_ih_invalid(struct thread *td, u_int xiv, struct trapframe *tf)
{
- ia64_set_eoi(0);
- ia64_srlz_d();
panic("invalid XIV: %u", xiv);
- return (1);
+ return (0);
}
static u_int
@@ -354,8 +354,7 @@ ia64_ih_irq(struct thread *td, u_int xiv, struct trapframe *tf)
ia64_intr_mask((void *)(uintptr_t)xiv);
log(LOG_ERR, "stray irq%u\n", i->irq);
}
- ia64_set_eoi(0);
- ia64_srlz_d();
+
return (0);
}
diff --git a/sys/ia64/ia64/mp_machdep.c b/sys/ia64/ia64/mp_machdep.c
index b1d32f7..05a655d 100644
--- a/sys/ia64/ia64/mp_machdep.c
+++ b/sys/ia64/ia64/mp_machdep.c
@@ -90,10 +90,8 @@ static u_int
ia64_ih_ast(struct thread *td, u_int xiv, struct trapframe *tf)
{
- ia64_set_eoi(0);
PCPU_INC(md.stats.pcs_nasts);
CTR1(KTR_SMP, "IPI_AST, cpuid=%d", PCPU_GET(cpuid));
- ia64_srlz_d();
return (0);
}
@@ -101,10 +99,8 @@ static u_int
ia64_ih_highfp(struct thread *td, u_int xiv, struct trapframe *tf)
{
- ia64_set_eoi(0);
PCPU_INC(md.stats.pcs_nhighfps);
ia64_highfp_save_ipi();
- ia64_srlz_d();
return (0);
}
@@ -112,11 +108,9 @@ static u_int
ia64_ih_preempt(struct thread *td, u_int xiv, struct trapframe *tf)
{
- ia64_set_eoi(0);
PCPU_INC(md.stats.pcs_npreempts);
CTR1(KTR_SMP, "IPI_PREEMPT, cpuid=%d", PCPU_GET(cpuid));
sched_preempt(curthread);
- ia64_srlz_d();
return (0);
}
@@ -124,11 +118,9 @@ static u_int
ia64_ih_rndzvs(struct thread *td, u_int xiv, struct trapframe *tf)
{
- ia64_set_eoi(0);
PCPU_INC(md.stats.pcs_nrdvs);
CTR1(KTR_SMP, "IPI_RENDEZVOUS, cpuid=%d", PCPU_GET(cpuid));
smp_rendezvous_action();
- ia64_srlz_d();
return (0);
}
@@ -137,10 +129,8 @@ ia64_ih_stop(struct thread *td, u_int xiv, struct trapframe *tf)
{
cpumask_t mybit;
- ia64_set_eoi(0);
PCPU_INC(md.stats.pcs_nstops);
mybit = PCPU_GET(cpumask);
- ia64_srlz_d();
savectx(PCPU_PTR(md.pcb));
OpenPOWER on IntegriCloud