• Aucun résultat trouvé

* Nested exceptions typically require saving the EPC, Status and SRSCtl registers, * setting up the appropriate GPR shadow set for the routine, disabling

* the appropriate IM bits in Status to prevent an interrupt loop, putting * the processor in kernel mode, and re-enabling interrupts. The sample code * below can not cover all nuances of this processing and is intended only * to demonstrate the concepts.

*/

/* Use the current GPR shadow set, and setup software context */

dmfc0 k0, C0_EPC /* Get restart address */

sd k0, EPCSave /* Save in memory */

mfc0 k0, C0_Status /* Get Status value */

IP7

sw k0, StatusSave /* Save in memory */

mfc0 k0, C0_SRSCtl /* Save SRSCtl if changing shadow sets */

sw k0, SRSCtlSave

li k1, ~IMbitsToClear /* Get Im bits to clear for this interrupt */

/* this must include at least the IM bit */

/* for the current interrupt, and may include */

/* others */

and k0, k0, k1 /* Clear bits in copy of Status */

/* If switching shadow sets, write new value to SRSCtlPSS here */

ins k0, zero, S_StatusEXL, (W_StatusKSU+W_StatusERL+W_StatusEXL) /* Clear KSU, ERL, EXL bits in k0 */

mtc0 k0, C0_Status /* Modify mask, switch to kernel mode, */

/* re-enable interrupts */

/*

* If switching shadow sets, clear only KSU above, write target * address to EPC, and do execute an eret to clear EXL, switch * shadow sets, and jump to routine

*/

/* Process interrupt here, including clearing device interrupt */

/*

* To complete interrupt processing, the saved values must be restored * and the original interrupted code restarted.

*/

di /* Disable interrupts - may not be required */

lw k0, StatusSave /* Get saved Status (including EXL set) */

ld k1, EPCSave /* and EPC */

mtc0 k0, C0_Status /* Restore the original value */

lw k0, SRSCtlSave /* Get saved SRSCtl */

dmtc0 k1, C0_EPC /* and EPC */

mtc0 k0, C0_SRSCtl /* Restore shadow sets */

ehb /* Clear hazard */

eret /* Dismiss the interrupt */

6.1.1.3 External Interrupt Controller Mode

External Interrupt Controller Mode redefines the way that the processor interrupt logic is configured to provide sup-port for an external interrupt controller. The interrupt controller is responsible for prioritizing all interrupts, including hardware, software, timer, and performance counter interrupts, and directly supplying to the processor the vector number (and optionally the priority level) of the highest priority interrupt. EIC interrupt mode is in effect if all of the following conditions are true:

• Config3VEIC = 1

• IntCtlVS≠ 0

• CauseIV = 1

• StatusBEV = 0

In EIC interrupt mode, the processor sends the state of the software interrupt requests (CauseIP1..IP0), the timer inter-rupt request (CauseTI), and the performance counter interrupt request (CausePCI) to the external interrupt controller, where it prioritizes these interrupts in a system-dependent way with other hardware interrupts. The interrupt

control-ler can be a hard-wired logic block, or it can be configurable based on control and status registers. This allows the interrupt controller to be more specific or more general as a function of the system environment and needs.

The external interrupt controller prioritizes its interrupt requests and produces the priority level and the vector number of the highest priority interrupt to be serviced. The priority level, called the Requested Interrupt Priority Level (RIPL), is a 6-bit encoded value in the range 0..63, inclusive. A value of 0 indicates that no interrupt requests are pending. The values 1..63 represent the lowest (1) to highest (63) RIPL for the interrupt to be serviced. The interrupt controller passes this value on the 6 hardware interrupt lines, which are treated as an encoded value in EIC interrupt mode. There are several implementation options available for the vector offset:

1. The first option is to treat the RIPL value as the vector number for the processor.

2. The second option is to send a separate vector number along with the RIPL to the processor.

3. A third option is to send an entire vector offset along with the RIPL to the processor.

StatusIPL(which overlays StatusIM7..IM2) is interpreted as the Interrupt Priority Level (IPL) at which the processor is currently operating (with a value of zero indicating that no interrupt is currently being serviced). When the interrupt controller requests service for an interrupt, the processor compares RIPL with StatusIPLto determine if the requested interrupt has higher priority than the current IPL. If RIPL is strictly greater than StatusIPL, and interrupts are enabled (StatusIE = 1, StatusEXL = 0, and StatusERL = 0) an interrupt request is signaled to the pipeline. When the processor starts the interrupt exception, it loads RIPL into CauseRIPL (which overlays CauseIP7..IP2) and signals the external interrupt controller to notify it that the request is being serviced. Because CauseRIPL is only loaded by the processor when an interrupt exception is signaled, it is available to software during interrupt processing. The vector number that the EIC passes into the core is combined with the IntCtlVS to determine where the interrupt service routines is located. The vector number is not stored in any software visible register. Some implementations may choose to use the RIPL as the vector number, but this is not a requirement.

In EIC interrupt mode, the external interrupt controller is also responsible for supplying the GPR shadow set number to use when servicing the interrupt. As such, theSRSMap register is not used in this mode, and the mapping of the vectored interrupt to a GPR shadow set is done by programming (or designing) the interrupt controller to provide the correct GPR shadow set number when an interrupt is requested. When the processor loads an interrupt request into CauseRIPL, it also loads the GPR shadow set number into SRSCtlEICSS, which is copied to SRSCtlCSSwhen the inter-rupt is serviced.

The operation of EIC interrupt mode is shown pictorially inFigure 6-2.

Figure 6-2 Interrupt Generation for External Interrupt Controller Interrupt Mode

A typical software handler for EIC interrupt mode bypasses the entire sequence of code following the IVexception label shown for the compatibility mode handler above. Instead, the hardware performs the prioritization, dispatching directly to the interrupt processing routine. Unlike the compatibility mode examples, an EIC interrupt handler may take advantage of a dedicated GPR shadow set to avoid saving any registers. As such, the SimpleInterrupt code shown above need not save the GPRs.

A nested interrupt is similar to that shown for compatibility mode, but may also take advantage of running the nested exception routine in the GPR shadow set dedicated to the interrupt or in another shadow set. It also need only copy CauseRIPLto StatusIPLto prevent lower priority interrupts from interrupting the handler. Such a routine might look as follows:

NestedException:

/*

* Nested exceptions typically require saving the EPC, Status,and SRSCtl registers, * setting up the appropriate GPR shadow set for the routine, disabling

* the appropriate IM bits in Status to prevent an interrupt loop, putting * the processor in kernel mode, and re-enabling interrupts. The sample code * below can not cover all nuances of this processing and is intended only * to demonstrate the concepts.

*/

/* Use the current GPR shadow set, and setup software context */

mfc0 k1, C0_Cause /* Read Cause to get RIPL value */

dmfc0 k0, C0_EPC /* Get restart address */

srl k1, k1, S_CauseRIPL /* Right justify RIPL field */

sd k0, EPCSave /* Save in memory */

mfc0 k0, C0_Status /* Get Status value */

CauseTI CausePCI

StatusIE

Interrupt Request

Option1 - RIPL as Vector Number

Interrupt Sources Shadow Set Mapping

CauseIP1 CauseIP0

Requested IPL

CauseRIPL

StatusIPL SRSCtlEICSS

RIPL

Option2- Explicit Vector Number

Option3 - Explicit Vector Offset