void _CPU_Exception_frame_print( const CPU_Exception_frame *frame ) { uint32_t trap; uint32_t real_trap; const CPU_Interrupt_frame *isf; trap = frame->trap; real_trap = SPARC_REAL_TRAP_NUMBER(trap); isf = frame->isf; printk( "Unexpected trap (%2d) at address 0x%08x\n", real_trap, isf->tpc); switch (real_trap) { /* * First the ones defined by the basic architecture */ case 0x00: printk( "reset\n" ); break; case 0x01: printk( "instruction access exception\n" ); break; case 0x02: printk( "illegal instruction\n" ); break; case 0x03: printk( "privileged instruction\n" ); break; case 0x04: printk( "fp disabled\n" ); break; case 0x07: printk( "memory address not aligned\n" ); break; case 0x08: printk( "fp exception\n" ); break; case 0x09: printk("data access exception at 0x%08x\n", ERC32_MEC.First_Failing_Address ); break; case 0x0A: printk( "tag overflow\n" ); break; /* * Then the ones defined by the ERC32 in particular */ case ERC32_TRAP_TYPE( ERC32_INTERRUPT_MASKED_ERRORS ): printk( "ERC32_INTERRUPT_MASKED_ERRORS\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_1 ): printk( "ERC32_INTERRUPT_EXTERNAL_1\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_2 ): printk( "ERC32_INTERRUPT_EXTERNAL_2\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_A_RX_TX ): printk( "ERC32_INTERRUPT_UART_A_RX_TX\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_B_RX_TX ): printk( "ERC32_INTERRUPT_UART_A_RX_TX\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_CORRECTABLE_MEMORY_ERROR ): printk( "ERC32_INTERRUPT_CORRECTABLE_MEMORY_ERROR\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_ERROR ): printk( "ERC32_INTERRUPT_UART_ERROR\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_DMA_ACCESS_ERROR ): printk( "ERC32_INTERRUPT_DMA_ACCESS_ERROR\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_DMA_TIMEOUT ): printk( "ERC32_INTERRUPT_DMA_TIMEOUT\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_3 ): printk( "ERC32_INTERRUPT_EXTERNAL_3\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_4 ): printk( "ERC32_INTERRUPT_EXTERNAL_4\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER ): printk( "ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_REAL_TIME_CLOCK ): printk( "ERC32_INTERRUPT_REAL_TIME_CLOCK\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_5 ): printk( "ERC32_INTERRUPT_EXTERNAL_5\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_WATCHDOG_TIMEOUT ): printk( "ERC32_INTERRUPT_WATCHDOG_TIMEOUT\n" ); break; default: break; } }
void _CPU_ISR_install_raw_handler( uint32_t vector, proc_ptr new_handler, proc_ptr *old_handler ) { uint32_t real_vector; CPU_Trap_table_entry *tbr; CPU_Trap_table_entry *slot; uint32_t u32_tbr; uint32_t u32_handler; /* * Get the "real" trap number for this vector ignoring the synchronous * versus asynchronous indicator included with our vector numbers. */ real_vector = SPARC_REAL_TRAP_NUMBER( vector ); /* * Get the current base address of the trap table and calculate a pointer * to the slot we are interested in. */ sparc_get_tbr( u32_tbr ); u32_tbr &= 0xfffff000; tbr = (CPU_Trap_table_entry *) u32_tbr; slot = &tbr[ real_vector ]; /* * Get the address of the old_handler from the trap table. * * NOTE: The old_handler returned will be bogus if it does not follow * the RTEMS model. */ #define HIGH_BITS_MASK 0xFFFFFC00 #define HIGH_BITS_SHIFT 10 #define LOW_BITS_MASK 0x000003FF if ( slot->mov_psr_l0 == _CPU_Trap_slot_template.mov_psr_l0 ) { u32_handler = (slot->sethi_of_handler_to_l4 << HIGH_BITS_SHIFT) | (slot->jmp_to_low_of_handler_plus_l4 & LOW_BITS_MASK); *old_handler = (proc_ptr) u32_handler; } else *old_handler = 0; /* * Copy the template to the slot and then fix it. */ *slot = _CPU_Trap_slot_template; u32_handler = (uint32_t) new_handler; slot->mov_vector_l3 |= vector; slot->sethi_of_handler_to_l4 |= (u32_handler & HIGH_BITS_MASK) >> HIGH_BITS_SHIFT; slot->jmp_to_low_of_handler_plus_l4 |= (u32_handler & LOW_BITS_MASK); /* * There is no instruction cache snooping, so we need to invalidate * the instruction cache to make sure that the processor sees the * changes to the trap table. This step is required on both single- * and multiprocessor systems. * * In a SMP configuration a change to the trap table might be * missed by other cores. If the system state is up, the other * cores can be notified using SMP messages that they need to * flush their icache. If the up state has not been reached * there is no need to notify other cores. They will do an * automatic flush of the icache just after entering the up * state, but before enabling interrupts. */ rtems_cache_invalidate_entire_instruction(); }
rtems_isr bsp_spurious_handler( rtems_vector_number trap, CPU_Interrupt_frame *isf ) { uint32_t real_trap; real_trap = SPARC_REAL_TRAP_NUMBER(trap); printk( "Unexpected trap (%2d) at address 0x%08x\n", real_trap, isf->tpc); switch (real_trap) { /* * First the ones defined by the basic architecture */ case 0x00: printk( "reset\n" ); break; case 0x01: printk( "instruction access exception\n" ); break; case 0x02: printk( "illegal instruction\n" ); break; case 0x03: printk( "privileged instruction\n" ); break; case 0x04: printk( "fp disabled\n" ); break; case 0x07: printk( "memory address not aligned\n" ); break; case 0x08: printk( "fp exception\n" ); break; case 0x09: printk("data access exception at 0x%08x\n", ERC32_MEC.First_Failing_Address ); break; case 0x0A: printk( "tag overflow\n" ); break; /* * Then the ones defined by the ERC32 in particular */ case ERC32_TRAP_TYPE( ERC32_INTERRUPT_MASKED_ERRORS ): printk( "ERC32_INTERRUPT_MASKED_ERRORS\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_1 ): printk( "ERC32_INTERRUPT_EXTERNAL_1\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_2 ): printk( "ERC32_INTERRUPT_EXTERNAL_2\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_A_RX_TX ): printk( "ERC32_INTERRUPT_UART_A_RX_TX\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_B_RX_TX ): printk( "ERC32_INTERRUPT_UART_A_RX_TX\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_CORRECTABLE_MEMORY_ERROR ): printk( "ERC32_INTERRUPT_CORRECTABLE_MEMORY_ERROR\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_UART_ERROR ): printk( "ERC32_INTERRUPT_UART_ERROR\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_DMA_ACCESS_ERROR ): printk( "ERC32_INTERRUPT_DMA_ACCESS_ERROR\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_DMA_TIMEOUT ): printk( "ERC32_INTERRUPT_DMA_TIMEOUT\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_3 ): printk( "ERC32_INTERRUPT_EXTERNAL_3\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_4 ): printk( "ERC32_INTERRUPT_EXTERNAL_4\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER ): printk( "ERC32_INTERRUPT_GENERAL_PURPOSE_TIMER\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_REAL_TIME_CLOCK ): printk( "ERC32_INTERRUPT_REAL_TIME_CLOCK\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_EXTERNAL_5 ): printk( "ERC32_INTERRUPT_EXTERNAL_5\n" ); break; case ERC32_TRAP_TYPE( ERC32_INTERRUPT_WATCHDOG_TIMEOUT ): printk( "ERC32_INTERRUPT_WATCHDOG_TIMEOUT\n" ); break; default: break; } /* * What else can we do but stop ... */ asm volatile( "mov 1, %g1; ta 0x0" ); }
/* Verified this is working properly from sparc64_install_isr_entries */ void _CPU_ISR_install_raw_handler( uint32_t vector, proc_ptr new_handler, proc_ptr *old_handler ) { uint32_t real_vector; CPU_Trap_table_entry *tba; CPU_Trap_table_entry *slot; uint64_t u64_tba; uint64_t u64_handler; /* * Get the "real" trap number for this vector ignoring the synchronous * versus asynchronous indicator included with our vector numbers. */ real_vector = SPARC_REAL_TRAP_NUMBER( vector ); /* * Get the current base address of the trap table and calculate a pointer * to the slot we are interested in. */ sparc64_get_tba( u64_tba ); /* u32_tbr &= 0xfffff000; */ u64_tba &= 0xffffffffffff8000; /* keep only trap base address */ tba = (CPU_Trap_table_entry *) u64_tba; /* use array indexing to fill in lower bits -- require * CPU_Trap_table_entry to be full-sized. */ slot = &tba[ real_vector ]; /* * Get the address of the old_handler from the trap table. * * NOTE: The old_handler returned will be bogus if it does not follow * the RTEMS model. */ /* shift amount to shift of hi bits (31:10) */ #define HI_BITS_SHIFT 10 /* shift amount of hm bits (41:32) */ #define HM_BITS_SHIFT 32 /* shift amount of hh bits (63:42) */ #define HH_BITS_SHIFT 42 /* We're only interested in bits 0-9 of the immediate field*/ #define IMM_MASK 0x000003FF if ( slot->rdpr_tstate_g4 == _CPU_Trap_slot_template.rdpr_tstate_g4 ) { u64_handler = (((uint64_t)((slot->sethi_of_hh_handler_to_g2 << HI_BITS_SHIFT) | (slot->or_g2_hm_handler_to_g2 & IMM_MASK))) << HM_BITS_SHIFT) | ((slot->sethi_of_handler_to_g3 << HI_BITS_SHIFT) | (slot->jmp_to_low_of_handler_plus_g3 & IMM_MASK)); *old_handler = (proc_ptr) u64_handler; } else *old_handler = 0; /* * Copy the template to the slot and then fix it. */ *slot = _CPU_Trap_slot_template; u64_handler = (uint64_t) new_handler; /* mask for extracting %hh */ #define HH_BITS_MASK 0xFFFFFC0000000000 /* mask for extracting %hm */ #define HM_BITS_MASK 0x000003FF00000000 /* mask for extracting %hi */ #define HI_BITS_MASK 0x00000000FFFFFC00 /* mask for extracting %lo */ #define LO_BITS_MASK 0x00000000000003FF slot->mov_vector_g2 |= vector; slot->sethi_of_hh_handler_to_g2 |= (u64_handler & HH_BITS_MASK) >> HH_BITS_SHIFT; slot->or_g2_hm_handler_to_g2 |= (u64_handler & HM_BITS_MASK) >> HM_BITS_SHIFT; slot->sethi_of_handler_to_g3 |= (u64_handler & HI_BITS_MASK) >> HI_BITS_SHIFT; slot->jmp_to_low_of_handler_plus_g3 |= (u64_handler & LO_BITS_MASK); /* need to flush icache after this !!! */ /* need to flush icache in case old trap handler is in cache */ rtems_cache_invalidate_entire_instruction(); }
void _BSP_Exception_frame_print( const CPU_Exception_frame *frame ) { uint32_t trap; uint32_t real_trap; const CPU_Interrupt_frame *isf; trap = frame->trap; real_trap = SPARC_REAL_TRAP_NUMBER(trap); isf = frame->isf; printk( "Unexpected trap (%2d) at address 0x%08x\n", real_trap, isf->tpc); switch (real_trap) { /* * First the ones defined by the basic architecture */ case 0x00: printk( "reset\n" ); break; case 0x01: printk( "instruction access exception\n" ); break; case 0x02: printk( "illegal instruction\n" ); break; case 0x03: printk( "privileged instruction\n" ); break; case 0x04: printk( "fp disabled\n" ); break; case 0x07: printk( "memory address not aligned\n" ); break; case 0x08: printk( "fp exception\n" ); break; case 0x09: printk("data access exception at 0x%08x\n", LEON_REG.Failed_Address ); break; case 0x0A: printk( "tag overflow\n" ); break; /* * Then the ones defined by the LEON in particular */ case LEON_TRAP_TYPE( LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR ): printk( "LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_UART_2_RX_TX ): printk( "LEON_INTERRUPT_UART_2_RX_TX\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_UART_1_RX_TX ): printk( "LEON_INTERRUPT_UART_1_RX_TX\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_0 ): printk( "LEON_INTERRUPT_EXTERNAL_0\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_1 ): printk( "LEON_INTERRUPT_EXTERNAL_1\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_2 ): printk( "LEON_INTERRUPT_EXTERNAL_2\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_3 ): printk( "LEON_INTERRUPT_EXTERNAL_3\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_TIMER1 ): printk( "LEON_INTERRUPT_TIMER1\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_TIMER2 ): printk( "LEON_INTERRUPT_TIMER2\n" ); break; default: break; } }
void _CPU_ISR_install_raw_handler( uint32_t vector, proc_ptr new_handler, proc_ptr *old_handler ) { uint32_t real_vector; CPU_Trap_table_entry *tbr; CPU_Trap_table_entry *slot; uint32_t u32_tbr; uint32_t u32_handler; /* * Get the "real" trap number for this vector ignoring the synchronous * versus asynchronous indicator included with our vector numbers. */ real_vector = SPARC_REAL_TRAP_NUMBER( vector ); /* * Get the current base address of the trap table and calculate a pointer * to the slot we are interested in. */ sparc_get_tbr( u32_tbr ); u32_tbr &= 0xfffff000; tbr = (CPU_Trap_table_entry *) u32_tbr; slot = &tbr[ real_vector ]; /* * Get the address of the old_handler from the trap table. * * NOTE: The old_handler returned will be bogus if it does not follow * the RTEMS model. */ #define HIGH_BITS_MASK 0xFFFFFC00 #define HIGH_BITS_SHIFT 10 #define LOW_BITS_MASK 0x000003FF if ( slot->mov_psr_l0 == _CPU_Trap_slot_template.mov_psr_l0 ) { u32_handler = (slot->sethi_of_handler_to_l4 << HIGH_BITS_SHIFT) | (slot->jmp_to_low_of_handler_plus_l4 & LOW_BITS_MASK); *old_handler = (proc_ptr) u32_handler; } else *old_handler = 0; /* * Copy the template to the slot and then fix it. */ *slot = _CPU_Trap_slot_template; u32_handler = (uint32_t) new_handler; slot->mov_vector_l3 |= vector; slot->sethi_of_handler_to_l4 |= (u32_handler & HIGH_BITS_MASK) >> HIGH_BITS_SHIFT; slot->jmp_to_low_of_handler_plus_l4 |= (u32_handler & LOW_BITS_MASK); /* need to flush icache after this !!! */ rtems_cache_invalidate_entire_instruction(); }
rtems_isr bsp_spurious_handler( rtems_vector_number trap, CPU_Interrupt_frame *isf ) { uint32_t real_trap; real_trap = SPARC_REAL_TRAP_NUMBER(trap); printk( "Unexpected trap (%2d) at address 0x%08x\n", real_trap, isf->tpc); switch (real_trap) { /* * First the ones defined by the basic architecture */ case 0x00: printk( "reset\n" ); break; case 0x01: printk( "instruction access exception\n" ); break; case 0x02: printk( "illegal instruction\n" ); break; case 0x03: printk( "privileged instruction\n" ); break; case 0x04: printk( "fp disabled\n" ); break; case 0x07: printk( "memory address not aligned\n" ); break; case 0x08: printk( "fp exception\n" ); break; case 0x09: printk("data access exception at 0x%08x\n", LEON_REG.Failed_Address ); break; case 0x0A: printk( "tag overflow\n" ); break; /* * Then the ones defined by the LEON in particular */ case LEON_TRAP_TYPE( LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR ): printk( "LEON_INTERRUPT_CORRECTABLE_MEMORY_ERROR\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_UART_2_RX_TX ): printk( "LEON_INTERRUPT_UART_2_RX_TX\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_UART_1_RX_TX ): printk( "LEON_INTERRUPT_UART_1_RX_TX\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_0 ): printk( "LEON_INTERRUPT_EXTERNAL_0\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_1 ): printk( "LEON_INTERRUPT_EXTERNAL_1\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_2 ): printk( "LEON_INTERRUPT_EXTERNAL_2\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_EXTERNAL_3 ): printk( "LEON_INTERRUPT_EXTERNAL_3\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_TIMER1 ): printk( "LEON_INTERRUPT_TIMER1\n" ); break; case LEON_TRAP_TYPE( LEON_INTERRUPT_TIMER2 ): printk( "LEON_INTERRUPT_TIMER2\n" ); break; default: break; } /* * What else can we do but stop ... */ __asm__ volatile( "mov 1, %g1; ta 0x0" ); }