summaryrefslogtreecommitdiff
path: root/acsr/v7_c.c
diff options
context:
space:
mode:
Diffstat (limited to 'acsr/v7_c.c')
-rw-r--r--acsr/v7_c.c273
1 files changed, 273 insertions, 0 deletions
diff --git a/acsr/v7_c.c b/acsr/v7_c.c
new file mode 100644
index 0000000..9f8cc11
--- /dev/null
+++ b/acsr/v7_c.c
@@ -0,0 +1,273 @@
+/*
+ * Copyright (c) 2011, ARM Limited. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with
+ * or without modification, are permitted provided that the
+ * following conditions are met:
+ *
+ * Redistributions of source code must retain the above
+ * copyright notice, this list of conditions and the
+ * following disclaimer.
+ *
+ * Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and
+ * the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * Neither the name of ARM nor the names of its
+ * contributors may be used to endorse or promote products
+ * derived from this software without specific prior written
+ * permission.
+ */
+
+/*
+ * The code to save and restore debug context uses the memory-mapped interface.
+ * The registers that are saved are enough to support a self-hosted debugger,
+ * but a different approach should be taken with an external debugger (cp14).
+ */
+
+#include "appf_types.h"
+#include "appf_internals.h"
+#include "appf_helpers.h"
+
+#define DIDR_VERSION_SHIFT 16
+#define DIDR_VERSION_MASK 0xF
+#define DIDR_VERSION_7_1 5
+#define DIDR_BP_SHIFT 24
+#define DIDR_BP_MASK 0xF
+#define DIDR_WP_SHIFT 28
+#define DIDR_WP_MASK 0xF
+#define CLAIMCLR_CLEAR_ALL 0xff
+
+#define DRAR_VALID_MASK 0x00000003
+#define DSAR_VALID_MASK 0x00000003
+#define DRAR_ADDRESS_MASK 0xFFFFF000
+#define DSAR_ADDRESS_MASK 0xFFFFF000
+#define OSLSR_OSLM_MASK 0x00000009
+#define OSLAR_UNLOCKED 0x00000000
+#define OSLAR_LOCKED 0xC5ACCE55
+#define LAR_UNLOCKED 0xC5ACCE55
+#define LAR_LOCKED 0x00000000
+#define OSDLR_UNLOCKED 0x00000000
+#define OSDLR_LOCKED 0x00000001
+
+typedef volatile struct
+{ /* Registers Save? */
+ appf_u32 const didr; /* 0 Read only */
+ appf_u32 dscr_i; /* 1 ignore - use dscr_e instead */
+ appf_u32 const dummy1[3]; /* 2-4 ignore */
+ appf_u32 dtrrx_dtrtx_i; /* 5 ignore */
+ appf_u32 wfar; /* 6 ignore - transient information */
+ appf_u32 vcr; /* 7 Save */
+ appf_u32 const dummy2; /* 8 ignore */
+ appf_u32 ecr; /* 9 ignore */
+ appf_u32 dsccr; /* 10 ignore */
+ appf_u32 dsmcr; /* 11 ignore */
+ appf_u32 const dummy3[20]; /* 12-31 ignore */
+ appf_u32 dtrrx_e; /* 32 ignore */
+ appf_u32 itr_pcsr; /* 33 ignore */
+ appf_u32 dscr_e; /* 34 Save */
+ appf_u32 dtrtx_e; /* 35 ignore */
+ appf_u32 drcr; /* 36 ignore */
+ appf_u32 eacr; /* 37 Save - V7.1 only */
+ appf_u32 const dummy4[2]; /* 38-39 ignore */
+ appf_u32 pcsr; /* 40 ignore */
+ appf_u32 cidsr; /* 41 ignore */
+ appf_u32 vidsr; /* 42 ignore */
+ appf_u32 const dummy5[21]; /* 43-63 ignore */
+ appf_u32 bvr[16]; /* 64-79 Save */
+ appf_u32 bcr[16]; /* 80-95 Save */
+ appf_u32 wvr[16]; /* 96-111 Save */
+ appf_u32 wcr[16]; /* 112-127 Save */
+ appf_u32 const dummy6[16]; /* 128-143 ignore */
+ appf_u32 bxvr[16]; /* 144-159 Save if have Virtualization extensions */
+ appf_u32 const dummy7[32]; /* 160-191 ignore */
+ appf_u32 oslar; /* 192 If oslsr[0] is 1, unlock before save/restore */
+ appf_u32 const oslsr; /* 193 ignore */
+ appf_u32 ossrr; /* 194 ignore */
+ appf_u32 const dummy8; /* 195 ignore */
+ appf_u32 prcr; /* 196 ignore */
+ appf_u32 prsr; /* 197 clear SPD on restore */
+ appf_u32 const dummy9[762]; /* 198-959 ignore */
+ appf_u32 itctrl; /* 960 ignore */
+ appf_u32 const dummy10[39]; /* 961-999 ignore */
+ appf_u32 claimset; /* 1000 Restore claim bits to here */
+ appf_u32 claimclr; /* 1001 Save claim bits from here */
+ appf_u32 const dummy11[2]; /* 1002-1003 ignore */
+ appf_u32 lar; /* 1004 Unlock before restore */
+ appf_u32 const lsr; /* 1005 ignore */
+ appf_u32 const authstatus; /* 1006 Read only */
+ appf_u32 const dummy12; /* 1007 ignore */
+ appf_u32 const devid2; /* 1008 Read only */
+ appf_u32 const devid1; /* 1009 Read only */
+ appf_u32 const devid; /* 1010 Read only */
+ appf_u32 const devtype; /* 1011 Read only */
+ appf_u32 const pid[8]; /* 1012-1019 Read only */
+ appf_u32 const cid[4]; /* 1020-1023 Read only */
+} debug_registers_t;
+
+typedef struct
+{
+ appf_u32 vcr;
+ appf_u32 dscr_e;
+ appf_u32 eacr;
+ appf_u32 bvr[16];
+ appf_u32 bcr[16];
+ appf_u32 wvr[16];
+ appf_u32 wcr[16];
+ appf_u32 bxvr[16];
+ appf_u32 claim;
+} debug_context_t; /* total size 86 * 4 = 344 bytes */
+
+debug_registers_t *read_debug_address(void)
+{
+ unsigned drar, dsar;
+
+ drar = read_drar();
+ dsar = read_dsar();
+
+ if (!(drar & DRAR_VALID_MASK)
+ || !(dsar & DSAR_VALID_MASK))
+ {
+ return 0; /* No memory-mapped debug on this processor */
+ }
+
+ return (debug_registers_t *)((drar & DRAR_ADDRESS_MASK)
+ + (dsar & DSAR_ADDRESS_MASK));
+}
+
+/*
+ * We assume that before save (and after restore):
+ * - OSLAR is NOT locked, or the debugger would not work properly
+ * - LAR is locked, because the ARM ARM says it must be
+ * - OSDLR is NOT locked, or the debugger would not work properly
+ */
+
+void save_v7_debug(appf_u32 *context)
+{
+ debug_registers_t *dbg = (void*)read_debug_address();
+ debug_context_t *ctx = (void*)context;
+ unsigned v71, num_bps, num_wps, i;
+ appf_u32 didr;
+
+ if (!dbg)
+ {
+ return;
+ }
+
+ didr = dbg->didr;
+ /*
+ * Work out what version of debug we have
+ */
+ v71 = (((didr >> DIDR_VERSION_SHIFT) & DIDR_VERSION_MASK) == DIDR_VERSION_7_1);
+
+ /*
+ * Save all context to memory
+ */
+ ctx->vcr = dbg->vcr;
+ ctx->dscr_e = dbg->dscr_e;
+ ctx->claim = dbg->claimclr;
+
+ if (v71)
+ {
+ ctx->eacr = dbg->eacr;
+ }
+
+ num_bps = 1 + ((didr >> DIDR_BP_SHIFT) & DIDR_BP_MASK);
+ for (i=0; i<num_bps; ++i)
+ {
+ ctx->bvr[i] = dbg->bvr[i];
+ ctx->bcr[i] = dbg->bcr[i];
+#ifdef VIRTUALIZATION
+ ctx->bxvr[i] = dbg->bxvr[i]; /* TODO: don't save the ones that don't exist */
+#endif
+ }
+
+ num_wps = 1 + ((didr >> DIDR_WP_SHIFT) & DIDR_WP_MASK);
+ for (i=0; i<num_wps; ++i)
+ {
+ ctx->wvr[i] = dbg->wvr[i];
+ ctx->wcr[i] = dbg->wcr[i];
+ }
+
+ /*
+ * If Debug V7.1, we must set osdlr (by cp14 interface) before power down.
+ * Once we have done this, debug becomes inaccessible.
+ */
+ if (v71)
+ {
+ write_osdlr(OSDLR_LOCKED);
+ }
+}
+
+void restore_v7_debug(appf_u32 *context)
+{
+ debug_registers_t *dbg = (void*)read_debug_address();
+ debug_context_t *ctx = (void*)context;
+ unsigned v71, num_bps, num_wps, i;
+ appf_u32 didr;
+
+ if (!dbg)
+ {
+ return;
+ }
+
+ didr = dbg->didr;
+ /*
+ * Work out what version of debug we have
+ */
+ v71 = (((didr >> DIDR_VERSION_SHIFT) & DIDR_VERSION_MASK) == DIDR_VERSION_7_1);
+
+ /* Enable write access to registers */
+ dbg->lar = LAR_UNLOCKED;
+ /*
+ * If Debug V7.1, we must unset osdlr (by cp14 interface) before restoring.
+ * (If the CPU has not actually power-cycled, osdlr may not be reset).
+ */
+ if (v71)
+ {
+ write_osdlr(OSDLR_UNLOCKED);
+ }
+
+ /*
+ * Restore all context from memory
+ */
+ dbg->vcr = ctx->vcr;
+ dbg->claimclr = CLAIMCLR_CLEAR_ALL;
+ dbg->claimset = ctx->claim;
+
+ if (v71)
+ {
+ dbg->eacr = ctx->eacr;
+ }
+
+ num_bps = 1 + ((didr >> DIDR_BP_SHIFT) & DIDR_BP_MASK);
+ for (i=0; i<num_bps; ++i)
+ {
+ dbg->bvr[i] = ctx->bvr[i];
+ dbg->bcr[i] = ctx->bcr[i];
+#ifdef VIRTUALIZATION
+ dbg->bxvr[i] = ctx->bxvr[i]; /* TODO: don't restore the ones that don't exist */
+#endif
+ }
+
+ num_wps = 1 + ((didr >> DIDR_WP_SHIFT) & DIDR_WP_MASK);
+ for (i=0; i<num_wps; ++i)
+ {
+ dbg->wvr[i] = ctx->wvr[i];
+ dbg->wcr[i] = ctx->wcr[i];
+ }
+
+ /* Clear PRSR.SPD by reading PRSR */
+ if (!v71)
+ {
+ (dbg->prsr);
+ }
+
+ /* Re-enable debug */
+ dbg->dscr_e = ctx->dscr_e;
+
+ /* Disable write access to registers */
+ dbg->lar = LAR_LOCKED;
+}
+