diff options
-rw-r--r-- | c/src/exec/score/cpu/hppa1.1/cpu.c | 336 | ||||
-rw-r--r-- | c/src/exec/score/cpu/hppa1.1/cpu.h | 32 | ||||
-rw-r--r-- | c/src/exec/score/cpu/hppa1.1/cpu_asm.s | 178 | ||||
-rw-r--r-- | c/src/exec/score/cpu/hppa1.1/hppa.h | 3 | ||||
-rw-r--r-- | cpukit/score/cpu/hppa1.1/cpu.c | 336 |
5 files changed, 209 insertions, 676 deletions
diff --git a/c/src/exec/score/cpu/hppa1.1/cpu.c b/c/src/exec/score/cpu/hppa1.1/cpu.c index 48e09b908a..89bb8a8447 100644 --- a/c/src/exec/score/cpu/hppa1.1/cpu.c +++ b/c/src/exec/score/cpu/hppa1.1/cpu.c @@ -19,117 +19,52 @@ #include <rtems/system.h> #include <rtems/score/isr.h> +void hppa_cpu_halt(unsigned32 the_error); -void hppa_external_interrupt_initialize(void); -void hppa_external_interrupt_enable(unsigned32); -void hppa_external_interrupt_disable(unsigned32); -void hppa_external_interrupt(unsigned32, CPU_Interrupt_frame *); -void hppa_cpu_halt(unsigned32); -/* - * The first level interrupt handler for first 32 interrupts/traps. - * Indexed by vector; generally each entry is _Generic_ISR_Handler. - * Some TLB traps may have their own first level handler. - */ - -extern void _Generic_ISR_Handler(void); -unsigned32 HPPA_first_level_interrupt_handler[HPPA_INTERNAL_INTERRUPTS]; - -/* _CPU_Initialize - * - * This routine performs processor dependent initialization. - * - * INPUT PARAMETERS: - * cpu_table - CPU table to initialize - * thread_dispatch - address of disptaching routine +/*PAGE * + * _CPU_ISR_install_raw_handler */ - -void _CPU_Initialize( - rtems_cpu_table *cpu_table, - void (*thread_dispatch) /* ignored on this CPU */ + +void _CPU_ISR_install_raw_handler( + unsigned32 vector, + proc_ptr new_handler, + proc_ptr *old_handler ) { - register unsigned8 *fp_context; - unsigned32 iva; - unsigned32 iva_table; - int i; - - extern void IVA_Table(void); - - /* - * XXX; need to setup fpsr smarter perhaps - */ - - fp_context = (unsigned8*) &_CPU_Null_fp_context; - for (i=0 ; i<sizeof(Context_Control_fp); i++) - *fp_context++ = 0; - - /* - * Set _CPU_Default_gr27 here so it will hopefully be the correct - * global data pointer for the entire system. - */ - - asm volatile( "stw %%r27,%0" : "=m" (_CPU_Default_gr27): ); - - /* - * Init the first level interrupt handlers - */ - - for (i=0; i <= HPPA_INTERNAL_INTERRUPTS; i++) - HPPA_first_level_interrupt_handler[i] = (unsigned32) _Generic_ISR_Handler; + /* + * This is unsupported. For HPPA this function is handled by BSP + */ - /* - * Init the 2nd level interrupt handlers - */ + _CPU_Fatal_halt( 0xdeaddead ); +} - for (i=0; i <= CPU_INTERRUPT_NUMBER_OF_VECTORS; i++) - _ISR_Vector_table[i] = (ISR_Handler_entry) hppa_cpu_halt; - /* - * Stabilize the interrupt stuff - */ - (void) hppa_external_interrupt_initialize(); +/* + * This is the default handler which is called if + * _CPU_ISR_install_vector() has not been called for the + * specified vector. It simply forwards onto the spurious + * handler defined in the cpu-table. + */ - /* - * Set the IVA to point to physical address of the IVA_Table - */ +static ISR_Handler +hppa_interrupt_report_spurious(ISR_Vector_number vector, + void* rtems_isr_frame) /* HPPA extension */ +{ - iva_table = (unsigned32) IVA_Table; -#if defined(hppa1_1) /* - * HACK: (from PA72000 TRM, page 4-19) - * "The hardware TLB miss handler will never attempt to service - * a non-access TLB miss or a TLB protection violation. It - * will only attempt to service TLB accesses that would cause - * Trap Numbers 6 (Instruction TLB miss) and 15 (Data TLB miss)." - * - * The LPA instruction is used to translate a virtual address to - * a physical address, however, if the requested virtual address - * is not currently resident in the TLB, the hardware TLB miss - * handler will NOT insert it. In this situation Trap Number - * #17 is invoked (Non-access Data TLB miss fault). - * - * To work around this, a dummy data access is first performed - * to the virtual address prior to the LPA. The dummy access - * causes the TLB entry to be inserted (if not already present) - * and then the following LPA instruction will not generate - * a non-access data TLB miss fault. - * - * It is unclear whether or not this behaves the same way for - * the PA8000. - * + * If the CPU table defines a spurious_handler, then + * call it. If the handler returns halt. */ - iva = *(volatile unsigned32 *)iva_table; /* dummy access */ -#endif - - HPPA_ASM_LPA(0, iva_table, iva); - set_iva(iva); - - _CPU_Table = *cpu_table; + if ( _CPU_Table.spurious_handler ) + _CPU_Table.spurious_handler(vector, rtems_isr_frame); + + hppa_cpu_halt(vector); } + /*PAGE * * _CPU_ISR_Get_level @@ -146,28 +81,10 @@ unsigned32 _CPU_ISR_Get_level(void) /*PAGE * - * _CPU_ISR_install_raw_handler - */ - -void _CPU_ISR_install_raw_handler( - unsigned32 vector, - proc_ptr new_handler, - proc_ptr *old_handler -) -{ - /* - * This is unsupported. - */ - - _CPU_Fatal_halt( 0xdeaddead ); -} - -/*PAGE - * * _CPU_ISR_install_vector * * This kernel routine installs the RTEMS handler for the - * specified vector. + * specified vector. The handler is a C callable routine. * * Input parameters: * vector - interrupt vector number @@ -178,12 +95,6 @@ void _CPU_ISR_install_raw_handler( * */ -/* - * HPPA has 8w for each vector instead of an address to jump to. - * We put the actual ISR address in '_ISR_vector_table'. This will - * be pulled by the code in the vector. - */ - void _CPU_ISR_install_vector( unsigned32 vector, proc_ptr new_handler, @@ -193,166 +104,74 @@ void _CPU_ISR_install_vector( *old_handler = _ISR_Vector_table[vector]; _ISR_Vector_table[vector] = new_handler; - - if (vector >= HPPA_INTERRUPT_EXTERNAL_BASE) - { - unsigned32 external_vector; - - external_vector = vector - HPPA_INTERRUPT_EXTERNAL_BASE; - if (new_handler) - hppa_external_interrupt_enable(external_vector); - else - /* XXX this can never happen due to _ISR_Is_valid_user_handler */ - hppa_external_interrupt_disable(external_vector); - } } - -/* - * Support for external and spurious interrupts on HPPA +/* _CPU_Initialize + * + * This routine performs processor dependent initialization. + * + * INPUT PARAMETERS: + * cpu_table - CPU table to initialize + * thread_dispatch - address of disptaching routine * - * TODO: - * Count interrupts - * make sure interrupts disabled properly - */ - -#define DISMISS(mask) set_eirr(mask) -#define DISABLE(mask) set_eiem(get_eiem() & ~(mask)) -#define ENABLE(mask) set_eiem(get_eiem() | (mask)) -#define VECTOR_TO_MASK(v) (1 << (31 - (v))) - -/* - * Init the external interrupt scheme - * called by bsp_start() */ -void -hppa_external_interrupt_initialize(void) +void _CPU_Initialize( + rtems_cpu_table *cpu_table, + void (*thread_dispatch) /* ignored on this CPU */ +) { - proc_ptr ignore; - - /* mark them all unused */ - DISABLE(~0); - DISMISS(~0); - - /* install the external interrupt handler */ - _CPU_ISR_install_vector( - HPPA_INTERRUPT_EXTERNAL_INTERRUPT, - (proc_ptr)hppa_external_interrupt, &ignore -); -} - -/* - * Enable a specific external interrupt - */ + register unsigned8 *fp_context; + int i; + proc_ptr old_handler; -void -hppa_external_interrupt_enable(unsigned32 v) -{ - unsigned32 isrlevel; + /* + * XXX; need to setup fpsr smarter perhaps + */ - _CPU_ISR_Disable(isrlevel); - ENABLE(VECTOR_TO_MASK(v)); - _CPU_ISR_Enable(isrlevel); -} + fp_context = (unsigned8*) &_CPU_Null_fp_context; + for (i=0 ; i<sizeof(Context_Control_fp); i++) + *fp_context++ = 0; -/* - * Does not clear or otherwise affect any pending requests - */ + /* + * Set _CPU_Default_gr27 here so it will hopefully be the correct + * global data pointer for the entire system. + */ -void -hppa_external_interrupt_disable(unsigned32 v) -{ - unsigned32 isrlevel; + asm volatile( "stw %%r27,%0" : "=m" (_CPU_Default_gr27): ); - _CPU_ISR_Disable(isrlevel); - DISABLE(VECTOR_TO_MASK(v)); - _CPU_ISR_Enable(isrlevel); -} + /* + * Init the 2nd level interrupt handlers + */ -void -hppa_external_interrupt_spurious_handler(unsigned32 vector, - CPU_Interrupt_frame *iframe) -{ -/* XXX should not be printing :) - printf("spurious external interrupt: %d at pc 0x%x; disabling\n", - vector, iframe->Interrupt.pcoqfront); -*/ -} + for (i=0; i < CPU_INTERRUPT_NUMBER_OF_VECTORS; i++) + _CPU_ISR_install_vector(i, + hppa_interrupt_report_spurious, + &old_handler); -void -hppa_external_interrupt_report_spurious(unsigned32 spurious_mask, - CPU_Interrupt_frame *iframe) -{ - int v; - for (v=0; v < HPPA_EXTERNAL_INTERRUPTS; v++) - if (VECTOR_TO_MASK(v) & spurious_mask) - { - DISMISS(VECTOR_TO_MASK(v)); - DISABLE(VECTOR_TO_MASK(v)); - hppa_external_interrupt_spurious_handler(v, iframe); - } - DISMISS(spurious_mask); + _CPU_Table = *cpu_table; + } /* - * External interrupt handler. - * This is installed as cpu interrupt handler for - * HPPA_INTERRUPT_EXTERNAL_INTERRUPT. It vectors out to - * specific external interrupt handlers. - */ - -void -hppa_external_interrupt(unsigned32 vector, - CPU_Interrupt_frame *iframe) -{ - unsigned32 mask; - unsigned32 *vp, *max_vp; - unsigned32 external_vector; - unsigned32 global_vector; - hppa_rtems_isr_entry handler; - - max_vp = &_CPU_Table.external_interrupt[_CPU_Table.external_interrupts]; - while ( (mask = (get_eirr() & get_eiem())) ) - { - for (vp = _CPU_Table.external_interrupt; (vp < max_vp) && mask; vp++) - { - unsigned32 m; - - external_vector = *vp; - global_vector = external_vector + HPPA_INTERRUPT_EXTERNAL_BASE; - m = VECTOR_TO_MASK(external_vector); - handler = (hppa_rtems_isr_entry) _ISR_Vector_table[global_vector]; - if ((m & mask) && handler) - { - DISMISS(m); - mask &= ~m; - handler(global_vector, iframe); - } - } - - if (mask != 0) { - if ( _CPU_Table.spurious_handler ) - { - handler = (hppa_rtems_isr_entry) _CPU_Table.spurious_handler; - handler(mask, iframe); - } - else - hppa_external_interrupt_report_spurious(mask, iframe); - } - } -} - -/* * Halt the system. * Called by the _CPU_Fatal_halt macro * * XXX * Later on, this will allow us to return to the prom. * For now, we just ignore 'type_of_halt' + * + * XXX + * NOTE: for gcc, this function must be at the bottom + * of the file, that is because if it is at the top + * of the file, gcc will inline it's calls. Since + * the function uses the HPPA_ASM_LABEL() macro, when + * gcc inlines it, you get two definitions of the same + * label name, which is an assembly error. */ + void hppa_cpu_halt(unsigned32 the_error) { @@ -360,6 +179,11 @@ hppa_cpu_halt(unsigned32 the_error) _CPU_ISR_Disable(isrlevel); + /* + * XXXXX NOTE: This label is only needed that that when + * the simulator stops, it shows the label name specified + */ HPPA_ASM_LABEL("_hppa_cpu_halt"); - HPPA_ASM_BREAK(1, 0); + HPPA_ASM_BREAK(0, 0); } + diff --git a/c/src/exec/score/cpu/hppa1.1/cpu.h b/c/src/exec/score/cpu/hppa1.1/cpu.h index 8c468ff59b..eca314f7af 100644 --- a/c/src/exec/score/cpu/hppa1.1/cpu.h +++ b/c/src/exec/score/cpu/hppa1.1/cpu.h @@ -216,26 +216,12 @@ typedef struct { void (*predriver_hook)( void ); void (*postdriver_hook)( void ); void (*idle_task)( void ); - - /* HPPA simulator is slow enough; don't waste time - * zeroing memory that is already zero - */ boolean do_zero_of_workspace; - unsigned32 interrupt_stack_size; unsigned32 extra_mpci_receive_server_stack; - - /* - * Control of external interrupts. - * We keep a table of external vector numbers (0 - 31) - * The table is sorted by priority, that is: the first entry - * in the table indicates the vector that is highest priorty. - * The handler function is stored in _ISR_Vector_Table[] and - * is set by rtems_interrupt_catch() - */ - - unsigned32 external_interrupts; /* # of external interrupts we use */ - unsigned32 external_interrupt[HPPA_EXTERNAL_INTERRUPTS]; + void * (*stack_allocate_hook)( unsigned32 ); + void (*stack_free_hook)( void * ); + /* end of fields required on all CPUs */ hppa_rtems_isr_entry spurious_handler; @@ -249,9 +235,6 @@ EXTERN unsigned32 _CPU_Default_gr27; EXTERN void *_CPU_Interrupt_stack_low; EXTERN void *_CPU_Interrupt_stack_high; -/* entry points */ -void hppa_external_interrupt_spurious_handler(unsigned32, CPU_Interrupt_frame *); - #endif /* ! ASM */ /* @@ -285,15 +268,12 @@ void hppa_external_interrupt_spurious_handler(unsigned32, CPU_Interrupt_frame *) /* * HPPA has 32 interrupts, then 32 external interrupts - * Rtems (_ISR_Vector_Table) is aware of the first 64 - * A BSP may reserve more. + * Rtems (_ISR_Vector_Table) is aware ONLY of the first 32 + * The BSP is aware of the external interrupts and possibly more. * - * External interrupts all come thru the same vector (4) - * The external handler is the only person aware of the other - * interrupts (genie, rhino, etc) */ -#define CPU_INTERRUPT_NUMBER_OF_VECTORS (HPPA_INTERRUPT_MAX) +#define CPU_INTERRUPT_NUMBER_OF_VECTORS (HPPA_INTERNAL_INTERRUPTS) #define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1) /* diff --git a/c/src/exec/score/cpu/hppa1.1/cpu_asm.s b/c/src/exec/score/cpu/hppa1.1/cpu_asm.s index 36650e7733..12814eda6e 100644 --- a/c/src/exec/score/cpu/hppa1.1/cpu_asm.s +++ b/c/src/exec/score/cpu/hppa1.1/cpu_asm.s @@ -1,5 +1,3 @@ -# @(#)cpu_asm.S 1.7 - 95/09/21 -# # # TODO: # Context_switch needs to only save callee save registers @@ -30,7 +28,6 @@ #include <rtems/score/hppa.h> #include <rtems/score/cpu_asm.h> #include <rtems/score/cpu.h> - #include <rtems/score/offsets.h> .SPACE $PRIVATE$ @@ -64,20 +61,12 @@ isr_r8 .reg %cr26 # PAGE^L -# void __Generic_ISR_Handler() +# void _Generic_ISR_Handler() # # This routine provides the RTEMS interrupt management. # -# NOTE: -# Upon entry, the stack will contain a stack frame back to the -# interrupted task. If dispatching is enabled, this is the -# outer most interrupt, (and a context switch is necessary or -# the current task has signals), then set up the stack to -# transfer control to the interrupt dispatcher. -# -# # We jump here from the interrupt vector. -# The hardware has done some stuff for us: +# The HPPA hardware has done some stuff for us: # PSW saved in IPSW # PSW set to 0 # PSW[E] set to default (0) @@ -89,117 +78,30 @@ isr_r8 .reg %cr26 # registers GR 1,8,9,16,17,24,25 copied to shadow regs # SHR 0 1 2 3 4 5 6 # -# Our vector stub did the following -# placed vector number is in r1 +# Our vector stub (in the BSP) MUST have done the following: # -# stub -# r1 <- vector number -# save ipsw under rock -# ipsw = ipsw & ~1 -- disable ints -# save qregs under rock -# qra = _Generic_ISR_handler -# rfi +# a) Saved the original %r9 into %isr_r9 (%cr25) +# b) Placed the vector number in %r9 +# c) Was allowed to also destroy $isr_r8 (%cr26), +# but the stub was NOT allowed to destroy any other registers. # -################################################ - -# Distinct Interrupt Entry Points +# The typical stub sequence (in the BSP) should look like this: +# +# a) mtctl %r9,isr_r9 ; (save r9 in cr25) +# b) ldi vector,%r9 ; (load constant vector number in r9) +# c) mtctl %r8,isr_r8 ; (save r8 in cr26) +# d) ldil L%MY_BSP_first_level_interrupt_handler,%r8 +# e) ldo R%MY_BSP_first_level_interrupt_handler(%r8),%r8 +# ; (point to BSP raw handler table) +# f) ldwx,s %r9(%r8),%r8 ; (load value from raw handler table) +# g) bv 0(%r8) ; (call raw handler: _Generic_ISR_Handler) +# h) mfctl isr_r8,%r8 ; (restore r8 from cr26 in delay slot) +# +# Optionally, steps (c) thru (h) _could_ be replaced with a single +# bl,n _Generic_ISR_Handler,%r0 # -# The following macro and the 32 instantiations of the macro -# are necessary to determine which interrupt vector occurred. # -# r9 is loaded with the vector number and then we jump to -# the first level interrupt handler. In most cases this -# is _Generic_ISR_Handler. In a few cases (such as TLB misc) -# it may be to some other entry point. # - -# table for first level interrupt handlers - .import HPPA_first_level_interrupt_handler, data - -#define THANDLER(vector) \ - mtctl %r9, isr_r9 ! \ - mtctl %r8, isr_r8 ! \ - ldi vector, %r9 ! \ - ldil L%HPPA_first_level_interrupt_handler,%r8 ! \ - ldo R%HPPA_first_level_interrupt_handler(%r8),%r8 ! \ - ldwx,s %r9(%r8),%r8 ! \ - bv 0(%r8) ! \ - mfctl isr_r8, %r8 - - .align 4096 - .EXPORT IVA_Table,ENTRY,PRIV_LEV=0 -IVA_Table: - .PROC - .CALLINFO FRAME=0,NO_CALLS - .ENTRY - - THANDLER(0) /* unused */ - - THANDLER(HPPA_INTERRUPT_HIGH_PRIORITY_MACHINE_CHECK) - - THANDLER(HPPA_INTERRUPT_POWER_FAIL) - - THANDLER(HPPA_INTERRUPT_RECOVERY_COUNTER) - - THANDLER(HPPA_INTERRUPT_EXTERNAL_INTERRUPT) - - THANDLER(HPPA_INTERRUPT_LOW_PRIORITY_MACHINE_CHECK) - - THANDLER(HPPA_INTERRUPT_INSTRUCTION_TLB_MISS) - - THANDLER(HPPA_INTERRUPT_INSTRUCTION_MEMORY_PROTECTION) - - THANDLER(HPPA_INTERRUPT_ILLEGAL_INSTRUCTION) - - THANDLER(HPPA_INTERRUPT_BREAK_INSTRUCTION) - - THANDLER(HPPA_INTERRUPT_PRIVILEGED_OPERATION) - - THANDLER(HPPA_INTERRUPT_PRIVILEGED_REGISTER) - - THANDLER(HPPA_INTERRUPT_OVERFLOW) - - THANDLER(HPPA_INTERRUPT_CONDITIONAL) - - THANDLER(HPPA_INTERRUPT_ASSIST_EXCEPTION) - - THANDLER(HPPA_INTERRUPT_DATA_TLB_MISS) - - THANDLER(HPPA_INTERRUPT_NON_ACCESS_INSTRUCTION_TLB_MISS) - - THANDLER(HPPA_INTERRUPT_NON_ACCESS_DATA_TLB_MISS) - - THANDLER(HPPA_INTERRUPT_DATA_MEMORY_PROTECTION) - - THANDLER(HPPA_INTERRUPT_DATA_MEMORY_BREAK) - - THANDLER(HPPA_INTERRUPT_TLB_DIRTY_BIT) - - THANDLER(HPPA_INTERRUPT_PAGE_REFERENCE) - - THANDLER(HPPA_INTERRUPT_ASSIST_EMULATION) - - THANDLER(HPPA_INTERRUPT_HIGHER_PRIVILEGE_TRANSFER) - - THANDLER(HPPA_INTERRUPT_LOWER_PRIVILEGE_TRANSFER) - - THANDLER(HPPA_INTERRUPT_TAKEN_BRANCH) - - THANDLER(HPPA_INTERRUPT_DATA_MEMORY_ACCESS_RIGHTS) - - THANDLER(HPPA_INTERRUPT_DATA_MEMORY_PROTECTION_ID) - - THANDLER(HPPA_INTERRUPT_UNALIGNED_DATA_REFERENCE) - - THANDLER(HPPA_INTERRUPT_PERFORMANCE_MONITOR) - - THANDLER(HPPA_INTERRUPT_INSTRUCTION_DEBUG) - - THANDLER(HPPA_INTERRUPT_DATA_DEBUG) - - .EXIT - .PROCEND - .EXPORT _Generic_ISR_Handler,ENTRY,PRIV_LEV=0 _Generic_ISR_Handler: .PROC @@ -235,8 +137,8 @@ _Generic_ISR_Handler: # At this point the following registers are damaged wrt the interrupt # reg current value saved value # ------------------------------------------------ -# arg0 scratch isr_arg0 (ctl) -# r9 vector number isr_r9 (ctl) +# arg0 scratch isr_arg0 (cr24) +# r9 vector number isr_r9 (cr25) # # Point to beginning of integer context and # save the integer context @@ -277,8 +179,8 @@ _Generic_ISR_Handler: # The following items are currently wrong in the integer context # reg current value saved value # ------------------------------------------------ -# arg0 scratch isr_arg0 (ctl) -# r9 vector number isr_r9 (ctl) +# arg0 scratch isr_arg0 (cr24) +# r9 vector number isr_r9 (cr25) # # Fix them @@ -377,6 +279,9 @@ stack_done: stw %r6, 0(%r4) # load address of user handler +# Note: No error checking is done, it is assumed that the +# vector table contains a valid address or a stub +# spurious handler. .import _ISR_Vector_table,data ldil L%_ISR_Vector_table,%r8 ldo R%_ISR_Vector_table(%r8),%r8 @@ -388,7 +293,7 @@ stack_done: # NOTE: can not use 'bl' since it uses "pc-relative" addressing # and we are using a hard coded address from a table # So... we fudge r2 ourselves (ala dynacall) -# +# arg0 = vector number, arg1 = ptr to rtems_interrupt_frame copy %r9, %r26 .call ARGW0=GR, ARGW1=GR blr %r0, rp @@ -404,29 +309,32 @@ post_user_interrupt_handler: rsm HPPA_PSW_I + HPPA_PSW_R, %r0 ldw -4(sp), sp -# r3 -- &_ISR_Nest_level +# r3 -- (most of) &_ISR_Nest_level # r5 -- value _ISR_Nest_level -# r4 -- &_Thread_Dispatch_disable_level +# r4 -- (most of) &_Thread_Dispatch_disable_level # r6 -- value _Thread_Dispatch_disable_level +# r7 -- (most of) &_ISR_Signals_to_thread_executing +# r8 -- value _ISR_Signals_to_thread_executing .import _ISR_Nest_level,data ldil L%_ISR_Nest_level,%r3 - ldo R%_ISR_Nest_level(%r3),%r3 - ldw 0(%r3),%r5 + ldw R%_ISR_Nest_level(%r3),%r5 .import _Thread_Dispatch_disable_level,data ldil L%_Thread_Dispatch_disable_level,%r4 - ldo R%_Thread_Dispatch_disable_level(%r4),%r4 - ldw 0(%r4), %r6 + ldw R%_Thread_Dispatch_disable_level(%r4),%r6 + + .import _ISR_Signals_to_thread_executing,data + ldil L%_ISR_Signals_to_thread_executing,%r7 # decrement isr nest level addi -1, %r5, %r5 - stw %r5, 0(%r3) + stw %r5, R%_ISR_Nest_level(%r3) # decrement dispatch disable level counter and, if not 0, go on addi -1,%r6,%r6 comibf,= 0,%r6,isr_restore - stw %r6, 0(%r4) + stw %r6, R%_Thread_Dispatch_disable_level(%r4) # check whether or not a context switch is necessary .import _Context_Switch_necessary,data @@ -436,9 +344,7 @@ post_user_interrupt_handler: # check whether or not a context switch is necessary because an ISR # sent signals to the interrupted task - .import _ISR_Signals_to_thread_executing,data - ldil L%_ISR_Signals_to_thread_executing,%r8 - ldw R%_ISR_Signals_to_thread_executing(%r8),%r8 + ldw R%_ISR_Signals_to_thread_executing(%r7),%r8 comibt,=,n 0,%r8,isr_restore @@ -450,6 +356,8 @@ post_user_interrupt_handler: # ISR_dispatch: + stw %r0, R%_ISR_Signals_to_thread_executing(%r7) + ssm HPPA_PSW_I, %r0 .import _Thread_Dispatch,code diff --git a/c/src/exec/score/cpu/hppa1.1/hppa.h b/c/src/exec/score/cpu/hppa1.1/hppa.h index 55c2a63aee..4ca7fd0a14 100644 --- a/c/src/exec/score/cpu/hppa1.1/hppa.h +++ b/c/src/exec/score/cpu/hppa1.1/hppa.h @@ -1,7 +1,4 @@ /* - * @(#)hppa.h 1.17 - 95/12/13 - * - * * Description: * * Definitions for HP PA Risc diff --git a/cpukit/score/cpu/hppa1.1/cpu.c b/cpukit/score/cpu/hppa1.1/cpu.c index 48e09b908a..89bb8a8447 100644 --- a/cpukit/score/cpu/hppa1.1/cpu.c +++ b/cpukit/score/cpu/hppa1.1/cpu.c @@ -19,117 +19,52 @@ #include <rtems/system.h> #include <rtems/score/isr.h> +void hppa_cpu_halt(unsigned32 the_error); -void hppa_external_interrupt_initialize(void); -void hppa_external_interrupt_enable(unsigned32); -void hppa_external_interrupt_disable(unsigned32); -void hppa_external_interrupt(unsigned32, CPU_Interrupt_frame *); -void hppa_cpu_halt(unsigned32); -/* - * The first level interrupt handler for first 32 interrupts/traps. - * Indexed by vector; generally each entry is _Generic_ISR_Handler. - * Some TLB traps may have their own first level handler. - */ - -extern void _Generic_ISR_Handler(void); -unsigned32 HPPA_first_level_interrupt_handler[HPPA_INTERNAL_INTERRUPTS]; - -/* _CPU_Initialize - * - * This routine performs processor dependent initialization. - * - * INPUT PARAMETERS: - * cpu_table - CPU table to initialize - * thread_dispatch - address of disptaching routine +/*PAGE * + * _CPU_ISR_install_raw_handler */ - -void _CPU_Initialize( - rtems_cpu_table *cpu_table, - void (*thread_dispatch) /* ignored on this CPU */ + +void _CPU_ISR_install_raw_handler( + unsigned32 vector, + proc_ptr new_handler, + proc_ptr *old_handler ) { - register unsigned8 *fp_context; - unsigned32 iva; - unsigned32 iva_table; - int i; - - extern void IVA_Table(void); - - /* - * XXX; need to setup fpsr smarter perhaps - */ - - fp_context = (unsigned8*) &_CPU_Null_fp_context; - for (i=0 ; i<sizeof(Context_Control_fp); i++) - *fp_context++ = 0; - - /* - * Set _CPU_Default_gr27 here so it will hopefully be the correct - * global data pointer for the entire system. - */ - - asm volatile( "stw %%r27,%0" : "=m" (_CPU_Default_gr27): ); - - /* - * Init the first level interrupt handlers - */ - - for (i=0; i <= HPPA_INTERNAL_INTERRUPTS; i++) - HPPA_first_level_interrupt_handler[i] = (unsigned32) _Generic_ISR_Handler; + /* + * This is unsupported. For HPPA this function is handled by BSP + */ - /* - * Init the 2nd level interrupt handlers - */ + _CPU_Fatal_halt( 0xdeaddead ); +} - for (i=0; i <= CPU_INTERRUPT_NUMBER_OF_VECTORS; i++) - _ISR_Vector_table[i] = (ISR_Handler_entry) hppa_cpu_halt; - /* - * Stabilize the interrupt stuff - */ - (void) hppa_external_interrupt_initialize(); +/* + * This is the default handler which is called if + * _CPU_ISR_install_vector() has not been called for the + * specified vector. It simply forwards onto the spurious + * handler defined in the cpu-table. + */ - /* - * Set the IVA to point to physical address of the IVA_Table - */ +static ISR_Handler +hppa_interrupt_report_spurious(ISR_Vector_number vector, + void* rtems_isr_frame) /* HPPA extension */ +{ - iva_table = (unsigned32) IVA_Table; -#if defined(hppa1_1) /* - * HACK: (from PA72000 TRM, page 4-19) - * "The hardware TLB miss handler will never attempt to service - * a non-access TLB miss or a TLB protection violation. It - * will only attempt to service TLB accesses that would cause - * Trap Numbers 6 (Instruction TLB miss) and 15 (Data TLB miss)." - * - * The LPA instruction is used to translate a virtual address to - * a physical address, however, if the requested virtual address - * is not currently resident in the TLB, the hardware TLB miss - * handler will NOT insert it. In this situation Trap Number - * #17 is invoked (Non-access Data TLB miss fault). - * - * To work around this, a dummy data access is first performed - * to the virtual address prior to the LPA. The dummy access - * causes the TLB entry to be inserted (if not already present) - * and then the following LPA instruction will not generate - * a non-access data TLB miss fault. - * - * It is unclear whether or not this behaves the same way for - * the PA8000. - * + * If the CPU table defines a spurious_handler, then + * call it. If the handler returns halt. */ - iva = *(volatile unsigned32 *)iva_table; /* dummy access */ -#endif - - HPPA_ASM_LPA(0, iva_table, iva); - set_iva(iva); - - _CPU_Table = *cpu_table; + if ( _CPU_Table.spurious_handler ) + _CPU_Table.spurious_handler(vector, rtems_isr_frame); + + hppa_cpu_halt(vector); } + /*PAGE * * _CPU_ISR_Get_level @@ -146,28 +81,10 @@ unsigned32 _CPU_ISR_Get_level(void) /*PAGE * - * _CPU_ISR_install_raw_handler - */ - -void _CPU_ISR_install_raw_handler( - unsigned32 vector, - proc_ptr new_handler, - proc_ptr *old_handler -) -{ - /* - * This is unsupported. - */ - - _CPU_Fatal_halt( 0xdeaddead ); -} - -/*PAGE - * * _CPU_ISR_install_vector * * This kernel routine installs the RTEMS handler for the - * specified vector. + * specified vector. The handler is a C callable routine. * * Input parameters: * vector - interrupt vector number @@ -178,12 +95,6 @@ void _CPU_ISR_install_raw_handler( * */ -/* - * HPPA has 8w for each vector instead of an address to jump to. - * We put the actual ISR address in '_ISR_vector_table'. This will - * be pulled by the code in the vector. - */ - void _CPU_ISR_install_vector( unsigned32 vector, proc_ptr new_handler, @@ -193,166 +104,74 @@ void _CPU_ISR_install_vector( *old_handler = _ISR_Vector_table[vector]; _ISR_Vector_table[vector] = new_handler; - - if (vector >= HPPA_INTERRUPT_EXTERNAL_BASE) - { - unsigned32 external_vector; - - external_vector = vector - HPPA_INTERRUPT_EXTERNAL_BASE; - if (new_handler) - hppa_external_interrupt_enable(external_vector); - else - /* XXX this can never happen due to _ISR_Is_valid_user_handler */ - hppa_external_interrupt_disable(external_vector); - } } - -/* - * Support for external and spurious interrupts on HPPA +/* _CPU_Initialize + * + * This routine performs processor dependent initialization. + * + * INPUT PARAMETERS: + * cpu_table - CPU table to initialize + * thread_dispatch - address of disptaching routine * - * TODO: - * Count interrupts - * make sure interrupts disabled properly - */ - -#define DISMISS(mask) set_eirr(mask) -#define DISABLE(mask) set_eiem(get_eiem() & ~(mask)) -#define ENABLE(mask) set_eiem(get_eiem() | (mask)) -#define VECTOR_TO_MASK(v) (1 << (31 - (v))) - -/* - * Init the external interrupt scheme - * called by bsp_start() */ -void -hppa_external_interrupt_initialize(void) +void _CPU_Initialize( + rtems_cpu_table *cpu_table, + void (*thread_dispatch) /* ignored on this CPU */ +) { - proc_ptr ignore; - - /* mark them all unused */ - DISABLE(~0); - DISMISS(~0); - - /* install the external interrupt handler */ - _CPU_ISR_install_vector( - HPPA_INTERRUPT_EXTERNAL_INTERRUPT, - (proc_ptr)hppa_external_interrupt, &ignore -); -} - -/* - * Enable a specific external interrupt - */ + register unsigned8 *fp_context; + int i; + proc_ptr old_handler; -void -hppa_external_interrupt_enable(unsigned32 v) -{ - unsigned32 isrlevel; + /* + * XXX; need to setup fpsr smarter perhaps + */ - _CPU_ISR_Disable(isrlevel); - ENABLE(VECTOR_TO_MASK(v)); - _CPU_ISR_Enable(isrlevel); -} + fp_context = (unsigned8*) &_CPU_Null_fp_context; + for (i=0 ; i<sizeof(Context_Control_fp); i++) + *fp_context++ = 0; -/* - * Does not clear or otherwise affect any pending requests - */ + /* + * Set _CPU_Default_gr27 here so it will hopefully be the correct + * global data pointer for the entire system. + */ -void -hppa_external_interrupt_disable(unsigned32 v) -{ - unsigned32 isrlevel; + asm volatile( "stw %%r27,%0" : "=m" (_CPU_Default_gr27): ); - _CPU_ISR_Disable(isrlevel); - DISABLE(VECTOR_TO_MASK(v)); - _CPU_ISR_Enable(isrlevel); -} + /* + * Init the 2nd level interrupt handlers + */ -void -hppa_external_interrupt_spurious_handler(unsigned32 vector, - CPU_Interrupt_frame *iframe) -{ -/* XXX should not be printing :) - printf("spurious external interrupt: %d at pc 0x%x; disabling\n", - vector, iframe->Interrupt.pcoqfront); -*/ -} + for (i=0; i < CPU_INTERRUPT_NUMBER_OF_VECTORS; i++) + _CPU_ISR_install_vector(i, + hppa_interrupt_report_spurious, + &old_handler); -void -hppa_external_interrupt_report_spurious(unsigned32 spurious_mask, - CPU_Interrupt_frame *iframe) -{ - int v; - for (v=0; v < HPPA_EXTERNAL_INTERRUPTS; v++) - if (VECTOR_TO_MASK(v) & spurious_mask) - { - DISMISS(VECTOR_TO_MASK(v)); - DISABLE(VECTOR_TO_MASK(v)); - hppa_external_interrupt_spurious_handler(v, iframe); - } - DISMISS(spurious_mask); + _CPU_Table = *cpu_table; + } /* - * External interrupt handler. - * This is installed as cpu interrupt handler for - * HPPA_INTERRUPT_EXTERNAL_INTERRUPT. It vectors out to - * specific external interrupt handlers. - */ - -void -hppa_external_interrupt(unsigned32 vector, - CPU_Interrupt_frame *iframe) -{ - unsigned32 mask; - unsigned32 *vp, *max_vp; - unsigned32 external_vector; - unsigned32 global_vector; - hppa_rtems_isr_entry handler; - - max_vp = &_CPU_Table.external_interrupt[_CPU_Table.external_interrupts]; - while ( (mask = (get_eirr() & get_eiem())) ) - { - for (vp = _CPU_Table.external_interrupt; (vp < max_vp) && mask; vp++) - { - unsigned32 m; - - external_vector = *vp; - global_vector = external_vector + HPPA_INTERRUPT_EXTERNAL_BASE; - m = VECTOR_TO_MASK(external_vector); - handler = (hppa_rtems_isr_entry) _ISR_Vector_table[global_vector]; - if ((m & mask) && handler) - { - DISMISS(m); - mask &= ~m; - handler(global_vector, iframe); - } - } - - if (mask != 0) { - if ( _CPU_Table.spurious_handler ) - { - handler = (hppa_rtems_isr_entry) _CPU_Table.spurious_handler; - handler(mask, iframe); - } - else - hppa_external_interrupt_report_spurious(mask, iframe); - } - } -} - -/* * Halt the system. * Called by the _CPU_Fatal_halt macro * * XXX * Later on, this will allow us to return to the prom. * For now, we just ignore 'type_of_halt' + * + * XXX + * NOTE: for gcc, this function must be at the bottom + * of the file, that is because if it is at the top + * of the file, gcc will inline it's calls. Since + * the function uses the HPPA_ASM_LABEL() macro, when + * gcc inlines it, you get two definitions of the same + * label name, which is an assembly error. */ + void hppa_cpu_halt(unsigned32 the_error) { @@ -360,6 +179,11 @@ hppa_cpu_halt(unsigned32 the_error) _CPU_ISR_Disable(isrlevel); + /* + * XXXXX NOTE: This label is only needed that that when + * the simulator stops, it shows the label name specified + */ HPPA_ASM_LABEL("_hppa_cpu_halt"); - HPPA_ASM_BREAK(1, 0); + HPPA_ASM_BREAK(0, 0); } + |