2 WHAT IS A TRAP?
The design of SPARC as a RISC processor means that a lot of the functionality that is normally controlled by complex instructions has to be done by supervisor (kernel) software. Examples of these could be memory exception handling or interrupt handling. When an event occurs that requires special handling in this way, the processor that detected that event will raise a trap so that the supervisor software is notified that it has to handle the event. We'll look at this mechanism in more detail in this section.
Traps can be generated for a number of reasons and you can see a list of traps under /usr/include/sys/v7/machtrap.h or under /usr/include/sys/v9/machtrap.h for SPARC v7/v8 and v9 respectively. Alternatively, refer to the appendices of this document for listings.
A trap can be caused either by an exception brought about by the execution of an instruction, an explicit trap instruction in running software (see 2.1.4, Software Traps) or triggered by some external interrupt request not directly related to the currently executing instruction.
In order to detect these
When the IU (Integer Unit, the part of the CPU that contains the
general purpose registers, does integer math and executes the
instructions) is about to execute an instruction it first checks
to see if there are any exception or interrupt conditions pending
and, if so, it selects the highest priority one and causes a trap.
Traps are also used to signal hardware faults and malfunctions,
for example a level15 asynchronous memory fault. In some fatal
conditions execution cannot continue and the machine will halt
or the supervisor software will handle the trap by panicing.
Next, we'll take a generic look at the different trap categories but we'll go into the version specific details later on.
A precise trap is brought about by an exception directly caused by
the executing instruction. This trap occurs before there is any
tangible change in the program state of the program that contained
the trapped instruction.
A deferred trap is similar to a precise trap but in this case the
program-visible state may have changed by the time the trap occurs.
Such a trap may in theory occur one or more instructions after the
trap inducing instruction has executed but it must occur before
any subsequent instruction attempts to use any modified register
or resource that the trap inducing instruction used.
For example, imagine that a floating point operation is being
executed. This does not happen synchronously with IU instructions
and so it is possible that a floating point exception could occur
as a deferred trap.
An interrupt trap, as you have probably guessed, is basically the
assertion of an interrupt, either generated externally (from
hardware) or internally (via software). The delivery of interrupts
is controlled by the PIL (Processor Interrupt Level) field of the
PSR (Processor State Register), which specifies the minimum
interrupt level to allow, and also by the mask of asserted bits in
the IE (Interrupt Enable register...architecture specific).
Under SPARC v9, we have a concept of a disrupt trap. This is very
similar to a deferred trap in that it could be related to an earlier
instruction but in this case the trap is an unrecoverable error.
Software traps are precise traps but I've decided to give a little more information about them here.
A software trap is basically what happens when we execute a trap instruction. The first half of the trap table is reserved for machine generated traps and so software traps start from 0x80 for SPARC v7/v8 or 0x100 for SPARC v9. When writing code that uses software traps, you simply use trap values from 0x0 to 0x7f for v7/v8 or from 0x0 to 0xff for v9. The specified trap value will automatically used as an offset from the start of the software traps. For example, software trap 0x8 is used to initiate a system call under SunOS 5.x and this maps to "real" trap 0x88 on SPARC v7/v8 or trap 0x108 on SPARC v9. If you attempt to use a trap value in a userland process that would fall off the end of the trap table when added to this software trap offset, an illegal instruction trap will occur. This will result in SIGILL being sent to your process.
2.2 How Traps are Dispatched to the Kernel
In this section we will look at the flow of execution into the
kernel when a trap occurs. This is different for SPARC v7/v8
and v9 so we will split this section into two.
When a trap occurs, the flow of execution jumps to an address which
is calculated from the Trap Base Register (TBR) and the
Trap Type (TT). The sequence is as follows:
sethi %hi(trap_handler), %l3 ! Load trap handler jmp [%l3 + %lo(trap_handler)] ! address and jump mov %psr, %l0 ! Delay: load %psr nopIt is the address of the trap table that is written into the TBR when the kernel is ready to handle traps. The kernel contains a table of trap vectors like the above example and it writes the address of this trap table into the TBR in it's startup code. You can look at the trap table on a running SunOS system by running adb against the kernel and looking at the instructions from "scb" onwards:
# adb -k physmem 1dec scb,8/ia _start: rd %psr, %l0 scb+4: ld [%l0], %f27 scb+8: jmp %l3 + 0x280 scb+0xc: clr %l4 scb+0x10: rd %psr, %l0 scb+0x14: sethi %hi(0xf0041000), %l3 scb+0x18: jmp %l3 + 0x280 scb+0x1c: mov 0x201, %l4Note that the trap table should be aligned on a 4096 byte boundary.
The SPARC v9 case is quite different from the v7/v8 case mainly due to the concept of processor states and trap nesting.
2.2.2.1 Trap Nesting
With the UltraSPARC architecture there is the concept of trap nesting. This defines a set of trap levels and a trap stack which the machine can use for more efficient trap processing. At the time of writing, there are five trap levels defined in the UltraSPARC architecture although the number of trap levels above four is implementation dependent.
The trap level register (TL) contains the current trap level of the processor. A processor normally executes at trap level zero (execute state). In SPARC v7/v8, the CPU enters trap state and system (supervisor) software (in other words, the kernel) has to save enough information about the processor state so that it can return from the trap successfully and also to prevent another error condition occurring whilst handling the trap. If an error occurs that would cause a trap when traps are already disabled (ie. we are in trap state), the v7/v8 CPU will watchdog reset. Upon completion of handling the trap, we have to restore the processor state before returning to the offending instruction (or terminating the process) and this time consuming operation is necessary because SPARC v7/v8 doesn't support trap nesting.
SPARC v9 handles things more efficiently. When a trap occurs, the CPU simply moves into the next trap level up (ie. TL is incremented). The most important processor states (PC, NPC and PSTATE) are saved on the trap stack. There is one set of trap state registers for each trap level and so entering a higher trap level is very fast and efficient. Here is an example of how we use trap levels to improve OS performance:
LEVEL 0: Normal program execution LEVEL 1: System calls, interrupt handlers LEVEL 2: Exceptions in OS routines LEVEL 3: Page fault handling LEVEL 4: RED state (see below)We still use a trap table concept under v9 but the destination address for the transfer of execution is calculated differently. Also, trap table entries for v9 are 8 instructions in size, except for spill/fill traps, in which case the entries are 32 instructions in size. Also, in a special state called the RED state (more on that later) we could use a different trap table!
The trap table is divided into three parts. The first half of the table is used for machine generated traps. The next quarter is reserved for software initiated traps and the final quarter is reserved for future use. The displacement into the trap table is defined by the trap level (TL) and the Trap Type (TT) together.
Let's take a look at this in some more detail. I strongly advise that you obtain a copy of the version 9 SPARC architecture manual if you want to follow this in detail.
When a trap occurs, the action taken depends on the TT, the current level of trap nesting (contained in the TL) and the processor state at that time. Let's look at processor states and what we mean by normal and special traps so that the rest of this section has more chance of making sense!
2.2.2.2 Processor States, Normal and Special Traps
The SPARC v9 processor is always in one of three states and these are:
Normal traps are traps that are processed when we are in the nice cosy execute state. If we trap in RED state, then this is a special trap. There is an implementation dependent address called the RED State Trap Vector Address (RSTVaddr) which contains the vector to the RED state trap table. This vector could be set to overlay the same one in the TBR. Under SunOS, the RSTVaddr table is at the same address as the normal trap table, so that the six RED state traps below overlay the first six entries in the trap table. The definition of those six RED state traps are:
- Execute state. This is the normal execution state.
- RED state. RED = Reset, Error and Debug. This is a state that is reserved for handling traps when we are at the penultimate level of trap nesting (TL = MAXTL - 1).
- Error state. This is a state that is entered when we have a trap occur at a point in time when we are at our maximum level of trap nesting (TL = MAXTL) or an unrecoverable fatal error has occurred.
TT Vector Reason 0 RSTVaddr|0x0 SPARC v8 style reset 1 RSTVaddr|0x20 Power On Reset (POR) 2 RSTVaddr|0x40 Watchdog Reset (WDR) 3 RSTVaddr|0x60 Externally Initiated Reset (XIR) 4 RSTVaddr|0x80 Software Initiated Reset (SIR) Others RSTVaddr|0xa0 All other traps in RED stateA fatal exception that causes us to drop into error state will cause the processor to note the exception and either halt, reset or watchdog reset. After the reset, the processor enters RED state with a TL appropriate to the type of reset (usually maximum). Also, the TT is set to the value of the original trap that caused the reset and not the TT value for the reset itself (ie. WDR - Watchdog reset or XIR - Externally Indicated Reset). When we reboot, if we detect that this RED state condition exists, we can interrogate the ECC (Error Check and Control) registers
Now that we have a concept of the different traps and processor states, let's look at the sequence of execution when a trap occurs to deliver the trap to the supervisor (kernel).
2.2.2.3 Normal Trap (Processor in Execute State)
- If TL = MAXTL-1, the processor enters RED state (Goto 2.2.2.3).
- TL = TL + 1
- Processor state, %pc, %npc, CWP, CCR (Condition Code Register), TT and ASI (Address Space Identifier register) are saved.
- The PSTATE (Processor State) register is updated as follows:
Refer to the architecture manual for a description of PSTATE
- RED field set to zero
- AM (Address Masking) disabled
- PRIV (Privileged Mode) enabled
- IE cleared, disabling interrupts
- AG set (Alternate Global Registers enabled)
- Endian mode set for traps (TLE)
- If TT is a register window trap, CWP is set to point to the register window to be accessed by the trap handler code.
Possibilities are:
Unlike SPARC v7/v7, non-register window traps do NOT result in a change in the CWP, as the nested trap concept provides some hardware support to preserve the processor state.
- TT = 0x24 (Clean Window), CWP = CWP + 1
- TT <= 0x80 AND TT <= 0xbf (Window Spill),
CWP = CWP + CANSAVE + 2. CANSAVE is a register that contains the number of register windows following the CWP that are NOT in use.- TT <= 0xc0 AND TT <= 0xff (Window fill),
CWP = CWP - 1- Control is transferred to the trap table at an address calculated as follows:
New %pc = TBA | (TL>0 ? 1: 0) | TL New %npc = TBA | (TL>0 ? 1: 0) | TL | 0x4Remember, TBA = Traptable Base Address, similar to the TBR in v8 Execution then resumes at the new %pc and %npc
2.2.2.4 Special Trap (Processor in RED State)
- TL = MAXTL
- The existing state is preserved as in 2.2.2.2, step 3.
- The PSTATE is modified as per 2.2.2.2, step 4 except that the RED field is asserted.
- If TT is a register window trap, CWP processing occurs as in 2.2.2.2, step 5.
- Implementation specific state changed may occur. For example, the MMU may be disabled.
- Control is transferred to the RED state trap table subject to the trap type. Look back to 2.2.2.1 for the RSTVaddr information to see how this vector is made.
This may seem rather complicated but once you have the picture built clearly it will all fall into place. Post or email if you need clarification.
Go to chapter 3 Back to table of contents