fix a problem where nested interrupts caused networking to hang

This commit is contained in:
Markus Fröschle
2015-10-11 05:52:58 +00:00
parent a6cd8d2912
commit ea0e9c1ec0

View File

@@ -140,7 +140,7 @@
* mask an jump through the corresponging vector
*/
.macro irq vector,int_mask,clr_int
move.w #0x2700,sr // disable interrupt
move.w #0x2700,sr // disable interrupts
subq.l #8,sp
movem.l d0/a5,(sp) // save registers
@@ -260,19 +260,19 @@ init_vec_loop:
vector_table_start:
std_exc_vec:
_std_exc_vec:
//move.w #0x2700,sr // disable interrupt
move.w #0x2700,sr // disable interrupt
subq.l #8,sp
movem.l d0/a5,(sp) // save registers
move.w 8(sp),d0 // fetch vector
and.l #0x3fc,d0 // mask out vector number
movem.l d0/a5,(sp) // save registers
move.w 8(sp),d0 // fetch vector
and.l #0x3fc,d0 // mask out vector number
//#define DBG_EXC
#ifdef DBG_EXC
// printout vector number of exception
lea -4 * 4(sp),sp // reserve stack space
movem.l d0-d1/a0-a1,(sp) // save gcc scratch registers
lea -4 * 4(sp),sp // reserve stack space
movem.l d0-d1/a0-a1,(sp) // save gcc scratch registers
lsr.l #2,d0 // shift vector number in place
lsr.l #2,d0 // shift vector number in place
cmp.l #33,d0
beq noprint
cmp.l #34,d0
@@ -281,30 +281,29 @@ _std_exc_vec:
beq noprint
cmp.l #46,d0
beq noprint
move.l 4 * 4 + 8 + 4(sp),-(sp) // pc at exception
move.l d0,-(sp) // provide it to xprintf()
move.l 4 * 4 + 8 + 4(sp),-(sp) // pc at exception
move.l d0,-(sp) // provide it to xprintf()
pea exception_text
jsr _xprintf // call xprintf()
add.l #3*4,sp // adjust stack
jsr _xprintf // call xprintf()
add.l #3*4,sp // adjust stack
noprint:
movem.l (sp),d0-d1/a0-a1 // restore registers
movem.l (sp),d0-d1/a0-a1 // restore registers
lea 4 * 4(sp),sp
#endif /* DBG_EXC */
add.l _rt_vbr,d0 // + VBR
add.l _rt_vbr,d0 // + VBR
move.l d0,a5
move.l (a5),d0 // fetch exception routine address
move.l (a5),d0 // fetch exception routine address
move.l 4(sp),a5 // restore a5
move.l d0,4(sp) // store exception routine address
move.l 4(sp),a5 // restore a5
move.l d0,4(sp) // store exception routine address
// FIXME: not clear why we would need the following?
//move.w 10(sp),d0 // restore original SR
//bset #13,d0 // set supervisor bit
//move.w d0,sr //
move.l (sp)+,d0 // restore d0
rts // jump to exception handler
move.w 10(sp),d0 // restore original SR (irq mask)
bset #13,d0 // set supervisor bit
move.w d0,sr //
move.l (sp)+,d0 // restore d0
rts // jump to exception handler
exception_text:
.ascii "DEBUG: EXCEPTION %d caught at %p"
@@ -312,62 +311,62 @@ exception_text:
.align 4
reset_vector:
move.w #0x2700,sr // disable interrupts
move.w #0x2700,sr // disable interrupts
move.l #0x31415926,d0
cmp.l 0x426,d0 // _resvalid: reset vector valid?
beq std_exc_vec // yes->
jmp _rom_entry // no, cold start machine
cmp.l 0x426,d0 // _resvalid: reset vector valid?
beq std_exc_vec // yes->
jmp _rom_entry // no, cold start machine
access:
move.w #0x2700,sr // disable interrupts
move.w #0x2700,sr // disable interrupts
link a6,#-4 * 4 // make room for gcc scratch registers
movem.l d0-d1/a0-a1,(sp) // save them
link a6,#-4 * 4 // make room for gcc scratch registers
movem.l d0-d1/a0-a1,(sp) // save them
move.l 4(a6),-(sp) // push format_status
move.l 8(a6),-(sp) // pc at exception
move.l MCF_MMU_MMUAR,-(sp) // MMU fault address
move.l MCF_MMU_MMUSR,-(sp) // MMU status regisrter
move.w #0x2300,sr // can lower interrupt mask now that MMU status is safe
jsr _mmutr_miss // call C routine
lea 4 * 4(sp),sp // adjust stack
move.l 4(a6),-(sp) // push format_status
move.l 8(a6),-(sp) // pc at exception
move.l MCF_MMU_MMUAR,-(sp) // MMU fault address
move.l MCF_MMU_MMUSR,-(sp) // MMU status regisrter
move.w #0x2300,sr // can lower interrupt mask now that MMU status is safe
jsr _mmutr_miss // call C routine
lea 4 * 4(sp),sp // adjust stack
tst.l d0 // exception handler signals bus error
tst.l d0 // exception handler signals bus error
bne bus_error
movem.l (sp),d0-d1/a0-a1 // restore registers
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6
rte
bus_error:
movem.l (sp),d0-d1/a0-a1 // restore registers
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6
bra std_exc_vec // FIXME: this seems to be bogous...
bra std_exc_vec // FIXME: this seems to be bogous...
zero_divide:
move.w #0x2700,sr // disable interrupt
move.w #0x2700,sr // disable interrupt
move.l a0,-(sp)
move.l d0,-(sp)
move.l 12(sp),a0 // pc
move.w (a0)+,d0 // command word
btst #7,d0 // long?
beq zd_word // nein->
move.l 12(sp),a0 // pc
move.w (a0)+,d0 // command word
btst #7,d0 // long?
beq zd_word // no->
addq.l #2,a0
zd_word:
and.l 0x3f,d0 // mask out ea field
cmp.w #0x08,d0 // -(ax) or less?
and.l 0x3f,d0 // mask out ea field
cmp.w #0x08,d0 // -(ax) or less?
ble zd_end
addq.l #2,a0
cmp.w #0x39,d0 // xxx.L
cmp.w #0x39,d0 // xxx.L
bne zd_nal
addq.l #2,a0
bra zd_end
zd_nal: cmp.w #0x3c,d0 // immediate?
bne zd_end // no->
btst #7,d0 // long?
beq zd_end // no
zd_nal: cmp.w #0x3c,d0 // immediate?
bne zd_end // no->
btst #7,d0 // long?
beq zd_end // no
addq.l #2,a0
zd_end:
move.l a0,12(sp)
@@ -377,172 +376,172 @@ zd_end:
#ifdef _NOT_USED_
linea:
move.w #0x2700,sr // disable interrupt
move.w #0x2700,sr // disable interrupt
halt
nop
nop
linef:
move.w #0x2700,sr // disable interrupt
move.w #0x2700,sr // disable interrupt
halt
nop
nop
format:
move.w #0x2700,sr // disable interrupt
move.w #0x2700,sr // disable interrupt
halt
nop
nop
//floating point
flpoow:
move.w #0x2700,sr // disable interrupt
move.w #0x2700,sr // disable interrupt
halt
nop
nop
#endif /* _NOT_USED */
irq1: irq 0x64, 1, 0x02 // Level 1 autovector interrupt (unused)
irq2: irq 0x68, 2, 0x04 // Level 2 autovector interrupt (horizontal blank)
irq3: irq 0x6c, 3, 0x08 // Level 3 autovector interrupt (unused)
irq4: irq 0x70, 4, 0x10 // Level 4 autovector interrupt (vertical blank)
irq1: irq 0x64, 1, 0x02 // Level 1 autovector interrupt (unused)
irq2: irq 0x68, 2, 0x04 // Level 2 autovector interrupt (horizontal blank)
irq3: irq 0x6c, 3, 0x08 // Level 3 autovector interrupt (unused)
irq4: irq 0x70, 4, 0x10 // Level 4 autovector interrupt (vertical blank)
#if defined(MACHINE_FIREBEE) /* these handlers are only meaningful for the Firebee */
irq5: //move.w #0x2700,sr // disable interrupts
subq.l #4,sp // extra space
#if defined(MACHINE_FIREBEE) /* these handlers are only meaningful for the Firebee */
irq5: //move.w #0x2700,sr // disable interrupts
subq.l #4,sp // extra space
link a6,#-4 * 4 // save gcc scratch registers
movem.l d0-d1/a0-a1,(sp)
link a6,#-4 * 4 // save gcc scratch registers
movem.l d0-d1/a0-a1,(sp)
jsr _irq5_handler // call C handler routine
jsr _irq5_handler // call C handler routine
tst.b d0 // handled?
beq irq5_forward
tst.b d0 // handled?
beq irq5_forward
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6
addq.l #4,sp
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6
addq.l #4,sp
rte // return from exception
rte // return from exception
irq5_forward: move.l 0x74,a0 // fetch OS irq5 vector
add.l _rt_vbr,a0 // add runtime vbr
move.l a0,4(a6) // put on stack
irq5_forward: move.l 0x74,a0 // fetch OS irq5 vector
add.l _rt_vbr,a0 // add runtime vbr
move.l a0,4(a6) // put on stack
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6 //
move.w #0x2500,sr // set interrupt level
rts // jump through vector
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6 //
move.w #0x2500,sr // set interrupt level
rts // jump through vector
/*
* irq6 needs special treatment since - because the Coldfire only supports autovector interrupts
* - the exception vector is provided by the simulated MFP from the FPGA
*/
irq6: //move.w #0x2700,sr // disable interrupt
subq.l #4,sp // extra space
irq6: move.w #0x2700,sr // disable interrupt
subq.l #4,sp // extra space
link a6,#-4 * 4 // save gcc scratch registers
link a6,#-4 * 4 // save gcc scratch registers
movem.l d0-d1/a0-a1,(sp)
move.l 8(a6),-(sp) // format status word
move.l 12(a6),-(sp) // pc at exception
jsr _irq6_handler // call C handler
lea 8(sp),sp // fix stack
move.l 8(a6),-(sp) // format status word
move.l 12(a6),-(sp) // pc at exception
jsr _irq6_handler // call C handler
lea 8(sp),sp // fix stack
tst.b d0 // interrupt handled?
beq irq6_forward // no, forward to TOS
tst.b d0 // interrupt handled?
beq irq6_forward // no, forward to TOS
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6
addq.l #4,sp // "extra space" not needed in this case
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6
addq.l #4,sp // "extra space" not needed in this case
rte
irq6_forward:
move.l 0xf0020000,a0 // fetch "MFP interrupt vector" from FPGA
add.l _rt_vbr,a0 // add runtime VBR
move.l (a0),4(a6) // fetch handler address and put it on "extra space"
move.l 0xf0020000,a0 // fetch "MFP interrupt vector" from FPGA
add.l _rt_vbr,a0 // add runtime VBR
move.l (a0),4(a6) // fetch handler address and put it on "extra space"
movem.l (sp),d0-d1/a0-a1
unlk a6
move.w #0x2600,sr // set interrupt mask to MFP level
unlk a6
move.w #0x2600,sr // set interrupt mask to MFP level
rts // jump through vector
rts // jump through vector
/*
* irq 7 = pseudo bus error
*/
irq7:
lea -12(sp),sp
lea -12(sp),sp
movem.l d0/a0,(sp)
move.l __RAMBAR0+0x008,a0 // real access error handler
move.l a0,8(sp) // this will be the return address for rts
move.l __RAMBAR0+0x008,a0 // real access error handler
move.l a0,8(sp) // this will be the return address for rts
move.w 12(sp),d0 // format/vector word
andi.l #0xf000,d0 // keep only the format
ori.l #2*4,d0 // simulate vector #2, no fault
move.w d0,12(sp)
move.w 12(sp),d0 // format/vector word
andi.l #0xf000,d0 // keep only the format
ori.l #2*4,d0 // simulate vector #2, no fault
move.w d0,12(sp)
// TODO: Inside an interrupt handler, 16(sp) is the return address.
// For an Access Error, it should be the address of the fault instruction instead
lea MCF_EPORT_EPFR,a0
bset #7,(a0) // clear int 7
lea MCF_EPORT_EPFR,a0
bset #7,(a0) // clear int 7
move.l (sp)+,d0 // restore registers
move.l (sp)+,a0
rts // Forward to the Access Error handler
move.l (sp)+,d0 // restore registers
move.l (sp)+,a0
rts // Forward to the Access Error handler
#else // handlers for M5484LITE
#else // handlers for M5484LITE
irq5: //move.w #0x2700,sr // disable interrupts
subq.l #4,sp // extra space
irq5: move.w #0x2700,sr // disable interrupts
subq.l #4,sp // extra space
link a6,#-4 * 4 // save gcc scratch registers
movem.l d0-d1/a0-a1,(sp)
link a6,#-4 * 4 // save gcc scratch registers
movem.l d0-d1/a0-a1,(sp)
jsr _irq5_handler // call C handler routine
jsr _irq5_handler // call C handler routine
tst.b d0 // handled?
beq irq5_forward
tst.b d0 // handled?
beq irq5_forward
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6
addq.l #4,sp
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6
addq.l #4,sp
rte // return from exception
rte // return from exception
irq5_forward: move.l 0x74,a0 // fetch OS irq5 vector
add.l _rt_vbr,a0 // add runtime vbr
move.l a0,4(a6) // put on stack
irq5_forward: move.l 0x74,a0 // fetch OS irq5 vector
add.l _rt_vbr,a0 // add runtime vbr
move.l a0,4(a6) // put on stack
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6 //
move.w #0x2500,sr // set interrupt level
rts // jump through vector
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6 //
move.w #0x2500,sr // set interrupt level
rts // jump through vector
irq6:
irq 0x74,5,0x20
irq7: // irq7 is tied to PCI INTA# and PCI INTB# on the M5484LITE
irq7: // irq7 is tied to PCI INTA# and PCI INTB# on the M5484LITE
//move.w #0x2700,sr // disable interrupts
move.w #0x2700,sr // disable interrupts
lea -4*4(sp),sp // save gcc scratch registers
movem.l d0-d1/a0-a1,(sp)
lea -4*4(sp),sp // save gcc scratch registers
movem.l d0-d1/a0-a1,(sp)
jsr _irq7_handler // call C handler routine
jsr _irq7_handler // call C handler routine
movem.l (sp),d0-d1/a0-a1 // restore registers
lea 4*4(sp),sp
movem.l (sp),d0-d1/a0-a1 // restore registers
lea 4 * 4(sp),sp
rte // return from exception
rte // return from exception
irq7text:
.data
.ascii "IRQ7!"
.dc.b 13,10,0
.ascii "IRQ7!"
.dc.b 13,10,0
.text
#endif /* MACHINE_FIREBEE */
@@ -568,33 +567,33 @@ irq7text:
* (sp) -> gcc scratch registers save area
*/
_lowlevel_isr_handler:
subq.l #4,sp // extra space
link a6,#-4 * 4 // make room for
movem.l d0-d1/a0-a1,(sp) // gcc scratch registers and save them,
// other registers will be taken care of by gcc itself
subq.l #4,sp // extra space
link a6,#-4 * 4 // make room for
movem.l d0-d1/a0-a1,(sp) // gcc scratch registers and save them,
// other registers will be taken care of by gcc itself
move.w 8(a6),d0 // fetch vector number from stack
lsr.l #2,d0 // move it in place
andi.l #0xff,d0 // mask it out
move.l d0,-(sp) // push it
jsr _isr_execute_handler // call the C handler
addq.l #4,sp // adjust stack
tst.b d0 // handled?
beq lowlevel_forward // no, forward it to TOS
move.w 8(a6),d0 // fetch vector number from stack
lsr.l #2,d0 // move it in place
andi.l #0xff,d0 // mask it out
move.l d0,-(sp) // push it
jsr _isr_execute_handler // call the C handler
addq.l #4,sp // adjust stack
tst.b d0 // handled?
beq lowlevel_forward // no, forward it to TOS
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6
addq.l #4,sp // eliminate extra space
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6
addq.l #4,sp // eliminate extra space
rte
lowlevel_forward:
move.l 8(a6),d0 // fetch OS irq vector
lsr.l #2,d0 // move it in place
andi.l #0xff,d0 // mask out vector number
add.l _rt_vbr,d0 // add runtime vbr
move.l d0,4(a6) // put on stack as return address
move.l 8(a6),d0 // fetch OS irq vector
lsr.l #2,d0 // move it in place
andi.l #0xff,d0 // mask out vector number
add.l _rt_vbr,d0 // add runtime vbr
move.l d0,4(a6) // put on stack as return address
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6 //
rts // jump through vector
movem.l (sp),d0-d1/a0-a1 // restore registers
unlk a6 //
rts // jump through vector