2007-12-10 Till Straumann <strauman@slac.stanford.edu>

* new-exceptions/bspsupport/README,
	new-exceptions/bspsupport/ppc_exc_bspsupp.h
	new-exceptions/bspsupport/vectors_init.c:
	added crude test to make sure MMU maps memory as
	write-back enabled.
This commit is contained in:
Till Straumann
2007-12-11 05:18:06 +00:00
parent 7c86d66b78
commit 59a4066e01
4 changed files with 99 additions and 15 deletions

View File

@@ -1,3 +1,11 @@
2007-12-10 Till Straumann <strauman@slac.stanford.edu>
* new-exceptions/bspsupport/README,
new-exceptions/bspsupport/ppc_exc_bspsupp.h
new-exceptions/bspsupport/vectors_init.c:
added crude test to make sure MMU maps memory as
write-back enabled.
2007-12-09 Till Straumann <strauman@slac.stanford.edu>
* new-exceptions/bspsupport/ppc_exc_test.c,

View File

@@ -242,6 +242,34 @@ USAGE
to 'libbsp_a_LIBADD'
CAVEATS
=======
On classic PPCs, early (and late) parts of the low-level
exception handling code run with the MMU disabled which mean
that the default caching attributes (write-back) are in effect
(thanks to Thomas Doerfler for bringing this up).
The code currently assumes that the MMU translations
for the task and interrupt stacks as well as some
variables in the data-area MATCH THE DEFAULT CACHING
ATTRIBUTES (this assumption also holds for the old code
in libbsp/powepc/shared/vectors ../irq).
During initialization of exception handling, a crude test
is performed to check if memory seems to have the write-back
attribute. The 'dcbz' instruction should - on most PPCs - cause
an alignment exception if the tested cache-line does not
have this attribute.
BSPs which entirely disable caching (e.g., by physically
disabling the cache(s)) should set the variable
ppc_exc_cache_wb_check = 0
prior to calling initialize_exceptions().
Note that this check does not catch all possible
misconfigurations (e.g., on the 860, the default attribute
is AFAIK [libcpu/powerpc/mpc8xx/mmu/mmu_init.c] set to
'caching-disabled' which is potentially harmful but
this situation is not detected).
RACE CONDITION WHEN DEALING WITH CRITICAL INTERRUPTS

View File

@@ -46,6 +46,18 @@ extern uint32_t ppc_exc_msr_bits;
*/
extern uint32_t ppc_exc_msr_irq_mask;
/* (See README under CAVEATS). During initialization
* a check is performed to assert that write-back
* caching is enabled for memory accesses. If a BSP
* runs entirely without any caching then it should
* set this variable to zero prior to initializing
* exceptions in order to skip the test.
* NOTE: The code does NOT support mapping memory
* with cache-attributes other than write-back
* (unless the entire cache is physically disabled)
*/
extern uint32_t ppc_exc_cache_wb_check;
/*
* Hook C exception handlers.
* - handlers for asynchronous exceptions run on the ISR stack

View File

@@ -26,6 +26,8 @@
static rtems_raw_except_global_settings exception_config;
static rtems_raw_except_connect_data exception_table[LAST_VALID_EXC + 1];
uint32_t ppc_exc_cache_wb_check = 1;
#if 0
typedef struct ppc_exc_connect_data_ {
rtems_raw_except_connect_data raw;
@@ -105,25 +107,26 @@ void C_exception_handler(BSP_Exception_frame* excPtr)
{
int recoverable = 0;
int synch = (int)excPtr->_EXC_number >= 0 ;
unsigned n = excPtr->_EXC_number & 0x7fff;
printk("Exception handler called for exception %d\n", excPtr->_EXC_number & 0x7fff);
printk("\t Next PC or Address of fault = %x\n", excPtr->EXC_SRR0);
printk("\t Saved MSR = %x\n", excPtr->EXC_SRR1);
printk("\t R0 = %08x", excPtr->GPR0);
printk("Exception handler called for exception %d (0x%x)\n", n, n);
printk("\t Next PC or Address of fault = %08x\n", excPtr->EXC_SRR0);
printk("\t Saved MSR = %08x\n", excPtr->EXC_SRR1);
printk("\t R0 = %08x", excPtr->GPR0);
if ( synch ) {
printk(" R1 = %08x", excPtr->GPR1);
printk(" R2 = %08x", excPtr->GPR2);
printk(" R1 = %08x", excPtr->GPR1);
printk(" R2 = %08x", excPtr->GPR2);
} else {
printk(" ");
printk(" ");
}
printk(" R3 = %08x\n", excPtr->GPR3);
printk("\t R4 = %08x", excPtr->GPR4);
printk(" R5 = %08x", excPtr->GPR5);
printk(" R6 = %08x", excPtr->GPR6);
printk(" R7 = %08x\n", excPtr->GPR7);
printk("\t R8 = %08x", excPtr->GPR8);
printk(" R9 = %08x", excPtr->GPR9);
printk(" R3 = %08x\n", excPtr->GPR3);
printk("\t R4 = %08x", excPtr->GPR4);
printk(" R5 = %08x", excPtr->GPR5);
printk(" R6 = %08x", excPtr->GPR6);
printk(" R7 = %08x\n", excPtr->GPR7);
printk("\t R8 = %08x", excPtr->GPR8);
printk(" R9 = %08x", excPtr->GPR9);
printk(" R10 = %08x", excPtr->GPR10);
printk(" R11 = %08x\n", excPtr->GPR11);
printk("\t R12 = %08x", excPtr->GPR12);
@@ -150,10 +153,10 @@ void C_exception_handler(BSP_Exception_frame* excPtr)
} else {
printk("\n");
}
printk("\t CR = %08x\n", excPtr->EXC_CR);
printk("\t CR = %08x\n", excPtr->EXC_CR);
printk("\t CTR = %08x\n", excPtr->EXC_CTR);
printk("\t XER = %08x\n", excPtr->EXC_XER);
printk("\t LR = %08x\n", excPtr->EXC_LR);
printk("\t LR = %08x\n", excPtr->EXC_LR);
/* Would be great to print DAR but unfortunately,
* that is not portable across different CPUs.
@@ -346,4 +349,37 @@ int n = sizeof(exception_table)/sizeof(exception_table[0]);
for ( i=0; i<n; i++ )
exception_table[i].hdl.vector = i;
ppc_exc_init(exception_table, n);
/* If we are on a classic PPC with MSR_DR enabled then
* assert that the mapping for at least this task's
* stack is write-back-caching enabled (see README/CAVEATS)
* Do this only if the cache is physically enabled.
* Since it is not easy to figure that out in a
* generic way we need help from the BSP: BSPs
* which run entirely w/o the cache may set
* ppc_exc_cache_wb_check to zero prior to calling
* this routine.
*
* We run this check only after exception handling is
* initialized so that we have some chance to get
* information printed if it fails.
*
* Note that it is unsafe to ignore this issue; if
* the check fails, do NOT disable it unless caches
* are always physically disabled.
*/
if ( ppc_exc_cache_wb_check && (MSR_DR & ppc_exc_msr_bits) ) {
/* The size of 63 assumes cache lines are at most 32 bytes */
uint8_t dummy[63];
uintptr_t p = (uintptr_t)dummy;
/* If the dcbz instruction raises an alignment exception
* then the stack is mapped as write-thru or caching-disabled.
* The low-level code is not capable of dealing with this
* ATM.
*/
p = (p + 31) & ~31;
asm volatile("dcbz 0, %0"::"b"(p));
/* If we make it thru here then things seem to be OK */
}
}