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.
This commit is contained in:
parent
cc7a041c2b
commit
95b11053b3
@ -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
|
||||
|
@ -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
|
||||
;;
|
||||
|
@ -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;
|
||||
}
|
||||
xiv = ia64_get_ivr();
|
||||
critical_exit();
|
||||
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();
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user