forked from Imagelibrary/rtems
2008-07-10 Till Straumann <strauman@slac.stanford.edu>
* new-exceptions/bspsupport/ppc_exc_asm_macros.S, new-exceptions/bspsupport/ppc_exc_bspsupp.h, new-exceptions/bspsupport/ppc_exc_hdl.c, new-exceptions/bspsupport/vectors_init.c: fixed and enabled stack-switching algorithm which figures out if we already run on the ISR stack rather than relying on the _ISR_Nest_level. Added 'ppc_exc_crit_always_enabled' variable which defines the semantics of critical interrupts. Added a test to TEST_LOCK_crit so that calling ppc_exc_wrapup() (and possibly the dispatcher) is always skipped if the BSP/user wants to leave critical interrupts always enabled (at the expense of having no OS support). changed TEST_LOCK_mchk so that asynchronous machine-check handlers never call ppc_exc_wrapup() (and the dispatcher). We don't want to disable MSR_ME ever (to avoid checkstops) and hence asynchronous MEs must not use OS services anyways. added and commented new variables 'ppc_exc_intr_stack_size' 'ppc_exc_crit_always_enabled'.
This commit is contained in:
@@ -84,18 +84,21 @@
|
||||
* priority exceptions (HPE) (by disabling
|
||||
* them while the stack is switched).
|
||||
*/
|
||||
#if 0
|
||||
#if 1
|
||||
.macro SWITCH_STACK RA RB FLVR
|
||||
mfspr \RB, SPRG1
|
||||
cmplw cr0, r1, \RB
|
||||
bgt do_r1_reload_\FLVR
|
||||
lwz \RA, ppc_exc_intr_stack_size@sdarel(r13)
|
||||
subf \RB, \RB, \RA
|
||||
subf \RB, \RA, \RB
|
||||
cmplw cr0, r1, \RB
|
||||
bge no_r1_reload_\FLVR
|
||||
do_r1_reload_\FLVR:
|
||||
mfspr r1, SPRG1
|
||||
no_r1_reload_\FLVR:
|
||||
lwz \RA, _ISR_Nest_level@sdarel(r13)
|
||||
addi \RA, \RA, 1
|
||||
stw \RA, _ISR_Nest_level@sdarel(r13)
|
||||
.endm
|
||||
#else
|
||||
.macro SWITCH_STACK RA RB FLVR
|
||||
@@ -269,7 +272,7 @@ ppc_exc_min_prolog_sync_\_NAME:
|
||||
* ON EXIT: cr4 is set (indicates no lower-priority locks are engaged)
|
||||
*
|
||||
*/
|
||||
.macro TEST_LOCK_std _SRR0
|
||||
.macro TEST_LOCK_std _SRR0 _FLVR
|
||||
/* 'std' is lowest level, i.e., can not be locked -> EQ(cr4) = 1 */
|
||||
creqv EQ(cr4), EQ(cr4), EQ(cr4)
|
||||
.endm
|
||||
@@ -285,10 +288,16 @@ ppc_exc_min_prolog_sync_\_NAME:
|
||||
* critical-exception wrapper has to check 'std' lock:
|
||||
*
|
||||
* Return cr4 = ( ppc_std_lock == 0
|
||||
* && * _SRR0 != <write std lock instruction> )
|
||||
* && * _SRR0 != <write std lock instruction>
|
||||
* && ppc_exc_crit_always_enabled == 0 )
|
||||
*
|
||||
*/
|
||||
.macro TEST_LOCK_crit _SRR0
|
||||
.macro TEST_LOCK_crit _SRR0 _FLVR
|
||||
/* Are critical exceptions always enabled ? */
|
||||
lwz r4, ppc_exc_crit_always_enabled@sdarel(r13)
|
||||
cmpwi cr4, r4, 0
|
||||
bne cr4, TEST_LOCK_crit_done_\_FLVR
|
||||
|
||||
/* STD interrupt could have been interrupted before
|
||||
* executing the 1st instruction which sets the lock;
|
||||
* check this case by looking at the opcode present
|
||||
@@ -311,8 +320,10 @@ ppc_exc_min_prolog_sync_\_NAME:
|
||||
* && ppc_exc_lock_std == 0 )
|
||||
*/
|
||||
crandc EQ(cr4), EQ(cr0), EQ(cr4)
|
||||
TEST_LOCK_crit_done_\_FLVR:
|
||||
.endm
|
||||
|
||||
#if 0
|
||||
/*
|
||||
**********************************************************************
|
||||
* MACRO: TEST_LOCK_mchk
|
||||
@@ -328,7 +339,7 @@ ppc_exc_min_prolog_sync_\_NAME:
|
||||
* && ppc_std_lock == 0
|
||||
* && ppc_crit_lock == 0 )
|
||||
*/
|
||||
.macro TEST_LOCK_mchk _SRR0
|
||||
.macro TEST_LOCK_mchk _SRR0 _FLVR
|
||||
TEST_1ST_OPCODE_mchk _REG=r4 _SRR0=\_SRR0
|
||||
/* cr4 set if 1st opcode matches writing either lock */
|
||||
|
||||
@@ -343,6 +354,29 @@ ppc_exc_min_prolog_sync_\_NAME:
|
||||
*/
|
||||
crandc EQ(cr4), EQ(cr0), EQ(cr4)
|
||||
.endm
|
||||
#else
|
||||
/*
|
||||
**********************************************************************
|
||||
* MACRO: TEST_LOCK_mchk
|
||||
**********************************************************************
|
||||
*
|
||||
* USES: cr4
|
||||
* ON EXIT: cr4 is cleared.
|
||||
*
|
||||
* We never want to disable machine-check exceptions to avoid
|
||||
* a checkstop. This means that we cannot use enabling/disabling
|
||||
* this type of exception for protection of critical OS data structures.
|
||||
* Therefore, calling OS primitives from a machine-check handler
|
||||
* is ILLEGAL. Since machine-checks can happen anytime it is not
|
||||
* legal to perform a context switch (since the exception could
|
||||
* hit a IRQ protected section of code).
|
||||
* We simply let this test return 0 so that ppc_exc_wrapup is
|
||||
* never called after handling a machine-check.
|
||||
*/
|
||||
.macro TEST_LOCK_mchk _SRR0 _FLVR
|
||||
crxor EQ(cr4), EQ(cr4), EQ(cr4)
|
||||
.endm
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
@@ -409,7 +443,7 @@ wrap_no_save_r14_\_FLVR:
|
||||
stw r5, ppc_exc_lock_\_PRI@sdarel(r13)
|
||||
|
||||
/* test lower-priority locks; result in (non-volatile) cr4 */
|
||||
TEST_LOCK_\_PRI _SRR0=\_SRR0
|
||||
TEST_LOCK_\_PRI _SRR0=\_SRR0 _FLVR=\_FLVR
|
||||
|
||||
/* Peform stack switch if necessary */
|
||||
SWITCH_STACK RA=r4 RB=r5 FLVR=\_FLVR
|
||||
|
||||
@@ -56,6 +56,42 @@ extern uint32_t ppc_exc_msr_bits;
|
||||
*/
|
||||
extern uint32_t ppc_exc_msr_irq_mask;
|
||||
|
||||
/*
|
||||
* Cache size of the interrupt stack in a SDA variable
|
||||
*/
|
||||
extern uint32_t ppc_exc_intr_stack_size;
|
||||
|
||||
/*
|
||||
* This variable defines the semantics of asynchronous
|
||||
* critical exceptions ("critical interrupts")
|
||||
* on BookE-style CPUs.
|
||||
*
|
||||
* There are the following ways of using these interrupts
|
||||
*
|
||||
* 1) permanently disabled; no support
|
||||
* 2) permanently enabled; handlers for critical interrupts
|
||||
* MUST NOT use any RTEMS primitives at all. They cannot
|
||||
* directly e.g., release a semaphore.
|
||||
* 3) enabled/disabled by the OS during critical sections.
|
||||
* In this scenario critical interrupts are not much
|
||||
* different from 'normal' interrupts but handlers may
|
||||
* safely use RTEMS primitives (i.e., the subset which
|
||||
* is OK to use from ISR context).
|
||||
*
|
||||
* The BSP (or application) may initialize this
|
||||
* variable PRIOR to calling 'initialize_exceptions'
|
||||
* to any of the following values:
|
||||
*
|
||||
* NOTE: so far, OS_SUPPORT is not supported by the cpukit
|
||||
* yet since the IRQ/enabling-disabling primitives
|
||||
* do not mask MSR_CE yet.
|
||||
*/
|
||||
#define PPC_EXC_CRIT_NO_OS_SUPPORT 1
|
||||
#define PPC_EXC_CRIT_OS_SUPPORT 0
|
||||
#define PPC_EXC_CRIT_DISABLED (-1)
|
||||
|
||||
extern int32_t ppc_exc_crit_always_enabled;
|
||||
|
||||
/* (See README under CAVEATS). During initialization
|
||||
* a check is performed to assert that write-back
|
||||
* caching is enabled for memory accesses. If a BSP
|
||||
|
||||
@@ -53,6 +53,10 @@ uint32_t ppc_exc_msr_irq_mask = MSR_EE;
|
||||
*/
|
||||
uint32_t ppc_exc_msr_bits = MSR_IR | MSR_DR | MSR_RI;
|
||||
|
||||
uint32_t ppc_exc_intr_stack_size = 0;
|
||||
|
||||
int32_t ppc_exc_crit_always_enabled = PPC_EXC_CRIT_NO_OS_SUPPORT;
|
||||
|
||||
|
||||
/* Table of C-handlers */
|
||||
static ppc_exc_handler_t ppc_exc_handlers[LAST_VALID_EXC + 1] = {0, };
|
||||
|
||||
@@ -337,11 +337,29 @@ int n = sizeof(exception_table)/sizeof(exception_table[0]);
|
||||
/* Use current MMU / RI settings when running C exception handlers */
|
||||
ppc_exc_msr_bits = _read_MSR() & ( MSR_DR | MSR_IR | MSR_RI );
|
||||
|
||||
/* Cache size of the interrupt stack in a SDA variable */
|
||||
ppc_exc_intr_stack_size = rtems_configuration_get_interrupt_stack_size();
|
||||
|
||||
/* Copy into a SDA variable that is easy to access from
|
||||
* assembly code
|
||||
*/
|
||||
if ( ppc_cpu_is_bookE() ) {
|
||||
ppc_exc_msr_irq_mask = MSR_EE | MSR_CE | MSR_DE ;
|
||||
switch (ppc_exc_crit_always_enabled) {
|
||||
case PPC_EXC_CRIT_NO_OS_SUPPORT:
|
||||
_write_MSR(_read_MSR() | (MSR_CE | MSR_DE));
|
||||
break;
|
||||
|
||||
case PPC_EXC_CRIT_OS_SUPPORT:
|
||||
printk("ppc_exc: PPC_EXC_CRIT_OS_SUPPORT not yet implemented\n");
|
||||
/* fall thru */
|
||||
|
||||
case PPC_EXC_CRIT_DISABLED:
|
||||
default:
|
||||
ppc_exc_crit_always_enabled = PPC_EXC_CRIT_DISABLED;
|
||||
_write_MSR(_read_MSR() & ~(MSR_CE | MSR_DE));
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
ppc_exc_msr_irq_mask = MSR_EE ;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user