mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-24 21:37:11 +00:00
updartes from Tony Bennett
This commit is contained in:
@@ -19,117 +19,52 @@
|
|||||||
|
|
||||||
#include <rtems/system.h>
|
#include <rtems/system.h>
|
||||||
#include <rtems/score/isr.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);
|
|
||||||
|
|
||||||
/*
|
/*PAGE
|
||||||
* The first level interrupt handler for first 32 interrupts/traps.
|
*
|
||||||
* Indexed by vector; generally each entry is _Generic_ISR_Handler.
|
* _CPU_ISR_install_raw_handler
|
||||||
* Some TLB traps may have their own first level handler.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern void _Generic_ISR_Handler(void);
|
void _CPU_ISR_install_raw_handler(
|
||||||
unsigned32 HPPA_first_level_interrupt_handler[HPPA_INTERNAL_INTERRUPTS];
|
unsigned32 vector,
|
||||||
|
proc_ptr new_handler,
|
||||||
/* _CPU_Initialize
|
proc_ptr *old_handler
|
||||||
*
|
|
||||||
* This routine performs processor dependent initialization.
|
|
||||||
*
|
|
||||||
* INPUT PARAMETERS:
|
|
||||||
* cpu_table - CPU table to initialize
|
|
||||||
* thread_dispatch - address of disptaching routine
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
void _CPU_Initialize(
|
|
||||||
rtems_cpu_table *cpu_table,
|
|
||||||
void (*thread_dispatch) /* ignored on this CPU */
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
register unsigned8 *fp_context;
|
/*
|
||||||
unsigned32 iva;
|
* This is unsupported. For HPPA this function is handled by BSP
|
||||||
unsigned32 iva_table;
|
*/
|
||||||
int i;
|
|
||||||
|
|
||||||
extern void IVA_Table(void);
|
_CPU_Fatal_halt( 0xdeaddead );
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Init the 2nd level interrupt handlers
|
|
||||||
*/
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the IVA to point to physical address of the IVA_Table
|
|
||||||
*/
|
|
||||||
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
iva = *(volatile unsigned32 *)iva_table; /* dummy access */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HPPA_ASM_LPA(0, iva_table, iva);
|
|
||||||
set_iva(iva);
|
|
||||||
|
|
||||||
_CPU_Table = *cpu_table;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static ISR_Handler
|
||||||
|
hppa_interrupt_report_spurious(ISR_Vector_number vector,
|
||||||
|
void* rtems_isr_frame) /* HPPA extension */
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the CPU table defines a spurious_handler, then
|
||||||
|
* call it. If the handler returns halt.
|
||||||
|
*/
|
||||||
|
if ( _CPU_Table.spurious_handler )
|
||||||
|
_CPU_Table.spurious_handler(vector, rtems_isr_frame);
|
||||||
|
|
||||||
|
hppa_cpu_halt(vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*PAGE
|
/*PAGE
|
||||||
*
|
*
|
||||||
* _CPU_ISR_Get_level
|
* _CPU_ISR_Get_level
|
||||||
@@ -144,30 +79,12 @@ unsigned32 _CPU_ISR_Get_level(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*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
|
/*PAGE
|
||||||
*
|
*
|
||||||
* _CPU_ISR_install_vector
|
* _CPU_ISR_install_vector
|
||||||
*
|
*
|
||||||
* This kernel routine installs the RTEMS handler for the
|
* This kernel routine installs the RTEMS handler for the
|
||||||
* specified vector.
|
* specified vector. The handler is a C callable routine.
|
||||||
*
|
*
|
||||||
* Input parameters:
|
* Input parameters:
|
||||||
* vector - interrupt vector number
|
* 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(
|
void _CPU_ISR_install_vector(
|
||||||
unsigned32 vector,
|
unsigned32 vector,
|
||||||
proc_ptr new_handler,
|
proc_ptr new_handler,
|
||||||
@@ -193,156 +104,55 @@ void _CPU_ISR_install_vector(
|
|||||||
*old_handler = _ISR_Vector_table[vector];
|
*old_handler = _ISR_Vector_table[vector];
|
||||||
|
|
||||||
_ISR_Vector_table[vector] = new_handler;
|
_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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* _CPU_Initialize
|
||||||
/*
|
*
|
||||||
* Support for external and spurious interrupts on HPPA
|
* 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)
|
void _CPU_Initialize(
|
||||||
#define DISABLE(mask) set_eiem(get_eiem() & ~(mask))
|
rtems_cpu_table *cpu_table,
|
||||||
#define ENABLE(mask) set_eiem(get_eiem() | (mask))
|
void (*thread_dispatch) /* ignored on this CPU */
|
||||||
#define VECTOR_TO_MASK(v) (1 << (31 - (v)))
|
)
|
||||||
|
|
||||||
/*
|
|
||||||
* Init the external interrupt scheme
|
|
||||||
* called by bsp_start()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
hppa_external_interrupt_initialize(void)
|
|
||||||
{
|
{
|
||||||
proc_ptr ignore;
|
register unsigned8 *fp_context;
|
||||||
|
int i;
|
||||||
|
proc_ptr old_handler;
|
||||||
|
|
||||||
/* mark them all unused */
|
/*
|
||||||
DISABLE(~0);
|
* XXX; need to setup fpsr smarter perhaps
|
||||||
DISMISS(~0);
|
*/
|
||||||
|
|
||||||
/* install the external interrupt handler */
|
fp_context = (unsigned8*) &_CPU_Null_fp_context;
|
||||||
_CPU_ISR_install_vector(
|
for (i=0 ; i<sizeof(Context_Control_fp); i++)
|
||||||
HPPA_INTERRUPT_EXTERNAL_INTERRUPT,
|
*fp_context++ = 0;
|
||||||
(proc_ptr)hppa_external_interrupt, &ignore
|
|
||||||
);
|
/*
|
||||||
|
* 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 2nd level interrupt handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (i=0; i < CPU_INTERRUPT_NUMBER_OF_VECTORS; i++)
|
||||||
|
_CPU_ISR_install_vector(i,
|
||||||
|
hppa_interrupt_report_spurious,
|
||||||
|
&old_handler);
|
||||||
|
|
||||||
|
_CPU_Table = *cpu_table;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable a specific external interrupt
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
hppa_external_interrupt_enable(unsigned32 v)
|
|
||||||
{
|
|
||||||
unsigned32 isrlevel;
|
|
||||||
|
|
||||||
_CPU_ISR_Disable(isrlevel);
|
|
||||||
ENABLE(VECTOR_TO_MASK(v));
|
|
||||||
_CPU_ISR_Enable(isrlevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Does not clear or otherwise affect any pending requests
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
hppa_external_interrupt_disable(unsigned32 v)
|
|
||||||
{
|
|
||||||
unsigned32 isrlevel;
|
|
||||||
|
|
||||||
_CPU_ISR_Disable(isrlevel);
|
|
||||||
DISABLE(VECTOR_TO_MASK(v));
|
|
||||||
_CPU_ISR_Enable(isrlevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
* Halt the system.
|
||||||
@@ -351,8 +161,17 @@ hppa_external_interrupt(unsigned32 vector,
|
|||||||
* XXX
|
* XXX
|
||||||
* Later on, this will allow us to return to the prom.
|
* Later on, this will allow us to return to the prom.
|
||||||
* For now, we just ignore 'type_of_halt'
|
* 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
|
void
|
||||||
hppa_cpu_halt(unsigned32 the_error)
|
hppa_cpu_halt(unsigned32 the_error)
|
||||||
{
|
{
|
||||||
@@ -360,6 +179,11 @@ hppa_cpu_halt(unsigned32 the_error)
|
|||||||
|
|
||||||
_CPU_ISR_Disable(isrlevel);
|
_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_LABEL("_hppa_cpu_halt");
|
||||||
HPPA_ASM_BREAK(1, 0);
|
HPPA_ASM_BREAK(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -216,26 +216,12 @@ typedef struct {
|
|||||||
void (*predriver_hook)( void );
|
void (*predriver_hook)( void );
|
||||||
void (*postdriver_hook)( void );
|
void (*postdriver_hook)( void );
|
||||||
void (*idle_task)( 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;
|
boolean do_zero_of_workspace;
|
||||||
|
|
||||||
unsigned32 interrupt_stack_size;
|
unsigned32 interrupt_stack_size;
|
||||||
unsigned32 extra_mpci_receive_server_stack;
|
unsigned32 extra_mpci_receive_server_stack;
|
||||||
|
void * (*stack_allocate_hook)( unsigned32 );
|
||||||
/*
|
void (*stack_free_hook)( void * );
|
||||||
* Control of external interrupts.
|
/* end of fields required on all CPUs */
|
||||||
* 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];
|
|
||||||
|
|
||||||
hppa_rtems_isr_entry spurious_handler;
|
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_low;
|
||||||
EXTERN void *_CPU_Interrupt_stack_high;
|
EXTERN void *_CPU_Interrupt_stack_high;
|
||||||
|
|
||||||
/* entry points */
|
|
||||||
void hppa_external_interrupt_spurious_handler(unsigned32, CPU_Interrupt_frame *);
|
|
||||||
|
|
||||||
#endif /* ! ASM */
|
#endif /* ! ASM */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -285,15 +268,12 @@ void hppa_external_interrupt_spurious_handler(unsigned32, CPU_Interrupt_frame *)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* HPPA has 32 interrupts, then 32 external interrupts
|
* HPPA has 32 interrupts, then 32 external interrupts
|
||||||
* Rtems (_ISR_Vector_Table) is aware of the first 64
|
* Rtems (_ISR_Vector_Table) is aware ONLY of the first 32
|
||||||
* A BSP may reserve more.
|
* 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)
|
#define CPU_INTERRUPT_MAXIMUM_VECTOR_NUMBER (CPU_INTERRUPT_NUMBER_OF_VECTORS - 1)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
# @(#)cpu_asm.S 1.7 - 95/09/21
|
|
||||||
#
|
|
||||||
#
|
#
|
||||||
# TODO:
|
# TODO:
|
||||||
# Context_switch needs to only save callee save registers
|
# Context_switch needs to only save callee save registers
|
||||||
@@ -30,7 +28,6 @@
|
|||||||
#include <rtems/score/hppa.h>
|
#include <rtems/score/hppa.h>
|
||||||
#include <rtems/score/cpu_asm.h>
|
#include <rtems/score/cpu_asm.h>
|
||||||
#include <rtems/score/cpu.h>
|
#include <rtems/score/cpu.h>
|
||||||
|
|
||||||
#include <rtems/score/offsets.h>
|
#include <rtems/score/offsets.h>
|
||||||
|
|
||||||
.SPACE $PRIVATE$
|
.SPACE $PRIVATE$
|
||||||
@@ -64,20 +61,12 @@ isr_r8 .reg %cr26
|
|||||||
|
|
||||||
|
|
||||||
# PAGE^L
|
# PAGE^L
|
||||||
# void __Generic_ISR_Handler()
|
# void _Generic_ISR_Handler()
|
||||||
#
|
#
|
||||||
# This routine provides the RTEMS interrupt management.
|
# 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.
|
# 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 saved in IPSW
|
||||||
# PSW set to 0
|
# PSW set to 0
|
||||||
# PSW[E] set to default (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
|
# registers GR 1,8,9,16,17,24,25 copied to shadow regs
|
||||||
# SHR 0 1 2 3 4 5 6
|
# SHR 0 1 2 3 4 5 6
|
||||||
#
|
#
|
||||||
# Our vector stub did the following
|
# Our vector stub (in the BSP) MUST have done the following:
|
||||||
# placed vector number is in r1
|
|
||||||
#
|
#
|
||||||
# stub
|
# a) Saved the original %r9 into %isr_r9 (%cr25)
|
||||||
# r1 <- vector number
|
# b) Placed the vector number in %r9
|
||||||
# save ipsw under rock
|
# c) Was allowed to also destroy $isr_r8 (%cr26),
|
||||||
# ipsw = ipsw & ~1 -- disable ints
|
# but the stub was NOT allowed to destroy any other registers.
|
||||||
# save qregs under rock
|
|
||||||
# qra = _Generic_ISR_handler
|
|
||||||
# rfi
|
|
||||||
#
|
#
|
||||||
################################################
|
# The typical stub sequence (in the BSP) should look like this:
|
||||||
|
#
|
||||||
# Distinct Interrupt Entry Points
|
# 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
|
.EXPORT _Generic_ISR_Handler,ENTRY,PRIV_LEV=0
|
||||||
_Generic_ISR_Handler:
|
_Generic_ISR_Handler:
|
||||||
.PROC
|
.PROC
|
||||||
@@ -235,8 +137,8 @@ _Generic_ISR_Handler:
|
|||||||
# At this point the following registers are damaged wrt the interrupt
|
# At this point the following registers are damaged wrt the interrupt
|
||||||
# reg current value saved value
|
# reg current value saved value
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
# arg0 scratch isr_arg0 (ctl)
|
# arg0 scratch isr_arg0 (cr24)
|
||||||
# r9 vector number isr_r9 (ctl)
|
# r9 vector number isr_r9 (cr25)
|
||||||
#
|
#
|
||||||
# Point to beginning of integer context and
|
# Point to beginning of integer context and
|
||||||
# save the integer context
|
# save the integer context
|
||||||
@@ -277,8 +179,8 @@ _Generic_ISR_Handler:
|
|||||||
# The following items are currently wrong in the integer context
|
# The following items are currently wrong in the integer context
|
||||||
# reg current value saved value
|
# reg current value saved value
|
||||||
# ------------------------------------------------
|
# ------------------------------------------------
|
||||||
# arg0 scratch isr_arg0 (ctl)
|
# arg0 scratch isr_arg0 (cr24)
|
||||||
# r9 vector number isr_r9 (ctl)
|
# r9 vector number isr_r9 (cr25)
|
||||||
#
|
#
|
||||||
# Fix them
|
# Fix them
|
||||||
|
|
||||||
@@ -377,6 +279,9 @@ stack_done:
|
|||||||
stw %r6, 0(%r4)
|
stw %r6, 0(%r4)
|
||||||
|
|
||||||
# load address of user handler
|
# 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
|
.import _ISR_Vector_table,data
|
||||||
ldil L%_ISR_Vector_table,%r8
|
ldil L%_ISR_Vector_table,%r8
|
||||||
ldo R%_ISR_Vector_table(%r8),%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
|
# NOTE: can not use 'bl' since it uses "pc-relative" addressing
|
||||||
# and we are using a hard coded address from a table
|
# and we are using a hard coded address from a table
|
||||||
# So... we fudge r2 ourselves (ala dynacall)
|
# So... we fudge r2 ourselves (ala dynacall)
|
||||||
#
|
# arg0 = vector number, arg1 = ptr to rtems_interrupt_frame
|
||||||
copy %r9, %r26
|
copy %r9, %r26
|
||||||
.call ARGW0=GR, ARGW1=GR
|
.call ARGW0=GR, ARGW1=GR
|
||||||
blr %r0, rp
|
blr %r0, rp
|
||||||
@@ -404,29 +309,32 @@ post_user_interrupt_handler:
|
|||||||
rsm HPPA_PSW_I + HPPA_PSW_R, %r0
|
rsm HPPA_PSW_I + HPPA_PSW_R, %r0
|
||||||
ldw -4(sp), sp
|
ldw -4(sp), sp
|
||||||
|
|
||||||
# r3 -- &_ISR_Nest_level
|
# r3 -- (most of) &_ISR_Nest_level
|
||||||
# r5 -- value _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
|
# 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
|
.import _ISR_Nest_level,data
|
||||||
ldil L%_ISR_Nest_level,%r3
|
ldil L%_ISR_Nest_level,%r3
|
||||||
ldo R%_ISR_Nest_level(%r3),%r3
|
ldw R%_ISR_Nest_level(%r3),%r5
|
||||||
ldw 0(%r3),%r5
|
|
||||||
|
|
||||||
.import _Thread_Dispatch_disable_level,data
|
.import _Thread_Dispatch_disable_level,data
|
||||||
ldil L%_Thread_Dispatch_disable_level,%r4
|
ldil L%_Thread_Dispatch_disable_level,%r4
|
||||||
ldo R%_Thread_Dispatch_disable_level(%r4),%r4
|
ldw R%_Thread_Dispatch_disable_level(%r4),%r6
|
||||||
ldw 0(%r4), %r6
|
|
||||||
|
.import _ISR_Signals_to_thread_executing,data
|
||||||
|
ldil L%_ISR_Signals_to_thread_executing,%r7
|
||||||
|
|
||||||
# decrement isr nest level
|
# decrement isr nest level
|
||||||
addi -1, %r5, %r5
|
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
|
# decrement dispatch disable level counter and, if not 0, go on
|
||||||
addi -1,%r6,%r6
|
addi -1,%r6,%r6
|
||||||
comibf,= 0,%r6,isr_restore
|
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
|
# check whether or not a context switch is necessary
|
||||||
.import _Context_Switch_necessary,data
|
.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
|
# check whether or not a context switch is necessary because an ISR
|
||||||
# sent signals to the interrupted task
|
# sent signals to the interrupted task
|
||||||
.import _ISR_Signals_to_thread_executing,data
|
ldw R%_ISR_Signals_to_thread_executing(%r7),%r8
|
||||||
ldil L%_ISR_Signals_to_thread_executing,%r8
|
|
||||||
ldw R%_ISR_Signals_to_thread_executing(%r8),%r8
|
|
||||||
comibt,=,n 0,%r8,isr_restore
|
comibt,=,n 0,%r8,isr_restore
|
||||||
|
|
||||||
|
|
||||||
@@ -450,6 +356,8 @@ post_user_interrupt_handler:
|
|||||||
#
|
#
|
||||||
|
|
||||||
ISR_dispatch:
|
ISR_dispatch:
|
||||||
|
stw %r0, R%_ISR_Signals_to_thread_executing(%r7)
|
||||||
|
|
||||||
ssm HPPA_PSW_I, %r0
|
ssm HPPA_PSW_I, %r0
|
||||||
|
|
||||||
.import _Thread_Dispatch,code
|
.import _Thread_Dispatch,code
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
/*
|
/*
|
||||||
* @(#)hppa.h 1.17 - 95/12/13
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Description:
|
* Description:
|
||||||
*
|
*
|
||||||
* Definitions for HP PA Risc
|
* Definitions for HP PA Risc
|
||||||
|
|||||||
@@ -19,117 +19,52 @@
|
|||||||
|
|
||||||
#include <rtems/system.h>
|
#include <rtems/system.h>
|
||||||
#include <rtems/score/isr.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);
|
|
||||||
|
|
||||||
/*
|
/*PAGE
|
||||||
* The first level interrupt handler for first 32 interrupts/traps.
|
*
|
||||||
* Indexed by vector; generally each entry is _Generic_ISR_Handler.
|
* _CPU_ISR_install_raw_handler
|
||||||
* Some TLB traps may have their own first level handler.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
extern void _Generic_ISR_Handler(void);
|
void _CPU_ISR_install_raw_handler(
|
||||||
unsigned32 HPPA_first_level_interrupt_handler[HPPA_INTERNAL_INTERRUPTS];
|
unsigned32 vector,
|
||||||
|
proc_ptr new_handler,
|
||||||
/* _CPU_Initialize
|
proc_ptr *old_handler
|
||||||
*
|
|
||||||
* This routine performs processor dependent initialization.
|
|
||||||
*
|
|
||||||
* INPUT PARAMETERS:
|
|
||||||
* cpu_table - CPU table to initialize
|
|
||||||
* thread_dispatch - address of disptaching routine
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
void _CPU_Initialize(
|
|
||||||
rtems_cpu_table *cpu_table,
|
|
||||||
void (*thread_dispatch) /* ignored on this CPU */
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
register unsigned8 *fp_context;
|
/*
|
||||||
unsigned32 iva;
|
* This is unsupported. For HPPA this function is handled by BSP
|
||||||
unsigned32 iva_table;
|
*/
|
||||||
int i;
|
|
||||||
|
|
||||||
extern void IVA_Table(void);
|
_CPU_Fatal_halt( 0xdeaddead );
|
||||||
|
|
||||||
/*
|
|
||||||
* 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;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Init the 2nd level interrupt handlers
|
|
||||||
*/
|
|
||||||
|
|
||||||
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();
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Set the IVA to point to physical address of the IVA_Table
|
|
||||||
*/
|
|
||||||
|
|
||||||
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.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
iva = *(volatile unsigned32 *)iva_table; /* dummy access */
|
|
||||||
#endif
|
|
||||||
|
|
||||||
HPPA_ASM_LPA(0, iva_table, iva);
|
|
||||||
set_iva(iva);
|
|
||||||
|
|
||||||
_CPU_Table = *cpu_table;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static ISR_Handler
|
||||||
|
hppa_interrupt_report_spurious(ISR_Vector_number vector,
|
||||||
|
void* rtems_isr_frame) /* HPPA extension */
|
||||||
|
{
|
||||||
|
|
||||||
|
/*
|
||||||
|
* If the CPU table defines a spurious_handler, then
|
||||||
|
* call it. If the handler returns halt.
|
||||||
|
*/
|
||||||
|
if ( _CPU_Table.spurious_handler )
|
||||||
|
_CPU_Table.spurious_handler(vector, rtems_isr_frame);
|
||||||
|
|
||||||
|
hppa_cpu_halt(vector);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*PAGE
|
/*PAGE
|
||||||
*
|
*
|
||||||
* _CPU_ISR_Get_level
|
* _CPU_ISR_Get_level
|
||||||
@@ -144,30 +79,12 @@ unsigned32 _CPU_ISR_Get_level(void)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*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
|
/*PAGE
|
||||||
*
|
*
|
||||||
* _CPU_ISR_install_vector
|
* _CPU_ISR_install_vector
|
||||||
*
|
*
|
||||||
* This kernel routine installs the RTEMS handler for the
|
* This kernel routine installs the RTEMS handler for the
|
||||||
* specified vector.
|
* specified vector. The handler is a C callable routine.
|
||||||
*
|
*
|
||||||
* Input parameters:
|
* Input parameters:
|
||||||
* vector - interrupt vector number
|
* 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(
|
void _CPU_ISR_install_vector(
|
||||||
unsigned32 vector,
|
unsigned32 vector,
|
||||||
proc_ptr new_handler,
|
proc_ptr new_handler,
|
||||||
@@ -193,156 +104,55 @@ void _CPU_ISR_install_vector(
|
|||||||
*old_handler = _ISR_Vector_table[vector];
|
*old_handler = _ISR_Vector_table[vector];
|
||||||
|
|
||||||
_ISR_Vector_table[vector] = new_handler;
|
_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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* _CPU_Initialize
|
||||||
/*
|
*
|
||||||
* Support for external and spurious interrupts on HPPA
|
* 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)
|
void _CPU_Initialize(
|
||||||
#define DISABLE(mask) set_eiem(get_eiem() & ~(mask))
|
rtems_cpu_table *cpu_table,
|
||||||
#define ENABLE(mask) set_eiem(get_eiem() | (mask))
|
void (*thread_dispatch) /* ignored on this CPU */
|
||||||
#define VECTOR_TO_MASK(v) (1 << (31 - (v)))
|
)
|
||||||
|
|
||||||
/*
|
|
||||||
* Init the external interrupt scheme
|
|
||||||
* called by bsp_start()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
hppa_external_interrupt_initialize(void)
|
|
||||||
{
|
{
|
||||||
proc_ptr ignore;
|
register unsigned8 *fp_context;
|
||||||
|
int i;
|
||||||
|
proc_ptr old_handler;
|
||||||
|
|
||||||
/* mark them all unused */
|
/*
|
||||||
DISABLE(~0);
|
* XXX; need to setup fpsr smarter perhaps
|
||||||
DISMISS(~0);
|
*/
|
||||||
|
|
||||||
/* install the external interrupt handler */
|
fp_context = (unsigned8*) &_CPU_Null_fp_context;
|
||||||
_CPU_ISR_install_vector(
|
for (i=0 ; i<sizeof(Context_Control_fp); i++)
|
||||||
HPPA_INTERRUPT_EXTERNAL_INTERRUPT,
|
*fp_context++ = 0;
|
||||||
(proc_ptr)hppa_external_interrupt, &ignore
|
|
||||||
);
|
/*
|
||||||
|
* 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 2nd level interrupt handlers
|
||||||
|
*/
|
||||||
|
|
||||||
|
for (i=0; i < CPU_INTERRUPT_NUMBER_OF_VECTORS; i++)
|
||||||
|
_CPU_ISR_install_vector(i,
|
||||||
|
hppa_interrupt_report_spurious,
|
||||||
|
&old_handler);
|
||||||
|
|
||||||
|
_CPU_Table = *cpu_table;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* Enable a specific external interrupt
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
hppa_external_interrupt_enable(unsigned32 v)
|
|
||||||
{
|
|
||||||
unsigned32 isrlevel;
|
|
||||||
|
|
||||||
_CPU_ISR_Disable(isrlevel);
|
|
||||||
ENABLE(VECTOR_TO_MASK(v));
|
|
||||||
_CPU_ISR_Enable(isrlevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Does not clear or otherwise affect any pending requests
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
hppa_external_interrupt_disable(unsigned32 v)
|
|
||||||
{
|
|
||||||
unsigned32 isrlevel;
|
|
||||||
|
|
||||||
_CPU_ISR_Disable(isrlevel);
|
|
||||||
DISABLE(VECTOR_TO_MASK(v));
|
|
||||||
_CPU_ISR_Enable(isrlevel);
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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.
|
* Halt the system.
|
||||||
@@ -351,8 +161,17 @@ hppa_external_interrupt(unsigned32 vector,
|
|||||||
* XXX
|
* XXX
|
||||||
* Later on, this will allow us to return to the prom.
|
* Later on, this will allow us to return to the prom.
|
||||||
* For now, we just ignore 'type_of_halt'
|
* 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
|
void
|
||||||
hppa_cpu_halt(unsigned32 the_error)
|
hppa_cpu_halt(unsigned32 the_error)
|
||||||
{
|
{
|
||||||
@@ -360,6 +179,11 @@ hppa_cpu_halt(unsigned32 the_error)
|
|||||||
|
|
||||||
_CPU_ISR_Disable(isrlevel);
|
_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_LABEL("_hppa_cpu_halt");
|
||||||
HPPA_ASM_BREAK(1, 0);
|
HPPA_ASM_BREAK(0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user