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]