13. Hawk Interrupts and Traps

Part of the Hawk Manual
by Douglas W. Jones
THE UNIVERSITY OF IOWA Department of Computer Science

Contents

13.1. The Trap Vector
13.2. The Trap Registers
13.3. A Trap Service Example


13.1. The Trap Vector

RESTARTTRAP     = #00
BUSTRAP         = #10
INSTRTRAP       = #20
PRIVTRAP        = #30
MMUTRAP         = #40
COPROCTRAP      = #50

IRQ0		= #80
IRQ1		= #90
IRQ2		= #A0
IRQ3		= #B0
IRQ4		= #C0
IRQ5		= #D0
IRQ6		= #E0
IRQ7		= #F0

The lowest memory addresses are known as the trap and interrupt vector. When the CPU detects an abnormal condition, either internally or signalled by external hardware, control is transferred to a location in the trap vector. The special conditions detected internally to cause traps are:

Restart -- location #00
A restart traps indicates power on or an external reset.

Bus -- location #10
A bus trap occurs when the CPU attempts to fetch from nonexistant memory or store in nonexistant or read-only memory. The cause is usually a programming error such as following an invalid pointer or corrupting a return address.

Instruction -- location #20
An instruction trap occurs when the CPU attempts to execute an undefined instruction. The cause is usually an attempt to execute data or a corrupt return address.

Privilege -- location #30
Privileged instruction (CPUGET or CPUSET) attempted in user state (PSW.level = 11112).

The memory management unit and coprocessors are not strictly part of the CPU, but they are closer to it than most other devices and report exceptions using the following traps:

MMU -- location #40
The memory management unit was unable to translate the virtual address provided by the CPU or it detected an attempt to violate the access rights for the indicated address. As with bus traps, programming errors are a common cause of MMU traps.

Coprocessor -- location #50
disabled or nonexistant coprocessor referenced by COGET or COSET.
Additional locations up through #F0 are included in the trap vector and reserved for other traps and device interrupts. Trap handlers and interrupt handlers are the same from the point of view of entry and exit, but traps and interrupts are handled differently by the CPU. Specifically, when a trap condition is reported to or by the CPU, the instruction currently being executed is aborted and the values in registers are preserved as they were immediately before the instruction that caused the trap. In contrast, when an interrupt is requested, the current instruction is allowed to complete before the CPU responds.

The final 8 locations in the trap vector are conventionally reserved for device interrupts. IRQ0 is the highest priority interrupt, a non-maskable interrupt that cannot be disabled by software. Devices asserting IRQ0 must retract their interrupt request immediately when the CPU acts on it or the CPU will hang.

IRQ1 through IRQ7 are controlled by the PSW level field:

There are two distinct ways that multiple devices may be assigned interrupt levels. One uses each level bit as an interrupt-enable bit for one device. In this case, only IRQ1, IRQ3 and IRQ7 should be used for high, medium and low priority devices, and PSW.level = 00002 should never be set to values other than x0002, x0012, x0112 and x1112.

The other approach requires an 8-way priority interrupt encoder, allowing seven distinct interrupt levels. This is upward compatible from the simpler model.

13.2. The Trap Registers

TPC — the trap program counter
TMA — the trap memory address
TSV — the trap save register

These registers are documented more fully in the section on processor control registers Each of these registers can be manipulated with the CPUGET and CPUSET instructions.

When an interrupt or trap occurs, the CPU first stores the program counter in the trap program counter register TPC, and the level field of the processor status word PSW is copied into the prior field, before setting the level field to zero. That is:

PSW.prior = PSW.level
PSW.level = 00002
TPC = PC PC = trap-vector location

This makes the trap handler uninterruptable and privileged, and it turns off the memory management unit.

In addition, If the trap occurred because of a memory addressing fault, the memory address and a notice of the cause is stored in the trap memory address register TMA. The trap save register TSV is available for use by trap service software.

13.3. A Trap Service Example

The following model trap handler saves the entire system state. We assume that the trap vector itself may be in ROM, with statically allocated RAM addresses for the register save areas associated with each entry in the trap vector, and no recursive trap handlers.

; code to handle illegal memory references
.       =       BUSTRAP
        CPUSET  R2,TSV          ; partially save R2
        LIL     R2,BUSSAVEAREA  ; get the save area pointer
        STORE   R1,R2,svR1      ; save R1
        LIL     R0,SAVEREGS	; join common code for all traps

The above code occupies 14 bytes and allows each trap to be handled with its own register save area. The common code shared by all trap handlers saves the registers as follows:

SAVEREGS:       ; enter with: R2 pointing to save area and stack
                ;             TPC holding user's PC
                ;             TSV holding user's R2
                ;             R1 saved in save area
        STORE   R3,R2,svR3
        CPUGET  R1,TSV
        CPUGET  R3,TPC
        STORE   R1,R2,svR2      ; R2 now properly saved
        STORE   R3,R2,svPC      ; PC now properly saved
        CPUGET  R1,TMA
        CPUGET  R3,PSW
        STORE   R1,R2,svMA
        STORE   R3,R2,svPSW

        ; ... straightforward code to save R4-15

        LOAD    R3,R2,myPSW
        LOAD    R1,R2,myCODE
        CPUSET  R3,PSW          ; this may enable interrupts
        ADDI    R2,R2,svSIZE
        JSRS    R1,R3           ; go serve the trap
        ADDI    R2,R2,-svSIZE

        ; ... code to restore R4-15

        LOAD    R3,R2,svPSW
        LOAD    R1,R2,svPC
        CPUSET  R3,PSW          ; disables interrupts
        CPUSET  R1,TPC
        LOAD    R3,R2,svR3
        LOAD    R1,R2,svR1
        LOAD    R2,R2,svR2
        RTT                     ; return to user!

The above code is written using R1 and R3 as alternate temporaries in order to improve pipeilined execution. On a superscalar machines, using more registers would allow even more parallelism.

The save area specific to each trap handler, and pointed to by R2 in the above code is assumed to be a record with field offsets declared something like the following:

; trap save area record structure
; (all fields are 1 word, so displacements are shown in words)

myCODE  =  0 <<2  ; pointer to trap-specific routine entry
myPSW   =  1 <<2  ; initial PSW to use for trap service
svPC    =  2 <<2  ; save area for PC
svR1    =  3 <<2  ; save area for registers
svR2    =  4 <<2
svR3    =  5 <<2

...   save areas for R4-12

svRD    = 15 <<2
svRE    = 16 <<2
svRF    = 17 <<2
svPSW   = 18 <<2  ; save area for PSW
svMA    = 19 <<2  ; save area for trap MA
svSIZE  = 20 <<2  ; size of register-save area

Note that the SAVEREGS code assumes that this save area is at the base of a region of memory that will serve as the stack for the trap service routine, and it assumes that the routine called as myCODE uses R2 as a stack pointer for any local variables or temporaries it may require.

The trap and interrupt entry sequence runs with the level field of the PSW set to zero, preventing interrupts. Once the state of the interrupted code is saved, the PSW may be set with a level field that enables some interrupts during the service of this trap or interrupt. The myPSW field of the trap service record allows for this.

If a trap handler uses only a few registers before returning, an abbreviated version of SAVEREGS can be used that only saves those registers. If a trap handler uses any coprocessors, it will need to use an extended version of SAVEREGS that saves the required coprocessor registers.

This approach to trap service is at the extreme RISC end of the spectrum! Many machines include complex trap entry hardware that automatically saves and restores blocks of registers.