diff options
Diffstat (limited to 'src/ssx/ppc405/ppc405_exceptions.S')
-rwxr-xr-x | src/ssx/ppc405/ppc405_exceptions.S | 832 |
1 files changed, 832 insertions, 0 deletions
diff --git a/src/ssx/ppc405/ppc405_exceptions.S b/src/ssx/ppc405/ppc405_exceptions.S new file mode 100755 index 0000000..c8be2e3 --- /dev/null +++ b/src/ssx/ppc405/ppc405_exceptions.S @@ -0,0 +1,832 @@ +// $Id: ppc405_exceptions.S,v 1.1.1.1 2013/12/11 21:03:27 bcbrock Exp $ +// $Source: /afs/awd/projects/eclipz/KnowledgeBase/.cvsroot/eclipz/chips/p8/working/procedures/ssx/ppc405/ppc405_exceptions.S,v $ +//----------------------------------------------------------------------------- +// *! (C) Copyright International Business Machines Corp. 2013 +// *! All Rights Reserved -- Property of IBM +// *! *** IBM Confidential *** +//----------------------------------------------------------------------------- + +/// \file ppc405_exceptions.S +/// \brief PPC405 exception vector area. +/// +/// The PowerPC exception vector area has many small and large 'holes' in the +/// SSX implementation. These are due to numerous unhandled exceptions and +/// unimplemented exceptions in the exception vector area that comprises 8KB +/// in the 405. SSX interrupt handling and other code is 'packed' into these +/// holes to reduce the effective code footprint of SSX. The packing is done +/// (hopefully) on a reasonable basis - we haven't tried to squeeze every last +/// byte by chopping up routines willy-nilly and stitching them together with +/// random branches - but some fragmentation has occurred in the interrupt +/// handling code. +/// +/// To facilitate the packing, the exception vector area is divided into 5 ELF +/// sections (addresses are offsets into the exception area) +/// +/// .vectors_0000 - Empty section for adding image header +/// +/// .vectors_0100 - From 0x0100 to 0x0bff. The beginning of the table through +/// the large space prior to the system call vector. +/// +/// .vectors_0c00 - From 0x0c00 to 0x0eff. This is a moderately large area +/// after the system call vector. +/// +/// .vectors_0f00 - From 0x0f00 to 0x1fff. From the APU Unavailable vector +/// through the major 3.5K hole above the Debug vector. +/// +/// .vectors_2000 - From 0x2000 to 0x2003 - branch to the Debug handler. +/// +/// The exception vector area must be aligned on a 64KB boundary. +/// +/// Note that PgP mainstore boot and interrupt controller handling is +/// currently hard-coded into this file - but it can easily be generalized if +/// a port to another environment is required, assuming the new environment +/// has something similar to a PgP or 405 ASIC interrupt controller. +/// +/// \cond + + .nolist +#include "ssx.h" + .list + +### **************************************************************************** +### .vectors_0000 - Empty section ( Image header will be placed in this section +### from the linker command file ) +### **************************************************************************** + + .section .vectors_0000, "a", @progbits + .global __vectors + .global __vectors_0000 +__vectors: +__vectors_0000: + +### **************************************************************************** +### .vectors_0100 +### **************************************************************************** + .section .vectors_0100, "ax", @progbits + + .global __vectors_0100 + +__vectors_0100: + + ############################################################ + # 0x0100 : Critical Interrupt + ############################################################ + +__critical_interrupt: + + ## The critical interrupt handler entry point is re-entrant - A handler + ## may allow preemption, which could cause another entry here. + + ## Entry invariants: + ## 1. Critical interupts are disabled; + ## 2. The SP points to a thread stack, the non-critical stack or + ## critical stack + + ## Since fast-mode handlers can not use SSX services or alter the + ## machine context, the exit of a fast mode handler is a simple RF(C)I. + + ## Begin by pushing the fast context on the stack. + + _ssx_fast_ctx_push SSX_CRITICAL + + ## Load critical status 0 and the handler array base address. Check + ## for interrupts pending in status register 0 while the IRQ is + ## computed and R5 is loaded with the critical flag. + + _lwzi %r3, %r3, OCB_OCISR0 + _liw %r6, __ppc405_irq_handlers + cmpwi %r3, 0 + cntlzw %r4, %r3 + li %r5, SSX_CRITICAL + bne+ critical_irq_found + + ## No IRQ pending in interrupt set 0. Try set 1. + + _lwzi %r3, %r3, OCB_OCISR1 + cmpwi %r3, 0 + cntlzw %r4, %r3 + addi %r4, %r4, 32 + beq- critical_phantom + + ## An active IRQ was found. At entry here R6 has the handler table + ## base address, R4 has the IRQ number, and R5 has the critical + ## flag. The IRQ is converted into a pointer to an 8-byte handler + ## structure, and the handler is dispatched. The call is made with the + ## parameters: + + ## R3 = private + ## R4 = irq + ## R5 = SSX_CRITICAL + +critical_irq_found: + + _save_update_kernel_context SSX_CRITICAL, %r4, %r7 + slwi %r3, %r4, 3 + lwzux %r7, %r6, %r3 + lwz %r3, 4(%r6) + mtlr %r7 + blrl + + ## Pop the stack/RFCI when (if) it returns here. + +fast_exit_critical: + + _ssx_fast_ctx_pop_exit SSX_CRITICAL + + ## This is a phantom interrupt - we got interrupted but no status bits + ## are set. The interrupt is marked as #64. The register used for the + ## handler table address (R6) is set to the special structure for the + ## phantom interrupt, with it's address adjusted to make it appear to + ## be the 64th entry in the table. + +critical_phantom: + + _liw %r6, __ppc405_phantom_irq + subi %r6, %r6, (64 * 8) + b critical_irq_found + + + ############################################################ + # 0x0200 : Machine Check, Data or Instruction + ############################################################ + + .org __vectors_0100 + 0x0100 +__machine_check: + + PPC405_MACHINE_CHECK_HANDLER + + .org __machine_check + 0x20 + + .global __ssx_irq_fast2full +__ssx_irq_fast2full: + + ## Convert a fast-mode to a full-mode interrupt by saving the + ## (volatile - fast) context, and switching to the appropriate system + ## stack. + + ## Entry invariants: + ## 1. The SP/stack must be exactly as it was when the fast-mode + ## handler was entered. + ## 2. No changes have been made to the MSR - the interrupt level must + ## remain disabled. + ## 3. The handler owns the fast context and has not modified the other + ## register context. This routine can only use the (volatile - + ## fast) register context. + + ## 41 (linear) instructions plus alignmenmt + + ## Start by pushing the (volatile - fast) context. Technically we also + ## need to save the CR as our contract with the handler is not to + ## disturb any of its register state. + + _ssx_vol_fast_ctx_push SSX_IRQ_CONTEXT + mfcr %r12 + + ## USPRG0 tells whether this is a critical or non-critical interrupt. + ## The high-order 8 bits of USPRG0 counts critical interrupt nesting, + ## and the SSX preemption rules guarantee that if the count is > 0 then + ## we are in a critical handler. + + mfusprg0 %r8 + extrwi. %r9, %r8, 8, 0 + beq fast2full_noncritical + + ## If the critical interrupt count is > 1, we are already in a + ## nested critical interrupt, so we're already on the critical stack + ## and there's nothing left to do. + + cmpwi %r9, 1 + bne 1f + + ## Otherwise, save the current stack pointer and switch to the critical + ## stack. + + _stwsd %r1, __ssx_saved_sp_critical + _lwzsd %r1, __ssx_critical_stack + + ## Restore the CR and return to the now full-mode handler. + +1: + mtcr %r12 + blr + + ## Non-critical interrupts are handled analogously to the above, + ## except that bits 8:15 of R7 are the non-critical + ## count. At entry here the (volatile - fast) context has been pushed, + ## R8 has USPRG0 and R12 contains the saved CR. + + ## Note that it would violate a kernel/API invariant if this routine + ## were entered from outside an interrupt context. + + .cache_align +fast2full_noncritical: + + extrwi %r9, %r8, 8, 8 + cmpwi %r9, 1 + bne 1f + + _stwsd %r1, __ssx_saved_sp_noncritical + _lwzsd %r1, __ssx_noncritical_stack + +1: + + .if (SSX_ERROR_CHECK_KERNEL | SSX_ERROR_CHECK_API) + cmpwi %r9, 0 + bne 2f + _ssx_panic PPC405_IRQ_FAST2FULL_INVARIANT +2: + .endif + + mtcr %r12 + blr + + + ############################################################ + # 0x0300 : Data Storage Interrupt + ############################################################ + + .org __vectors_0100 + 0x0200 +__data_storage: + + PPC405_DATA_STORAGE_HANDLER + + .org __data_storage + 0x20 + + .global __ssx_irq_full_mode_exit +__ssx_irq_full_mode_exit: + + ## Exit a full-mode handler. + + ## Entry invariants: + ## 1. The SP/stack must be in exactly the same state it was left in at + ## the exit of __ssx_irq_fast2full. + ## 2. It is assumed the the preemption rules of SSX have been followed + ## - in particular that critical handlers have not enabled + ## non-critical interrupts. + + ## We can freely modify the volatile context here - the handler is done + ## and we will restore the interrupted volatile context. + + ## 22 linear instructions + + ## If the critical count is non-zero, then the SSX preemption rules + ## guarantee that we are exiting from a critical interrupt + ## handler. This test is safe to make even if critical interrupts are + ## enabled, because the variable is set exactly once in a critical + ## section. + + mfusprg0 %r3 + extrwi. %r4, %r3, 8, 0 + beq full_exit_noncritical + + ## The context restore must be done from a critical section, in case + ## the handler enabled preemption. + + _ssx_critical_section_enter SSX_CRITICAL, %r5, %r6 + + ## If the critical count (R4) is > 1 then this is a nested interrupt + ## and we can simply pop the context and RFCI. + + cmpwi %r4, 1 + bne full_exit_critical + + ## Otherwise, restore the saved stack pointer before popping and RFCI. + + _lwzsd %r1, __ssx_saved_sp_critical + +full_exit_critical: + _ssx_vol_fast_ctx_pop SSX_IRQ_CONTEXT, SSX_CRITICAL + b fast_exit_critical + + + ############################################################ + # 0x0400 : Instruction Storage Interrupt + ############################################################ + + .org __vectors_0100 + 0x0300 +__instruction_storage: + + PPC405_INSTRUCTION_STORAGE_HANDLER + + .org __instruction_storage + 0x20 + + ## The idle thread has no permanent register context. The idle thread + ## entry point is re-entered whenever the idle thread is scheduled. + + .global __ssx_idle_thread + .global __ssx_idle_thread_from_bootloader + +__ssx_idle_thread: + + ## The idle thread 'uses' the non-critical stack. Any register context + ## pushed here is redundant and is wiped out/ignored every time the + ## idle thread is re-scheduled. + + ## The idle thread simply establishes a default machine context and + ## enters the wait-enable state. The idle thread is always entered + ## with non-critical interrupts disabled. + ## + ## The kernel context is initialized to indicate that the idle thread + ## is running - the idle thread priority is SSX_THREADS, and the + ## 'thread-mode' bit is asserted as well. + ## + ## This loop can also be called from the SSX bootloader if main() + ## returns - in which case we don't muck with the USPRG0 or the stack + ## pointer. + + li %r3, (SSX_THREADS | PPC405_THREAD_MODE) + mtusprg0 %r3 + _lwzsd %r1, __ssx_noncritical_stack + +__ssx_idle_thread_from_bootloader: + + li %r3, SSX_THREADS + SSX_TRACE_THREAD_SWITCH %r3, %r4 + _lwzsd %r3, __ssx_thread_machine_context_default + _oriwa %r3, %r3, MSR_WE + mtmsr %r3 + b . + + ## ssx_halt() is implemented on the PPC405 by disabling all + ## interrupts, forcing external debug mode, and executing a trap. A + ## 0x0 word appears after the trap instruction similar to the default + ## SSX_PANIC macro. The caller may also call ssx_halt() with + ## parameters which will appear in R3, R4, etc. In the Simics + ## environment we use the Simics 'trap' since Simics does not handle + ## the PPC405 TRAP instruction correctly. + + .global ssx_halt +ssx_halt: + li %r31, 0 + mtmsr %r31 + isync + _liwa %r31, (DBCR0_EDM | DBCR0_TDE) + mtdbcr0 %r31 + isync +#if SIMICS_ENVIRONMENT + rlwimi 1, 1, 0, 0, 0 +#else + trap +#endif + .long 0 + + ############################################################ + # 0x0500 : External Interrupt + ############################################################ + + .org __vectors_0100 + 0x0400 +__external_interrupt: + + ## The non-critical interrupt handler entry point is re-entrant - A + ## handler may allow preemption, which could cause another entry here. + + ## Entry invariants: + ## 1. Non-critical interupts are disabled; + ## 2. The SP points to a thread stack or the non-critical stack. + + ## Since fast-mode handlers can not use SSX services or alter the + ## machine context, the exit of a fast mode handler is a simple RF(C)I. + + ## Begin by pushing the fast context on the current stack. + + _ssx_fast_ctx_push SSX_NONCRITICAL + + ## Load noncritical status 0 and the handler array base address. Check + ## for interrupts pending in status register 0 while the IRQ is + ## computed and R5 is loaded with the noncritical flag. + + _lwzi %r3, %r3, OCB_ONISR0 + _liw %r6, __ppc405_irq_handlers + cmpwi %r3, 0 + cntlzw %r4, %r3 + li %r5, SSX_NONCRITICAL + bne+ noncritical_irq_found + + ## No IRQ pending in interrupt set 0. Try set 1. + + _lwzi %r3, %r3, OCB_ONISR1 + cmpwi %r3, 0 + cntlzw %r4, %r3 + addi %r4, %r4, 32 + beq- noncritical_phantom + + ## An active IRQ was found. At entry here R6 has the handler table + ## base address, R4 has the IRQ number, and R5 has the noncritical + ## flag. The IRQ is converted into a pointer to an 8-byte handler + ## structure, and the handler is dispatched. The call is made with the + ## parameters: + + ## R3 = private + ## R4 = irq + ## R5 = SSX_NONCRITICAL + +noncritical_irq_found: + + _save_update_kernel_context SSX_NONCRITICAL, %r4, %r7 + slwi %r3, %r4, 3 + lwzux %r7, %r6, %r3 + lwz %r3, 4(%r6) + mtlr %r7 + blrl + + ## Pop the stack/RFI when (if) it returns here. + +fast_exit_noncritical: + + _ssx_fast_ctx_pop_exit SSX_NONCRITICAL + + ## This is a phantom interrupt - we got interrupted but no status bits + ## are set. The interrupt is marked as #64. The register used for the + ## handler table address (R6) is set to the special structure for the + ## phantom interrupt, with it's address adjusted to make it appear to + ## be the 64th entry in the table. + +noncritical_phantom: + + _liw %r6, __ppc405_phantom_irq + subi %r6, %r6, (64 * 8) + b noncritical_irq_found + + ############################################################ + # 0x0600 : Alignment Exception + ############################################################ + + .org __vectors_0100 + 0x0500 +__alignment_exception: + + PPC405_ALIGNMENT_HANDLER + + .org __alignment_exception + 0x20 +pit_handler: + + ## The portable timer handler of SSX a full-mode handler with the prototype: + ## void (*ssx_timer_handler)(void). + ## + ## To support the portable specification, the kernel clears the + ## interrupt by writing the PIS back into the TSR before calling the + ## handler. SSX does not use the PIT in auto-reload mode - it is + ## tickless - so the interrupt will not fire again until reprogrammed + ## by the timer handler. The timer handler does not take any arguments. + + ## 21 instructions + + _ssx_fast_ctx_push SSX_NONCRITICAL + li %r3, PPC405_IRQ_PIT + _save_update_kernel_context SSX_NONCRITICAL, %r3, %r4 + + _liwa %r3, TSR_PIS + mttsr %r3 + isync + + _ssx_irq_fast2full __ssx_timer_handler + + + ############################################################ + # 0x0700 : Program Interrupt + ############################################################ + + .org __vectors_0100 + 0x0600 +__program_interrupt: + + PPC405_PROGRAM_HANDLER + + .org __program_interrupt + 0x20 + + ## Exiting a full-mode non-critical handler is more complex than the + ## critical case, because the handler may have made a new + ## highest-priority thread runnable and we may need to go through a + ## delayed scheduling step. + + ## Note that the idle thread is treated as a special case. The idle + ## thread has no permanent register context. To avoid having to + ## allocate a stack area for the idle thread, the idle thread + ## 'uses' the non-critical stack. When the idle thread is interrupted + ## the (redundant) context is pushed, but is then effectively lost. + ## Whenever we restore the idle thread we simply reenter the idle + ## thread entry point. + + ## At entry: + ## 1. R3 holds the value of USPRG0 (__SsxKernelContext) + + ## 33 linear instructions. + +full_exit_noncritical: + + ## Enter a critical section for the return from interrupt, in the event + ## that the handler enabled preemption. + + _ssx_critical_section_enter SSX_NONCRITICAL, %r4, %r5 + + ## If the non-critical count is > 1 then this is a nested interrupt + ## and we can simply pop the context and RFI. Note that it would + ## violate a kernel/API invariant if this routine were entered from + ## outside an interrupt context (interrupt level == 0). + + extrwi. %r4, %r3, 8, 8 + + .if (SSX_ERROR_CHECK_KERNEL | SSX_ERROR_CHECK_API) + bne 1f + _ssx_panic PPC405_IRQ_FULL_EXIT_INVARIANT +1: + .endif + + cmpwi %r4, 1 + bne exit_noncritical_without_switch + + ## Otherwise, restore the saved stack pointer and continue. + + _lwzsd %r1, __ssx_saved_sp_noncritical + + ## If we are not in thread mode (i.e., we took an interrupt in an + ## interupt-only configuration of SSX or after ssx_initialize() but + ## before ssx_start_threads) simply pop the context and RFI - in this + ## case we'll most likely be returning to main() or the non-thread-mode + ## idle thread. + + andi. %r4, %r3, PPC405_THREAD_MODE + beq exit_noncritical_without_switch + + ## Now, check for a delayed context switch. If none is pending, we can + ## exit (after a check for the idle thread special case). + + _lwzsd %r3, __ssx_delayed_switch + cmpwi %r3, 0 + bne noncritical_switch + + _lwzsd %r3, __ssx_current_thread + cmpwi %r3, 0 + beq __ssx_idle_thread + +exit_noncritical_without_switch: + _ssx_vol_fast_ctx_pop SSX_IRQ_CONTEXT, SSX_NONCRITICAL + b fast_exit_noncritical + + ## The non-critical interrupt activated a delayed context switch. The + ## C-level code has taken care of the scheduling decisions - we simply + ## need to implement them here. + +noncritical_switch: + + ## Clear the delayed switch flag and go to the context switch code to + ## finish the switch. + + li %r3, 0 + _stwsd %r3, __ssx_delayed_switch + + b thread_save_non_volatile_and_switch + + + ############################################################ + # 0x0800 : FPU Unavailable + ############################################################ + + .org __vectors_0100 + 0x0700 +__fpu_unavailable: + + PPC405_FPU_UNAVAILABLE_HANDLER + + .org __fpu_unavailable + 0x20 + + + ## Exit traces are moved here because the code area (0x100 bytes) + ## reserved for individual interrupts is overflowing when tracing is + ## enabled. This is kind of a hack: We know that this trace only + ## occurs when we're about to exit the fast context, at a place + ## where we can use any of the fast registers. + +__ssx_trace_critical_irq_exit: + SSX_TRACE_CRITICAL_IRQ_EXIT %r3, %r4 + blr + +__ssx_trace_noncritical_irq_exit: + SSX_TRACE_NONCRITICAL_IRQ_EXIT %r3, %r4 + blr + + ## >>>>>>>>>> Pack .vectors_0100 here. Room for ~900 bytes. <<<<<<<<<< + +### **************************************************************************** +### .vectors_0c00 +### **************************************************************************** + + .section .vectors_0c00, "ax", @progbits + .global __vectors_0c00 +__vectors_0c00: + + ############################################################ + # 0x0c00 : System Call + ############################################################ + + .org __vectors_0c00 + 0x0 + .global __ssx_next_thread_resume + +__system_call: + + ## The system call exception is used by SSX as a handy way to start a + ## context switch, as the continuation address and MSR of the thread to + ## be swapped out are saved in SRR0 and SRR1. + + ## Non-critical interrupts are disabled at entry. + + ## Note that the system call exception begins a large free area + ## so there is plenty of room for the context switch code. + + ## Begin by saving the volatile context of the current thread. + + _ssx_fast_ctx_push SSX_NONCRITICAL + _ssx_vol_fast_ctx_push SSX_THREAD_CONTEXT + +thread_save_non_volatile_and_switch: + + ## Finish the thread context save by pushing the non-volatile context + ## and saving the resulting stack pointer in the thread structure. If + ## the current thread is the idle thread this step is bypassed. + + ## This symbol is also used as an entry point by the non-critical + ## interrupt handler - non-critical interrupts are disabled here. + + _lwzsd %r3, __ssx_current_thread + cmpwi %r3, 0 + beq __ssx_next_thread_resume + + _ssx_non_vol_ctx_push + stw %r1, SSX_THREAD_OFFSET_SAVED_STACK_POINTER(%r3) + + ## The next thread becomes the current thread, and we switch to its + ## stack - unless the new thread is the idle thread, in which case it + ## (the idle thread) is simply resumed. + +__ssx_next_thread_resume: + + _lwzsd %r3, __ssx_next_thread + _stwsd %r3, __ssx_current_thread + + cmpwi %r3, 0 + beq __ssx_idle_thread + + lwz %r1, SSX_THREAD_OFFSET_SAVED_STACK_POINTER(%r3) + + ## Restore the thread context and resume the new thread. The kernel + ## context in thread mode is simply the thread priority OR'ed with the + ## thread-mode flag. All other fields are cleared. + + _ssx_non_vol_ctx_pop + _ssx_vol_fast_ctx_pop SSX_THREAD_CONTEXT, SSX_NONCRITICAL + + _lbzsd %r3, __ssx_next_priority + SSX_TRACE_THREAD_SWITCH %r3, %r4 + ori %r3, %r3, PPC405_THREAD_MODE + mtusprg0 %r3 + + _ssx_fast_ctx_pop + rfi + + ## >>>>>>>> Pack .vectors_0c00 here - room for ~500 bytes <<<<<<< + +### **************************************************************************** +### .vectors_0f00 +### **************************************************************************** + + .section .vectors_0f00, "ax", @progbits + .global __vectors_0f00 +__vectors_0f00: + + ############################################################ + # 0x0f20 : APU Unavailable + ############################################################ + + .org __vectors_0f00 + 0x20 # 0x0f20 +__apu_unavailable: + + PPC405_APU_UNAVAILABLE_HANDLER + + .org __vectors_0f00 + 0x40 # 0x0f40 + +fit_handler: + + ## The FIT handler is user defined, and is a fast-mode handler. By + ## convention the kernel clears the interrupt by writing the FIS back + ## into the TSR. + + _ssx_fast_ctx_push SSX_NONCRITICAL + + _lwzsd %r3, __ppc405_fit_arg + li %r4, PPC405_IRQ_FIT + li %r5, SSX_NONCRITICAL + + _save_update_kernel_context SSX_NONCRITICAL, %r4, %r6 + + _liwa %r6, TSR_FIS + mttsr %r6 + isync + + _lwzsd %r6, __ppc405_fit_routine + mtlr %r6 + blrl + + b fast_exit_noncritical + + + ############################################################ + # 0x10x0 : PIT, FIT and Watchdog Interrupts + ############################################################ + + .org __vectors_0f00 + 0x100 # 0x1000 +__pit_interrupt: + + b pit_handler + + .org __vectors_0f00 + 0x110 # 0x1010 +__fit_interrupt: + + b fit_handler + + .org __vectors_0f00 + 0x120 # 0x1020 +__watchdog_interrupt: + + ## Watchdog setup is described in the SSX Specification. + ## The kernel clears TSR[WIS] prior to calling the handler. + ## The watchdog handler is a critical, fast-mode handler. + + _ssx_fast_ctx_push SSX_CRITICAL + + _lwzsd %r3, __ppc405_watchdog_arg + li %r4, PPC405_IRQ_WATCHDOG + li %r5, SSX_CRITICAL + + _save_update_kernel_context SSX_CRITICAL, %r4, %r6 + + _liwa %r6, TSR_WIS + mttsr %r6 + isync + + _lwzsd %r6, __ppc405_watchdog_routine + mtlr %r6 + blrl + + b fast_exit_critical + + + ############################################################ + # 0x1100 : Data TLB Miss + ############################################################ + + .org __vectors_0f00 + 0x200 # 0x1100 +__data_tlb_miss: + + PPC405_DATA_TLB_MISS_HANDLER + + .org __data_tlb_miss + 0x20 +debug_handler: + + ## SSX does nothing upon reception of the debug interrupt other + ## than calling the handler (if non-0). The debug handler is a + ## fast-mode handler. + + _ssx_fast_ctx_push SSX_CRITICAL + + _lwzsd %r3, __ppc405_debug_arg + li %r4, PPC405_IRQ_DEBUG + li %r5, SSX_CRITICAL + + _save_update_kernel_context SSX_CRITICAL, %r4, %r6 + + _lwzsd %r6, __ppc405_debug_routine + cmpwi %r6, 0 + mtlr %r6 + beq debug_exit + blrl + +debug_exit: + b fast_exit_critical + + + ############################################################ + # 0x1200 : Instruction TLB Miss + ############################################################ + + .org __vectors_0f00 + 0x300 # 0x1200 +__instruction_tlb_miss: + + PPC405_INSTRUCTION_TLB_MISS_HANDLER + + .org __instruction_tlb_miss + 0x20 + + ## >>>>>> Pack .vectors_0f00 A huge hole here - ~3.5KB <<<<<< + +### **************************************************************************** +### .vectors_2000 +### **************************************************************************** + + .section .vectors_2000, "ax", @progbits + + .global __vectors_2000 +__vectors_2000: + + ############################################################ + # 0x2000 : Debug Interrupt + ############################################################ + +__debug_interrupt: + b debug_handler + +/// \endcond |