diff options
author | marcel <marcel@FreeBSD.org> | 2003-08-04 00:08:39 +0000 |
---|---|---|
committer | marcel <marcel@FreeBSD.org> | 2003-08-04 00:08:39 +0000 |
commit | 47e1af7da85f4a66bb2b605035aedf62a1eaaa2b (patch) | |
tree | 84535f5c21edb1dc060917dc5f7c76dcbcf370b6 /sys | |
parent | a506e844d169350a3ac4998c79b3c441fd5ef7bd (diff) | |
download | FreeBSD-src-47e1af7da85f4a66bb2b605035aedf62a1eaaa2b.zip FreeBSD-src-47e1af7da85f4a66bb2b605035aedf62a1eaaa2b.tar.gz |
Fix handling of external interrupts: we weren't calling ast() when
interrupting user mode. The net effect of this bug is that a clock
interrupt does not cause rescheduling and processes are not
preempted. It only takes a "while (1);" to render the machine
useless.
This bug was introduced by the context changes and EPC syscall code.
Handling of ASTs was moved to C for clarity and ease of maintenance,
but was not added for the external interrupt case.
This needs to be revisited. We now have calls to do_ast() in trap(),
break_syscall() and ivt_External_Interrupt(). A single call in
exception_restore covers these 3 places without duplication. This
is where we handled ASTs prior to the overhaul, except that the
meat has been moved to do_ast(), a C function. This was the goal
to begin with.
Pointy hat: marcel
Diffstat (limited to 'sys')
-rw-r--r-- | sys/ia64/ia64/exception.S | 63 | ||||
-rw-r--r-- | sys/ia64/ia64/genassym.c | 2 |
2 files changed, 51 insertions, 14 deletions
diff --git a/sys/ia64/ia64/exception.S b/sys/ia64/ia64/exception.S index 795ec93..feffb65 100644 --- a/sys/ia64/ia64/exception.S +++ b/sys/ia64/ia64/exception.S @@ -1150,28 +1150,65 @@ IVT_ENTRY(External_Interrupt, 0x3000) br.sptk exception_save ;; } -{ .mmb -2: alloc r14=ar.pfs,0,0,2,0 // make a frame for calling with - add out1=16,sp - nop 0 -} - -3: mov out0=cr.ivr // find interrupt vector + alloc r14=ar.pfs,0,0,2,0 ;; - cmp.eq p15,p0=15,out0 // check for spurious vector number -(p15) br.dpnt.few exception_restore // if spurious, we are done +1: +{ .mii + mov out0=cr.ivr // Get interrupt vector + add out1=16,sp ;; - ssm psr.i // re-enable interrupts + cmp.eq p15,p0=15,out0 // check for spurious vector number +} +{ .mbb + ssm psr.i // re-enable interrupts +(p15) br.dpnt.few 2f // if spurious, we are done br.call.sptk.many rp=interrupt // call high-level handler ;; - rsm psr.i // disable interrupts +} +{ .mmi + rsm psr.i // disable interrupts ;; srlz.d - mov cr.eoi=r0 // and ack the interrupt + nop 0 +} +{ .mmi + mov cr.eoi=r0 // ack the interrupt ;; srlz.d - br.sptk.few 3b // loop for more + nop 0 +} +{ .mfb + nop 0 + nop 0 + br.sptk 1b // loop for more ;; +} +2: +{ .mmi + add r14=16+TF_SPECIAL_IIP,sp + ;; + ld8 r14=[r14] + add out0=16,sp + ;; +} +{ .mii + nop 0 + extr.u r14=r14,61,3 + ;; + cmp.ge p15,p0=5,r14 +} +{ .mfb + nop 0 + nop 0 +(p15) br.call.sptk rp=do_ast + ;; +} +{ .mfb + nop 0 + nop 0 + br.sptk exception_restore + ;; +} IVT_END(External_Interrupt) IVT_ENTRY(Reserved_3400, 0x3400) diff --git a/sys/ia64/ia64/genassym.c b/sys/ia64/ia64/genassym.c index 302c441..0c0ec81 100644 --- a/sys/ia64/ia64/genassym.c +++ b/sys/ia64/ia64/genassym.c @@ -112,7 +112,7 @@ ASSYM(TD_PCB, offsetof(struct thread, td_pcb)); ASSYM(TDF_ASTPENDING, TDF_ASTPENDING); ASSYM(TDF_NEEDRESCHED, TDF_NEEDRESCHED); -ASSYM(TF_SPECIAL_NDIRTY, offsetof(struct trapframe, tf_special.ndirty)); +ASSYM(TF_SPECIAL_IIP, offsetof(struct trapframe, tf_special.iip)); ASSYM(UC_MCONTEXT, offsetof(ucontext_t, uc_mcontext)); |