trap_table.s revision 7c478bd95313f5f23a4c958a745db2134aa03244
2N/A * The contents of this file are subject to the terms of the 2N/A * Common Development and Distribution License, Version 1.0 only 2N/A * (the "License"). You may not use this file except in compliance 2N/A * See the License for the specific language governing permissions 2N/A * and limitations under the License. 2N/A * When distributing Covered Code, include this CDDL HEADER in each 2N/A * If applicable, add the following below this CDDL HEADER, with the 2N/A * fields enclosed by brackets "[]" replaced with your own identifying 2N/A * information: Portions Copyright [yyyy] [name of copyright owner] 2N/A * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 2N/A * Use is subject to license terms. 2N/A#
pragma ident "%Z%%M% %I% %E% SMI" 2N/A * WARNING: If you add a fast trap handler which can be invoked by a 2N/A * non-privileged user, you may have to use the FAST_TRAP_DONE macro 2N/A * instead of "done" instruction to return back to the user mode. See 2N/A * comments for the "fast_trap_done" entry point for more information. 2N/A * An alternate FAST_TRAP_DONE_CHK_INTR macro should be used for the 2N/A * cases where you always want to process any pending interrupts before 2N/A * returning back to the user mode. 2N/A * SPARC V9 Trap Table 2N/A * Most of the trap handlers are made from common building 2N/A * blocks, and some are instantiated multiple times within 2N/A * the trap table. So, I build a bunch of macros, then 2N/A * populate the table using only the macros. 2N/A * Many macros branch to sys_trap. Its calling convention is: 2N/A * %g1 kernel trap handler 2N/A * %g2, %g3 args for above 2N/A * Tracing macro. Adds two instructions if TRAPTRACE is defined. 2N/A * This macro is used to update per cpu mmu stats in perf critical 2N/A * paths. It is only enabled in debug kernels or if SFMMU_STAT_GATHER 2N/A#
endif /* DEBUG || SFMMU_STAT_GATHER */ 2N/A * This first set are funneled to trap() with %tt as the type. 2N/A * Trap will then either panic or send the user a signal. 2N/A * NOT is used for traps that just shouldn't happen. 2N/A * It comes in both single and quadruple flavors. 2N/A * RED is for traps that use the red mode handler. 2N/A * We should never see these either. 2N/A * BAD is used for trap vectors we don't have a kernel 2N/A * It also comes in single and quadruple versions. 2N/A * TRAP vectors to the trap() function. 2N/A * It's main use is for user errors. 2N/A * SYSCALL is used for system calls on both ILP32 and LP64 kernels 2N/A * depending on the "which" parameter (should be either syscall_trap 2N/A * or syscall_trap32). 2N/A * GOTO just jumps to a label. 2N/A * It's used for things that can be fixed without going thru sys_trap. 2N/A * GOTO_TT just jumps to a label. 2N/A * correctable ECC error traps at level 0 and 1 will use this macro. 2N/A * It's used for things that can be fixed without going thru sys_trap. 2N/A * Takes breakpoint if privileged, calls trap() if not. 2N/A * REGISTER WINDOW MANAGEMENT MACROS 2N/A * various convenient units of padding 2N/A * CLEAN_WINDOW is the simple handler for cleaning a register window. 2N/A * If we get an unresolved tlb miss while in a window handler, the fault 2N/A * handler will resume execution at the last instruction of the window 2N/A * hander, instead of delivering the fault to the kernel. Spill handlers 2N/A * use this to spill windows into the wbuf. 2N/A * The mixed handler works by checking %sp, and branching to the correct 2N/A * handler. This is done by branching back to label 1: for 32b frames, 2N/A * or label 2: for 64b frames; which implies the handler order is: 32b, 2N/A * 64b, mixed. The 1: and 2: labels are offset into the routines to 2N/A * allow the branchs' delay slots to contain useful instructions. 2N/A * SPILL_32bit spills a 32-bit-wide kernel register window. It 2N/A * assumes that the kernel context and the nucleus context are the 2N/A * same. The stack pointer is required to be eight-byte aligned even 2N/A * though this code only needs it to be four-byte aligned. 2N/A * SPILL_32bit_asi spills a 32-bit-wide register window into a 32-bit 2N/A * wide address space via the designated asi. It is used to spill 2N/A * non-kernel windows. The stack pointer is required to be eight-byte 2N/A * aligned even though this code only needs it to be four-byte 2N/A * SPILL_32bit_tt1 spills a 32-bit-wide register window into a 32-bit 2N/A * wide address space via the designated asi. It is used to spill 2N/A * windows at tl>1 where performance isn't the primary concern and 2N/A * where we don't want to use unnecessary registers. The stack 2N/A * pointer is required to be eight-byte aligned even though this code 2N/A * only needs it to be four-byte aligned. 2N/A * FILL_32bit fills a 32-bit-wide kernel register window. It assumes 2N/A * that the kernel context and the nucleus context are the same. The 2N/A * stack pointer is required to be eight-byte aligned even though this 2N/A * code only needs it to be four-byte aligned. 2N/A * FILL_32bit_asi fills a 32-bit-wide register window from a 32-bit 2N/A * wide address space via the designated asi. It is used to fill 2N/A * non-kernel windows. The stack pointer is required to be eight-byte 2N/A * aligned even though this code only needs it to be four-byte 2N/A * FILL_32bit_tt1 fills a 32-bit-wide register window from a 32-bit 2N/A * wide address space via the designated asi. It is used to fill 2N/A * windows at tl>1 where performance isn't the primary concern and 2N/A * where we don't want to use unnecessary registers. The stack 2N/A * pointer is required to be eight-byte aligned even though this code 2N/A * only needs it to be four-byte aligned. 2N/A * SPILL_64bit spills a 64-bit-wide kernel register window. It 2N/A * assumes that the kernel context and the nucleus context are the 2N/A * same. The stack pointer is required to be eight-byte aligned. 2N/A * SPILL_64bit_asi spills a 64-bit-wide register window into a 64-bit 2N/A * wide address space via the designated asi. It is used to spill 2N/A * non-kernel windows. The stack pointer is required to be eight-byte 2N/A * SPILL_64bit_tt1 spills a 64-bit-wide register window into a 64-bit 2N/A * wide address space via the designated asi. It is used to spill 2N/A * windows at tl>1 where performance isn't the primary concern and 2N/A * where we don't want to use unnecessary registers. The stack 2N/A * pointer is required to be eight-byte aligned. 2N/A * FILL_64bit fills a 64-bit-wide kernel register window. It assumes 2N/A * that the kernel context and the nucleus context are the same. The 2N/A * stack pointer is required to be eight-byte aligned. 2N/A * FILL_64bit_asi fills a 64-bit-wide register window from a 64-bit 2N/A * wide address space via the designated asi. It is used to fill 2N/A * non-kernel windows. The stack pointer is required to be eight-byte 2N/A * FILL_64bit_tt1 fills a 64-bit-wide register window from a 64-bit 2N/A * wide address space via the designated asi. It is used to fill 2N/A * windows at tl>1 where performance isn't the primary concern and 2N/A * where we don't want to use unnecessary registers. The stack 2N/A * pointer is required to be eight-byte aligned. 2N/A * SPILL_mixed spills either size window, depending on 2N/A * whether %sp is even or odd, to a 32-bit address space. 2N/A * This may only be used in conjunction with SPILL_32bit/ 2N/A * SPILL_64bit. New versions of SPILL_mixed_{tt1,asi} would be 2N/A * needed for use with SPILL_{32,64}bit_{tt1,asi}. Particular 2N/A * attention should be paid to the instructions that belong 2N/A * in the delay slots of the branches depending on the type 2N/A * of spill handler being branched to. 2N/A * Clear upper 32 bits of %sp if it is odd. 2N/A * We won't need to clear them in 64 bit kernel. 2N/A * FILL_mixed(ASI) fills either size window, depending on 2N/A * whether %sp is even or odd, from a 32-bit address space. 2N/A * This may only be used in conjunction with FILL_32bit/ 2N/A * FILL_64bit. New versions of FILL_mixed_{tt1,asi} would be 2N/A * needed for use with FILL_{32,64}bit_{tt1,asi}. Particular 2N/A * attention should be paid to the instructions that belong 2N/A * in the delay slots of the branches depending on the type 2N/A * of fill handler being branched to. 2N/A * Clear upper 32 bits of %sp if it is odd. 2N/A * We won't need to clear them in 64 bit kernel. 2N/A * respectively, into the address space via the designated asi. The 2N/A * unbiased stack pointer is required to be eight-byte aligned (even for 2N/A * the 32-bit case even though this code does not require such strict 2N/A * With SPARC v9 the spill trap takes precedence over the cleanwin trap 2N/A * so when cansave == 0, canrestore == 6, and cleanwin == 6 the next save 2N/A * will cause cwp + 2 to be spilled but will not clean cwp + 1. That 2N/A * window may contain kernel data so in user_rtt we set wstate to call 2N/A * these spill handlers on the first user spill trap. These handler then 2N/A * spill the appropriate window but also back up a window and clean the 2N/A * window that didn't get a cleanwin trap. 2N/A * Floating point disabled. 2N/A * Floating point exceptions. 2N/A * asynchronous traps at level 0 and level 1 2N/A * The first instruction must be a membar for UltraSPARC-III 2N/A * to stop RED state entry if the store queue has many 2N/A * pending bad stores (PRM, Chapter 11). 2N/A * Defaults to BAD entry, but establishes label to be used for 2N/A * architecture-specific overwrite of trap table entry. 2N/A * illegal instruction trap 2N/A * divide by zero trap 2N/A * trap instruction for V9 user trap handlers 2N/A * LEVEL_INTERRUPT is for level N interrupts. 2N/A * VECTOR_INTERRUPT is for the vector trap. 2N/A * MMU Trap Handlers. 2N/A * SPARC V9 IMPL. DEP. #109(1) and (2) and #110(1) and (2) 2N/A * Flush the TLB using either the primary, secondary, or nucleus flush 2N/A * operation based on whether the ctx from the tag access register matches 2N/A * the primary or secondary context (flush the nucleus if neither matches). 2N/A * Requires a membar #Sync before next ld/st. 2N/A * g2 = tag access register 2N/A#
error "TAGACC_CTX_MASK != CTXREG_CTX_MASK" 2N/A * Define labels to direct cscope quickly to labels that 2N/A * are generated by macro expansion of DTLB_MISS(). 2N/A * Needs to be exactly 32 instructions 2N/A * UTLB NOTE: If we don't hit on the 8k pointer then we branch 2N/A * to a special 4M tsb handler. It would be nice if that handler 2N/A * could live in this file but currently it seems better to allow 2N/A * it to fall thru to sfmmu_tsb_miss. 2N/A * Define labels to direct cscope quickly to labels that 2N/A * are generated by macro expansion of ITLB_MISS(). 2N/A * Instruction miss handler. 2N/A * ldda instructions will have their ASI patched 2N/A * by sfmmu_patch_ktsb at runtime. 2N/A * MUST be EXACTLY 32 instructions or we'll break. 2N/A * This macro is the first level handler for fast protection faults. 2N/A * It first demaps the tlb entry which generated the fault and then 2N/A * attempts to set the modify bit on the hash. It needs to be 2N/A * exactly 32 instructions. 2N/A * g2 = tag access register ;\ 2N/A * g3 = ctx number ;\ 2N/A /* clobbers g1 and g6 */ ;\
2N/A * g2 = tag access register (in) 2N/A * g3 - g4 = scratch (clobbered) 2N/A * g5 = tsbe data (in) 2N/A * g6 = scratch (clobbered) 2N/A * g7 = pc we jumped here from (in) 2N/A * ttextra = value to OR in to trap type (%tt) (in) 2N/A * ======================================================================= 2N/A * SPARC V9 TRAP TABLE 2N/A * The trap table is divided into two halves: the first half is used when 2N/A * taking traps when TL=0; the second half is used when taking traps from 2N/A * TL>0. Note that handlers in the second half of the table might not be able 2N/A * to make the same assumptions as handlers in the first half of the table. 2N/A * Worst case trap nesting so far: 2N/A * at TL=0 client issues software trap requesting service 2N/A * at TL=1 nucleus wants a register window 2N/A * at TL=3 processing TLB miss 2N/A * at TL=4 handle asynchronous error 2N/A * Note that a trap from TL=4 to TL=5 places Spitfire in "RED mode". 2N/A * ======================================================================= 2N/A /* hardware traps */ 2N/A RED;
/* 003 externally initiated reset */ 2N/A RED;
/* 004 software initiated reset */ 2N/A RED;
/* 005 red mode exception */ 2N/A NOT;
/* 009 instruction access MMU miss */ 2N/A /* 00A instruction access error */ 2N/A NOT;
/* 012 unimplemented LDD */ 2N/A NOT;
/* 013 unimplemented STD */ 2N/A NOT;
/* 029 internal processor error */ 2N/A NOT;
/* 031 data access MMU miss */ 2N/A /* 032 data access error */ 2N/A NOT;
/* 033 data access protection */ 2N/A NOT;
/* 038 LDQF mem address not aligned */ 2N/A NOT;
/* 039 STQF mem address not aligned */ 2N/A NOT;
/* 040 async data error */ 2N/A /* 17C test ptl1_panic */ 2N/A#
endif /* PTL1_PANIC_DEBUG */ 2N/A /* 00A instruction access error */ 2N/A /* 032 data access error */ 2N/A * We only reserve the above four special case soft traps for code running 2N/A * at TL>0, so we can truncate the trap table here. 2N/A * We get to exec_fault in the case of an instruction miss and tte 2N/A * has no execute bit set. We go to tl0 to handle it. 2N/A * g2 = tag access register (in) 2N/A * g3 - g4 = scratch (clobbered) 2N/A * g5 = tsbe data (in) 2N/A * g6 = scratch (clobbered) 2N/A * g7 = pc we jumped here from (in) 2N/A * %g5 user trap handler 2N/A * %g7 misaligned addr - for alignment traps only 2N/A * If the DTrace pid provider is single stepping a copied-out 2N/A * instruction, t->t_dtrace_step will be set. In that case we need 2N/A * to abort the single-stepping (since execution of the instruction 2N/A * was interrupted) and use the value of t->t_dtrace_npc as the %npc. 2N/A * %g5 user trap handler 2N/A * If the DTrace pid provider is single stepping a copied-out 2N/A * instruction, t->t_dtrace_step will be set. In that case we need 2N/A * to abort the single-stepping (since execution of the instruction 2N/A * was interrupted) and use the value of t->t_dtrace_npc as the %npc. 2N/A * Cheetah takes unfinished_FPop trap for certain range of operands 2N/A * to the "fitos" instruction. Instead of going through the slow 2N/A * software emulation path, we try to simulate the "fitos" instruction 2N/A * via "fitod" and "fdtos" provided the following conditions are met: 2N/A * fpu_exists is set (if DEBUG) 2N/A * not in privileged mode 2N/A * ftt is unfinished_FPop 2N/A * NXM IEEE trap is not enabled 2N/A * instruction at %tpc is "fitos" 2N/A * %g1 per cpu address 2N/A * %g6 user instruction 2N/A * Note that we can take a memory access related trap while trying 2N/A * to fetch the user instruction. Therefore, we set CPU_TL1_HDLR 2N/A * flag to catch those traps and let the SFMMU code deal with page 2N/A * fault and data access exception. 2N/A st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 2N/A set FITOS_INSTR_MASK, %g7 2N/A set FITOS_INSTR, %g5 2N/A bne,pn %xcc, .fp_exception_cont ! branch if not FITOS_INSTR 2N/A * This is unfinished FPops trap for "fitos" instruction. We 2N/A * need to simulate "fitos" via "fitod" and "fdtos" instruction 2N/A * We need a temporary FP register to do the conversion. Since 2N/A * both source and destination operands for the "fitos" instruction 2N/A * have to be within %f0-%f31, we use an FP register from the upper 2N/A * Now convert data back into single precision 2N/A * Update FPop_unfinished trap kstat 2N/A * Update fpu_sim_fitos kstat 2N/A * Let _fp_exception deal with simulating FPop instruction. 2N/A * Note that we need to pass %fsr in %g2 (already read above). 2N/A * .spill_clean: clean the previous window, restore the wstate, and 2N/A * Entry: %g7 contains new wstate 2N/A * Cheetah overwrites SFAR on a DTLB miss, hence read it now. 2N/A srl %g6, 23, %g1 ! using ldda or not? 2N/A brz,a,pt %g1, 2f ! check for ldda instruction 2N/A srl %g6, 13, %g1 ! check immflag 2N/A rdpr %tstate, %g2 ! %tstate in %g2 2N/A srl %g2, 31, %g1 ! get asi from %tstate 2N/A srl %g6, 5, %g1 ! get asi from instruction 2N/A and %g1, 0xFF, %g1 ! imm_asi field 2N/A cmp %g1, ASI_P ! primary address space 2N/A cmp %g1, ASI_PNF ! primary no fault address space 2N/A cmp %g1, ASI_S ! secondary address space 2N/A cmp %g1, ASI_SNF ! secondary no fault address space 2N/A lduwa [%g5]ASI_USER, %g7 ! get first half of misaligned data 2N/A add %g5, 4, %g5 ! increment misaligned data address 2N/A lduwa [%g5]ASI_USER, %g5 ! get second half of misaligned data 2N/A or %g5, %g7, %g5 ! combine data 2N/A CPU_ADDR(%g7, %g1) ! save data on a per-cpu basis 2N/A stx %g5, [%g7 + CPU_TMP1] ! save in cpu_tmp1 2N/A srl %g6, 25, %g3 ! %g6 has the instruction 2N/A and %g3, 0x1F, %g3 ! %g3 has rd 2N/A LDDF_REG(%g3, %g7, %g4) 2N/A st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 2N/A st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 2N/A set T_USER, %g3 ! trap type in %g3 2N/A or %g3, T_LDDF_ALIGN, %g3 2N/A mov %g5, %g2 ! misaligned vaddr in %g2 2N/A set fpu_trap, %g1 ! goto C for the little and 2N/A ba,pt %xcc, sys_trap ! no fault little asi's
2N/A * Cheetah overwrites SFAR on a DTLB miss, hence read it now. 2N/A srl %g6, 23, %g1 ! using stda or not? 2N/A brz,a,pt %g1, 2f ! check for stda instruction 2N/A srl %g6, 13, %g1 ! check immflag 2N/A rdpr %tstate, %g2 ! %tstate in %g2 2N/A srl %g2, 31, %g1 ! get asi from %tstate 2N/A srl %g6, 5, %g1 ! get asi from instruction 2N/A and %g1, 0xFF, %g1 ! imm_asi field 2N/A cmp %g1, ASI_P ! primary address space 2N/A cmp %g1, ASI_S ! secondary address space 2N/A and %g6, 0x1F, %g6 ! %g6 has rd 2N/A STDF_REG(%g6, %g7, %g4) ! STDF_REG(REG, ADDR, TMP) 2N/A ldx [%g7 + CPU_TMP1], %g6 2N/A stuwa %g7, [%g5]ASI_USER ! first half 2N/A add %g5, 4, %g5 ! increment misaligned data address 2N/A stuwa %g6, [%g5]ASI_USER ! second half 2N/A st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 2N/A st %g0, [%g1 + CPU_TL1_HDLR] ! clear tl1_hdlr flag 2N/A set T_USER, %g3 ! trap type in %g3 2N/A or %g3, T_STDF_ALIGN, %g3 2N/A mov %g5, %g2 ! misaligned vaddr in %g2 2N/A set fpu_trap, %g1 ! goto C for the little and 2N/A ba,pt %xcc, sys_trap ! nofault little asi's
2N/A#
endif /* DEBUG_USER_TRAPTRACECTL */ 2N/A * Note that the xcc part of the ccr is not provided. 2N/A * The V8 code shows why the V9 trap is not faster: 2N/A * #define GETPSR_TRAP() \ 2N/A * mov %psr, %i0; jmp %l2; rett %l2+4; nop; 2N/A * Note that there is no support for ccr.xcc in the V9 code. 2N/A * get home lgrpid on which the calling thread is currently executing. 2N/A * Entry for old 4.x trap (trap 0). 2N/A * Handler for software trap 9. 2N/A * Set trap0 emulation address for old 4.x system call trap. 2N/A * XXX - this should be a system call. 2N/A * trap handler for unexpected mmu traps. 2N/A * simply checks if the trap was a user lddf/stdf alignment trap, in which 2N/A * case we go to fpu_trap or a user trap from the window handler, in which 2N/A * case we go save the state on the pcb. Otherwise, we go to ptl1_panic. 2N/A#
endif /* TRAPTRACE */ 2N/A * We are running on a Panther and have hit a DTLB parity error. 2N/A * AM is cleared on trap, so addresses are 64 bit 2N/A * We are going to update cpu_m.tl1_hdlr using physical address. 2N/A * Flush the D$ line, so that stale data won't be accessed later. 2N/A /* tpc should be in the trap table */ 2N/A * Several traps use kmdb_trap and kmdb_trap_tl1 as their handlers. These 2N/A * traps are valid only when kmdb is loaded. When the debugger is active, 2N/A * the code below is rewritten to transfer control to the appropriate 2N/A * debugger entry points. 2N/A * This entry is copied from OBP's trap table during boot. 2N/A * if kernel, set PCONTEXT to 0 for debuggers 2N/A * if user, clear nucleus page sizes 2N/A * TRAPTRACE support. 2N/A * labels here are branched to with "rd %pc, %g7" in the delay slot. 2N/A * Return is done by "jmp %g7 + 4". 2N/A * g2 = tag access register (in) 2N/A * g3 - g4 = scratch (clobbered) 2N/A * g5 = tsbe data (in) 2N/A * g6 = scratch (clobbered) 2N/A * g7 = pc we jumped here from (in) 2N/A * g1 = tsb8k pointer (in) 2N/A * g2 = tag access register (in) 2N/A * g3 = tsb4m pointer (in) 2N/A * g5 - g6 = scratch (clobbered) 2N/A * g7 = pc we jumped here from (in) 2N/A * g2 = tag access register (in) 2N/A * g3 = ctx number (in) 2N/A#
endif /* TRAPTRACE */ 2N/A * expects offset into tsbmiss area in %g1 and return pc in %g7 2N/A * fast_trap_done, fast_trap_done_chk_intr: 2N/A * Due to the design of UltraSPARC pipeline, pending interrupts are not 2N/A * taken immediately after a RETRY or DONE instruction which causes IE to 2N/A * go from 0 to 1. Instead, the instruction at %tpc or %tnpc is allowed 2N/A * to execute first before taking any interrupts. If that instruction 2N/A * results in other traps, and if the corresponding trap handler runs 2N/A * entirely at TL=1 with interrupts disabled, then pending interrupts 2N/A * won't be taken until after yet another instruction following the %tpc 2N/A * A malicious user program can use this feature to block out interrupts 2N/A * for extended durations, which can result in send_mondo_timeout kernel 2N/A * This problem is addressed by servicing any pending interrupts via 2N/A * sys_trap before returning back to the user mode from a fast trap 2N/A * handler. The "done" instruction within a fast trap handler, which 2N/A * runs entirely at TL=1 with interrupts disabled, is replaced with the 2N/A * FAST_TRAP_DONE macro, which branches control to this fast_trap_done 2N/A * We check for any pending interrupts here and force a sys_trap to 2N/A * service those interrupts, if any. To minimize overhead, pending 2N/A * interrupts are checked if the %tpc happens to be at 16K boundary, 2N/A * which allows a malicious program to execute at most 4K consecutive 2N/A * instructions before we service any pending interrupts. If a worst 2N/A * case fast trap handler takes about 2 usec, then interrupts will be 2N/A * blocked for at most 8 msec, less than a clock tick. 2N/A * For the cases where we don't know if the %tpc will cross a 16K 2N/A * boundary, we can't use the above optimization and always process 2N/A * any pending interrupts via fast_frap_done_chk_intr entry point. 2N/A * %pstate am:0 priv:1 ie:0 2N/A * globals are AG (not normal globals) 2N/A andncc %g5, %g6, %g0 ! check lower 14 bits of %tpc 2N/A bz,a,pn %icc, 1f ! branch if zero (lower 32 bits only) 2N/A ldxa [%g0]ASI_INTR_RECEIVE_STATUS, %g5 2N/Afast_trap_done_chk_intr: 2N/A ldxa [%g0]ASI_INTR_RECEIVE_STATUS, %g5 2N/A and %g5, IRSR_BUSY, %g5 2N/A bnz,pn %xcc, 2f ! branch if any pending intr 2N/A * We get here if there are any pending interrupts. 2N/A * Force a dummy sys_trap call so that interrupts can be serviced.