summaryrefslogtreecommitdiffstats
path: root/c
diff options
context:
space:
mode:
authorTill Straumann <strauman@slac.stanford.edu>2006-02-14 03:02:47 +0000
committerTill Straumann <strauman@slac.stanford.edu>2006-02-14 03:02:47 +0000
commit902a417d1977152ea2ce8406cd73eba40bad3a7a (patch)
tree9117678bcc227860fd1d00ddb03f11fee2cd3973 /c
parentBe less restrictive on picking up target tools to enable using rpm.specs for ... (diff)
downloadrtems-902a417d1977152ea2ce8406cd73eba40bad3a7a.tar.bz2
2006-02-13 Till Straumann <strauman@slac.stanford.edu>
* shared/startup/panic.c, shared/startup/probeMemEnd.c: added code for BSPs to use: panic using printk() to display reason. probeMemEnd() to determine memory size by probing.
Diffstat (limited to 'c')
-rw-r--r--c/src/lib/libbsp/powerpc/ChangeLog5
-rw-r--r--c/src/lib/libbsp/powerpc/shared/startup/panic.c122
-rw-r--r--c/src/lib/libbsp/powerpc/shared/startup/probeMemEnd.c182
3 files changed, 309 insertions, 0 deletions
diff --git a/c/src/lib/libbsp/powerpc/ChangeLog b/c/src/lib/libbsp/powerpc/ChangeLog
index 3715b53219..b614e98d72 100644
--- a/c/src/lib/libbsp/powerpc/ChangeLog
+++ b/c/src/lib/libbsp/powerpc/ChangeLog
@@ -1,3 +1,8 @@
+2006-02-13 Till Straumann <strauman@slac.stanford.edu>
+ * shared/startup/panic.c, shared/startup/probeMemEnd.c:
+ added code for BSPs to use: panic using printk() to display
+ reason. probeMemEnd() to determine memory size by probing.
+
2006-02-08 Joel Sherrill <joel@OARcorp.com>
* shared/startup/linkcmds: Add sections required by newer gcc versions.
diff --git a/c/src/lib/libbsp/powerpc/shared/startup/panic.c b/c/src/lib/libbsp/powerpc/shared/startup/panic.c
new file mode 100644
index 0000000000..e5fa57c0fb
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/shared/startup/panic.c
@@ -0,0 +1,122 @@
+#include <rtems.h>
+#include <bsp.h>
+#include <bsp/uart.h>
+#include <rtems/bspIo.h>
+#include <libcpu/stackTrace.h>
+
+static void
+rebootQuestion()
+{
+ printk("Press a key to reboot\n");
+ BSP_poll_char_via_serial();
+ rtemsReboot();
+}
+
+void BSP_panic(char *s)
+{
+ printk("%s PANIC %s\n",_RTEMS_version, s);
+ rebootQuestion();
+}
+
+#define THESRC Internal_errors_What_happened.the_source
+#define ISITNL Internal_errors_What_happened.is_internal
+#define THEERR Internal_errors_What_happened.the_error
+
+char *score_status_text(rtems_status_code sc)
+{
+ switch (sc) {
+ case INTERNAL_ERROR_NO_CONFIGURATION_TABLE:
+ return "INTERNAL_ERROR_NO_CONFIGURATION_TABLE";
+ case INTERNAL_ERROR_NO_CPU_TABLE:
+ return "INTERNAL_ERROR_NO_CPU_TABLE";
+ case INTERNAL_ERROR_INVALID_WORKSPACE_ADDRESS:
+ return "INTERNAL_ERROR_INVALID_WORKSPACE_ADDRESS";
+ case INTERNAL_ERROR_TOO_LITTLE_WORKSPACE:
+ return "INTERNAL_ERROR_TOO_LITTLE_WORKSPACE";
+ case INTERNAL_ERROR_WORKSPACE_ALLOCATION:
+ return "INTERNAL_ERROR_WORKSPACE_ALLOCATION";
+ case INTERNAL_ERROR_INTERRUPT_STACK_TOO_SMALL:
+ return "INTERNAL_ERROR_INTERRUPT_STACK_TOO_SMALL";
+ case INTERNAL_ERROR_THREAD_EXITTED:
+ return "INTERNAL_ERROR_THREAD_EXITTED";
+ case INTERNAL_ERROR_INCONSISTENT_MP_INFORMATION:
+ return "INTERNAL_ERROR_INCONSISTENT_MP_INFORMATION";
+ case INTERNAL_ERROR_INVALID_NODE:
+ return "INTERNAL_ERROR_INVALID_NODE";
+ case INTERNAL_ERROR_NO_MPCI:
+ return "INTERNAL_ERROR_NO_MPCI";
+ case INTERNAL_ERROR_BAD_PACKET:
+ return "INTERNAL_ERROR_BAD_PACKET";
+ case INTERNAL_ERROR_OUT_OF_PACKETS:
+ return "INTERNAL_ERROR_OUT_OF_PACKETS";
+ case INTERNAL_ERROR_OUT_OF_GLOBAL_OBJECTS:
+ return "INTERNAL_ERROR_OUT_OF_GLOBAL_OBJECTS";
+ case INTERNAL_ERROR_OUT_OF_PROXIES:
+ return "INTERNAL_ERROR_OUT_OF_PROXIES";
+ case INTERNAL_ERROR_INVALID_GLOBAL_ID:
+ return "INTERNAL_ERROR_INVALID_GLOBAL_ID";
+ case INTERNAL_ERROR_BAD_STACK_HOOK:
+ return "INTERNAL_ERROR_BAD_STACK_HOOK";
+ case INTERNAL_ERROR_BAD_ATTRIBUTES:
+ return "INTERNAL_ERROR_BAD_ATTRIBUTES";
+ case 18: /* not in header (yet) :-( */
+ return "INTERNAL_ERROR_CALLED_FROM_WRONG_ENVIRONMENT";
+ default:
+ break;
+ }
+ return 0;
+}
+
+void _BSP_Fatal_error(unsigned int v)
+{
+unsigned long flags;
+char *err = 0;
+
+ rtems_interrupt_disable(flags);
+ printk("%s\n",_RTEMS_version);
+ printk("FATAL ERROR:\n");
+ printk("Internal error: %s\n", ISITNL? "Yes":"No");
+ printk("Environment:");
+ switch (THESRC) {
+ case INTERNAL_ERROR_CORE:
+ printk(" RTEMS Core\n");
+ err = score_status_text(THEERR);
+ break;
+
+ case INTERNAL_ERROR_RTEMS_API:
+ printk(" RTEMS API\n");
+ err = rtems_status_text(THEERR);
+ break;
+
+ case INTERNAL_ERROR_POSIX_API:
+ printk(" POSIX API (errno)\n");
+ /* could use strerror but I'd rather avoid using this here */
+ break;
+
+ case INTERNAL_ERROR_ITRON_API:
+ printk(" ITRON API\n");
+ /* conversion to string not implemented */
+ break;
+
+ default:
+ printk(" UNKNOWN (0x%x)\n",THESRC);
+ break;
+ }
+ if ( _Thread_Dispatch_disable_level )
+ printk(" Error occurred in a Thread Dispatching DISABLED context (level %i)\n",
+ _Thread_Dispatch_disable_level);
+ else
+ printk("enabled\n");
+ if ( _ISR_Nest_level )
+ printk(" Error occurred from ISR context (ISR nest level %i)\n", _ISR_Nest_level);
+
+ printk("Error %d",THEERR);
+ if (err) {
+ printk(": %s",err);
+ }
+ printk("\n");
+ printk("Stack Trace:\n");
+ CPU_print_stack();
+
+ rebootQuestion();
+}
diff --git a/c/src/lib/libbsp/powerpc/shared/startup/probeMemEnd.c b/c/src/lib/libbsp/powerpc/shared/startup/probeMemEnd.c
new file mode 100644
index 0000000000..dea3947342
--- /dev/null
+++ b/c/src/lib/libbsp/powerpc/shared/startup/probeMemEnd.c
@@ -0,0 +1,182 @@
+/* $Id$ */
+#include <rtems.h>
+#include <libcpu/spr.h>
+#include <libcpu/cpuIdent.h>
+#include <rtems/bspIo.h>
+
+/* Till Straumann <straumanatslacdotstanforddotedu>, 2005 */
+
+/* Simple memory probing routine
+ *
+ * - call from MMU-disabled section to avoid having to
+ * set up mappings.
+ * NOTE: this implies WIMG = 0011
+ * - call AFTER image is at its destination and PRIOR
+ * to setting up the heap or using any memory beyond
+ * __rtems_end, i.e., the probing algorithm may safely
+ * tamper with memory > __rtems_end.
+ * - MUST lock caches since we're gonna hit space with
+ * no memory attached.
+ *
+ * ASSUMPTIONS:
+ * o image occupies addresses between 0..__rtems_end
+ * o memory size is a multiple of 1<<LD_MEM_PROBE_STEP
+ *
+ * CAVEATS:
+ * o all caches must be disabled or locked (some
+ * boards really don't like it if you try to
+ * cache physical addresses with nothing attached)
+ * and this is highly CPU dependent :-(...
+ *
+ * - RETURNS size of memory detected in bytes or 0 on
+ * error.
+ */
+
+/* declare as an array so the compiler doesn't generate
+ * a reloc to .sdata & friends
+ */
+extern uint32_t __rtems_end[];
+
+#ifndef LD_MEM_PROBE_STEP
+#define LD_MEM_PROBE_STEP (24) /* 16MB */
+#endif
+
+#define TAG 0xfeedcafe
+
+#define __DO_ALIGN(a, s) (((uint32_t)(a) + (s)-1) & ~((s)-1))
+#define __ALIGN(a) __DO_ALIGN(a, (1<<LD_MEM_PROBE_STEP))
+
+void __here_s_the_real_end();
+
+#define SWITCH_MSR(msr) \
+ asm volatile( \
+ " mtsrr1 %0 \n" \
+ " bl 1f \n" \
+ "1: mflr %0 \n" \
+ " addi %0, %0, 1f-1b \n"\
+ " mtsrr0 %0 \n" \
+ " sync \n" \
+ " rfi \n" \
+ "1: \n" \
+ : \
+ :"b"(msr) \
+ :"lr" \
+ )
+
+SPR_RW(L2CR)
+SPR_RW(L3CR)
+SPR_RO(PVR)
+SPR_RW(HID0)
+
+
+/* Shouldn't matter if the caches are enabled or not... */
+
+/* FIXME: This should go into libcpu, really... */
+int
+CPU_lockUnlockCaches(register int doLock)
+{
+register uint32_t v, x;
+ if ( _read_MSR() & MSR_VE ) {
+#define DSSALL 0x7e00066c /* dssall opcode */
+ asm volatile(" .long %0"::"i"(DSSALL));
+#undef DSSALL
+ }
+ asm volatile("sync");
+ switch ( _read_PVR()>>16 ) {
+ default: printk(__FILE__" CPU_lockUnlockCaches(): unknown CPU (PVR = 0x%08x)\n",_read_PVR());
+ return -1;
+ case PPC_750: printk("CPU_lockUnlockCaches(): Can't lock L2 on a mpc750, sorry :-(\n");
+ return -2; /* cannot lock L2 :-( */
+ case PPC_7455:
+ case PPC_7457:
+ v = _read_L3CR();
+ x = 1<<(31-9);
+ v = doLock ? v | x : v & ~x;
+ _write_L3CR(v);
+
+ v = _read_L2CR();
+ x = 1<<(31-11);
+ v = doLock ? v | x : v & ~x;
+ _write_L2CR(v);
+ break;
+
+ case PPC_7400:
+ v = _read_L2CR();
+ x = 1<<(31-21);
+ v = doLock ? v | x : v & ~x;
+ _write_L2CR(v);
+ break;
+ case PPC_603:
+ case PPC_604:
+ case PPC_604e:
+ break;
+ }
+
+ v = _read_HID0();
+ x = 1<<(31-19);
+ v = doLock ? v | x : v & ~x;
+ _write_HID0(v);
+ asm volatile("sync");
+ return 0;
+}
+
+uint32_t
+probeMemoryEnd()
+{
+register volatile uint32_t *probe;
+register uint32_t scratch;
+register uint32_t tag = TAG;
+register uint32_t flags;
+
+ probe = (volatile uint32_t *)__ALIGN(__rtems_end);
+
+ /* Start with some checks. We avoid using any services
+ * such as 'printk' so we can run at a very early stage.
+ * Also, we *try* to avoid to really rely on the memory
+ * being unused by restoring the probed locations and
+ * keeping everything in registers. Hence we could
+ * even probe our own stack :-)
+ */
+
+ /* are we really at the highest address ? */
+ if ( probe < (volatile uint32_t *)__here_s_the_real_end ) {
+ probe = (volatile uint32_t*)__ALIGN(__here_s_the_real_end);
+ }
+
+ if ( CPU_lockUnlockCaches(1) )
+ return 0;
+
+ asm volatile("mfmsr %0":"=r"(flags));
+
+ SWITCH_MSR( flags & ~(MSR_EE|MSR_DR|MSR_IR) );
+
+ for ( ; (uint32_t)probe ; probe += (1<<LD_MEM_PROBE_STEP)/sizeof(*probe) ) {
+
+ /* see if by chance our tag is already there */
+ if ( tag == (scratch = *probe) ) {
+ /* try another tag */
+ tag = ~tag;
+ }
+ *probe = tag;
+
+ /* make sure it's written out */
+ asm volatile ("sync");
+
+ /* try to read back */
+ if ( tag != *probe ) {
+ break;
+ }
+ /* restore */
+ *probe = scratch;
+ /* make sure the icache is not contaminated */
+ asm volatile ("sync; icbi 0, %0"::"r"(probe));
+ }
+
+ SWITCH_MSR(flags);
+
+ CPU_lockUnlockCaches(0);
+
+ return (uint32_t) probe;
+}
+
+void __here_s_the_real_end() {}