updartes from Tony Bennett

This commit is contained in:
Joel Sherrill
1996-04-22 16:30:02 +00:00
parent 767a6c614c
commit d0b7c4e61e
5 changed files with 235 additions and 702 deletions

View File

@@ -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.
/*PAGE
*
* _CPU_ISR_install_raw_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
*
*/
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;
/*
* This is unsupported. For HPPA this function is handled by BSP
*/
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;
/*
* 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;
_CPU_Fatal_halt( 0xdeaddead );
}
/*
* 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
*
* _CPU_ISR_Get_level
@@ -144,30 +79,12 @@ unsigned32 _CPU_ISR_Get_level(void)
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
*
* _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,156 +104,55 @@ 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;
register unsigned8 *fp_context;
int i;
proc_ptr old_handler;
/* mark them all unused */
DISABLE(~0);
DISMISS(~0);
/*
* XXX; need to setup fpsr smarter perhaps
*/
/* install the external interrupt handler */
_CPU_ISR_install_vector(
HPPA_INTERRUPT_EXTERNAL_INTERRUPT,
(proc_ptr)hppa_external_interrupt, &ignore
);
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 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.
@@ -351,8 +161,17 @@ hppa_external_interrupt(unsigned32 vector,
* 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);
}

View File

@@ -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)
/*

View File

@@ -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

View File

@@ -1,7 +1,4 @@
/*
* @(#)hppa.h 1.17 - 95/12/13
*
*
* Description:
*
* Definitions for HP PA Risc

View File

@@ -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.
/*PAGE
*
* _CPU_ISR_install_raw_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
*
*/
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;
/*
* This is unsupported. For HPPA this function is handled by BSP
*/
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;
/*
* 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;
_CPU_Fatal_halt( 0xdeaddead );
}
/*
* 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
*
* _CPU_ISR_Get_level
@@ -144,30 +79,12 @@ unsigned32 _CPU_ISR_Get_level(void)
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
*
* _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,156 +104,55 @@ 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;
register unsigned8 *fp_context;
int i;
proc_ptr old_handler;
/* mark them all unused */
DISABLE(~0);
DISMISS(~0);
/*
* XXX; need to setup fpsr smarter perhaps
*/
/* install the external interrupt handler */
_CPU_ISR_install_vector(
HPPA_INTERRUPT_EXTERNAL_INTERRUPT,
(proc_ptr)hppa_external_interrupt, &ignore
);
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 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.
@@ -351,8 +161,17 @@ hppa_external_interrupt(unsigned32 vector,
* 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);
}