diff options
author | Till Straumann <strauman@slac.stanford.edu> | 2008-07-10 21:31:06 +0000 |
---|---|---|
committer | Till Straumann <strauman@slac.stanford.edu> | 2008-07-10 21:31:06 +0000 |
commit | 8bac4851a68eb074fbdaa3b9be634b3bc4a7ba38 (patch) | |
tree | 08f7bcf7e7cc06884ad6d832b22df897b9db8d08 /c/src/lib/libcpu | |
parent | 2008-07-10 Till Straumann <strauman@slac.stanford.edu> (diff) | |
download | rtems-8bac4851a68eb074fbdaa3b9be634b3bc4a7ba38.tar.bz2 |
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'.
Diffstat (limited to 'c/src/lib/libcpu')
4 files changed, 99 insertions, 7 deletions
diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_asm_macros.h b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_asm_macros.h index e176735f77..4f66d91e54 100644 --- a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_asm_macros.h +++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_asm_macros.h @@ -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 diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_bspsupp.h b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_bspsupp.h index de805c9366..5c816ff86c 100644 --- a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_bspsupp.h +++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_bspsupp.h @@ -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 diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_hdl.c b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_hdl.c index 1426110019..ec0533e822 100644 --- a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_hdl.c +++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/ppc_exc_hdl.c @@ -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, }; diff --git a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/vectors_init.c b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/vectors_init.c index 86e2ca7c1f..dd80dd094d 100644 --- a/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/vectors_init.c +++ b/c/src/lib/libcpu/powerpc/new-exceptions/bspsupport/vectors_init.c @@ -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 ; } |