fsset@bach.lerc.nasa.gov (Scott E. Townsend) (11/22/90)
[ I'm not expecting miracles, but I'll take 'em if I get 'em]
I've been having problems off and on with exceptions/interrupt handling.
I've got some code (included below) which works in many situations but is
not fully correct, and I would appreciate any pointers anyone could provide.
I've read the 88100 manual a couple of times, but things still aren't quite
sinking in.
The system is a hypercube-style machine with multiple CPUs sahring VME bus
memory in each node. We don't do virtual memory (yet), but we do use the
CMMUs for mapping memory as cached/non-cached.
My current problem is an error exception. I suspect that I'm getting a
floating imprecise exception while trying to drain the FPU to handle an
interrupt, here's the home-grown register dump I get:
Cube Client> arc2d
Cube Client> load 0 0 arc2d
copying 'arc2d-0.bin' to remote host
copying 'arc2d.sym' to remote host
loading cube node 0, processor 0 from 'arc2d'...
Cube Client>
Cube Client> assign 0 0 stdin small.in
Cube Client> assign 0 0 stdout small.out
Cube Client>
Cube Client> start 0 0
Halt advisory from 0.0, Error exception (9)
R00 = 00000000 R01 = 800003F3 R02 = 72800000 R03 = 08800000
R04 = 1E800000 R05 = 7D800000 R06 = 347FFFFE R07 = BE2AAAAB
R08 = 3E124925 R09 = 13800000 R10 = 67800000 R11 = 00000001
R12 = 00000000 R13 = 3E4CCCCD R14 = 3F36DB6F R15 = 40200001
R16 = 001066E8 R17 = 41800002 R18 = 0000000B R19 = 80000000
R20 = 3F800000 R21 = 00000019 R22 = 00000000 R23 = 3F4CCCCC
R24 = 00106684 R25 = 40200001 R26 = 00000000 R27 = 00000000
R28 = 00000000 R29 = 00000000 R30 = 00000000 R31 = 007D3AF0
PID = 00000011 PSR = 800003FB EPSR = 800003F0 SSBR = 00000404
SXIP = 000AB5AE SNIP = 000AB5B2 SFIP = 000AB5B6 VBR = 00000000
DMT0 = 00000000 DMD0 = 0008087C DMA0 = 007D3B1C DMT1 = 00000000
DMD1 = 0008087C DMA1 = 007D3B1C DMT2 = 00000000 DMD2 = 7D800000
DMA2 = 007D3B1C SR0 = 00000000 SR1 = 800003F3 SR2 = 00000000
SR3 = 00003008 FPECR = 00000004 FPHS1 = 00000000 FPLS1 = 00000000
FPHS2 = 000FA75E FPLS2 = 00000000 FPPT = 0000D9E0 FPRH = 00100000
FPRL = 00000000 FPIT = F4F0000A FPSR = 00000001 FPCR = 00000000
At '_logf' + 6C (000AB5AC)
000AB5AC: 85490009 fmul.sss r10,r9,r9
elapsed time: 0 00:00:04
(This example is running on a single node and processor)
Now here's my interrupt handler:
;
; Interrupt exception.
;
global _interrupt
_interrupt:
subu sp,sp,72
st r1,sp,16
ldcr r1,SFIP ; save exception regs
st r1,sp,8
ldcr r1,SNIP
st r1,sp,4
ldcr r1,EPSR
st r1,sp,0
ldcr r1,PSR ; prepare to re-enable exceptions
and r1,r1,0XFFF7 ; but leave interrupts disabled
stcr r1,EPSR
or.u r1,r0,hi16(fpu_snip+2)
or r1,r1,lo16(fpu_snip+2)
stcr r1,SNIP
or.u r1,r0,hi16(fpu_sfip+2)
or r1,r1,lo16(fpu_sfip+2)
stcr r1,SFIP
ld r1,sp,16
rte ; flush pending FPU operations
fpu_snip:
tb1 0,r0,511
fpu_sfip:
st r1,sp,16
ldcr r1,PSR
and r1,r1,0XFFFE
tb1 0,r0,511
stcr r0,SSBR
tb1 0,r0,511
stcr r1,PSR ; re-enable shadowing
st.d r12,sp,64 ; save compiler scratch regs
st.d r10,sp,56
st.d r8,sp,48
st.d r6,sp,40
st.d r4,sp,32
st.d r2,sp,24
or.u r1,r0,hi16(MVME181_SSR) ; fetch interrupt status
ld r1,r1,lo16(MVME181_SSR)
bb1 VMEINT7,r1,abort ; unsupported interrupts
bb1 VMEINT6,r1,abort
bb1 VMEINT5,r1,abort
bb1 VMEINT4,r1,abort
bb1 VMEINT3,r1,abort
bb1 PARINT,r1,abort
bb1 ACFAIL,r1,abort
bb1 SYSFAIL,r1,abort
vmeint2:
bb0 VMEINT2,r1,vmeint1
or.u r1,r0,hi16(MVME181_VMEACK2) ; fetch interrupt vector
or r1,r1,lo16(MVME181_VMEACK2)
ld.h r2,r1,0 ; halfword to get lower byte
mask r2,r2,0X00FF ; only lower byte is significant
bsr _pr_int_handler
or.u r1,r0,hi16(MVME181_SSR) ; re-fetch interrupt status
ld r1,r1,lo16(MVME181_SSR)
vmeint1:
bb0 VMEINT1,r1,asio
or.u r1,r0,hi16(MVME181_VMEACK1) ; fetch interrupt vector
or r1,r1,lo16(MVME181_VMEACK1)
ld.h r2,r1,0 ; halfword to get lower byte
mask r2,r2,0X00FF ; only lower byte is significant
bsr _pt_int_handler
or.u r1,r0,hi16(MVME181_SSR) ; re-fetch interrupt status
ld r1,r1,lo16(MVME181_SSR)
asio:
bb0 ASIOINT,r1,abort
bsr _timer_handler
or.u r1,r0,hi16(MVME181_SSR) ; re-fetch interrupt status
ld r1,r1,lo16(MVME181_SSR)
abort:
bb0 ABORTINT,r1,exit
ldcr r10,SXIP ; for determining where we were
ld r11,sp,16 ; (saved r1)
or r12,r1,r0 ; (interrupt condition)
addu sp,sp,72 ; restore & jump to debugger
xcr sp,sp,SR3 ; (taken from debugger vector)
or.u r1,r0,hi16(DBUG_INT)
or r1,r1,lo16(DBUG_INT)
jmp r1
exit:
tb0 0,r0,204 ; disable exceptions
or.u r1,r0,hi16(_sched_event) ; test for scheduler event
ld.b r10,r1,lo16(_sched_event)
bcnd ne0,r10,goto_sched
resume:
ld.d r2,sp,24 ; restore scratch regs
ld.d r4,sp,32
ld.d r6,sp,40
ld.d r8,sp,48
ld.d r10,sp,56
ld.d r12,sp,64
ld r1,sp,0 ; restore exception regs
stcr r1,EPSR
ld r1,sp,4
stcr r1,SNIP
ld r1,sp,8
stcr r1,SFIP
ld r1,sp,16
addu sp,sp,72
tb1 0,r0,511 ; clear scoreboard
stcr r0,SSBR
rte
;
; A scheduler event has occured, so we return to it rather than where we
; were at the time of the interrupt.
;
goto_sched:
ld.d r2,sp,24 ; restore scratch regs
ld.d r4,sp,32
ld.d r6,sp,40
ld.d r8,sp,48
ld.d r10,sp,56
ld.d r12,sp,64
ld r1,sp,0 ; restore exception regs
stcr r1,EPSR
ld r1,sp,4
stcr r1,SNIP
ld r1,sp,8
stcr r1,SFIP
stcr r0,SSBR
or.u r1,r0,hi16(_branch_to_loop+2)
or r1,r1,lo16(_branch_to_loop+2)
stcr r1,SNIP
or.u r1,r0,hi16(_branch_to_loop+6)
or r1,r1,lo16(_branch_to_loop+6)
stcr r1,SFIP
ld r1,sp,16
addu sp,sp,72
tb1 0,r0,511 ; clear scoreboard
stcr r0,SSBR
rte
;
; Freeze shadowing.
;
global _trap_204
_trap_204:
ldcr r10,EPSR
or r10,r10,1
stcr r10,EPSR
rte
So if anyone out there would be kind enough to look at this, I'd really
appreciate it. If you could send example code, that would be even better!
Thanks for any help you can provide.
--
------------------------------------------------------------------------
Scott Townsend | Phone: 216-433-8101
NASA Lewis Research Center | Mail Stop: 5-11
Cleveland, Ohio 44135 | Email: fsset@bach.lerc.nasa.gov
------------------------------------------------------------------------andrew@frip.WV.TEK.COM (Andrew Klossner) (11/26/90)
| ldcr r1,PSR ; prepare to re-enable exceptions | and r1,r1,0XFFF7 ; but leave interrupts disabled | stcr r1,EPSR | | or.u r1,r0,hi16(fpu_snip+2) | or r1,r1,lo16(fpu_snip+2) | stcr r1,SNIP | | or.u r1,r0,hi16(fpu_sfip+2) | or r1,r1,lo16(fpu_sfip+2) | stcr r1,SFIP | | ld r1,sp,16 | rte ; flush pending FPU operations The RTE instruction will enable the FPU but shadows will still be frozen, so any FPU exceptions will take the ERROR exception vector. You could put a fast bypass around this code by checking to see if SSBR is zero. If so, no scoreboard registers were set, and so there can't be any pending FPU exceptions. (This assumes up-to-date silicon.) By the way, there's no code here to clean up the data pipeline. You have to do that on every interrupt exception. -=- Andrew Klossner (uunet!tektronix!frip.WV.TEK!andrew) [UUCP] (andrew%frip.wv.tek.com@relay.cs.net) [ARPA]