forked from Imagelibrary/rtems
libdebugger/arm: Support ROM tables.
- Parse the ROM taables if present to find the component base for the debug hardware. This lets the RPi2 run dl09.exe.
This commit is contained in:
@@ -26,6 +26,8 @@
|
||||
|
||||
#define TARGET_DEBUG 0
|
||||
|
||||
#define ARM_DUMP_ROM_TABLES 0
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
@@ -548,10 +550,278 @@ arm_debug_cp14_enable(rtems_debugger_target* target)
|
||||
static jmp_buf unlock_abort_jmpbuf;
|
||||
static size_t arm_debug_retries;
|
||||
|
||||
static void
|
||||
arm_debug_dump_rom_table(uint32_t* rom, size_t depth)
|
||||
{
|
||||
uint32_t pidr[7];
|
||||
uint32_t cidr[4];
|
||||
uint32_t memtype;
|
||||
uint32_t pidr4_4KB_count;
|
||||
size_t r;
|
||||
|
||||
static const char *table_class[16] = {
|
||||
"reserved",
|
||||
"ROM table",
|
||||
"reserved", "reserved",
|
||||
"reserved",
|
||||
"reserved",
|
||||
"reserved",
|
||||
"reserved",
|
||||
"reserved",
|
||||
"CoreSight component",
|
||||
"reserved",
|
||||
"Peripheral Test Block",
|
||||
"reserved",
|
||||
"OptimoDE DESS",
|
||||
"Generic IP component",
|
||||
"PrimeCell or System component"
|
||||
};
|
||||
|
||||
#define ROM_READ(b_, o_, r_) b_[((o_) / sizeof(uint32_t)) + (r_)]
|
||||
|
||||
if (depth > 16) {
|
||||
rtems_debugger_printf("]] rom: too deep\n");
|
||||
return;
|
||||
}
|
||||
|
||||
for (r = 0; r < 4; ++r)
|
||||
pidr[r] = ROM_READ(rom, 0xfe0, r) & 0xff;
|
||||
for (r = 0; r < 3; ++r)
|
||||
pidr[r + 4] = ROM_READ(rom, 0xfd0, r) & 0xff;
|
||||
for (r = 0; r < 4; ++r)
|
||||
cidr[r] = ROM_READ(rom, 0xff0, r) & 0xff;
|
||||
memtype = ROM_READ(rom, 0xfcc, 0);
|
||||
|
||||
pidr4_4KB_count = pidr[4] & (((1 << (7 - 4)) - 1) >> 4);
|
||||
|
||||
rtems_debugger_printf("]] rom = %p\n", rom);
|
||||
rtems_debugger_printf(" PIDR: %08x %08x %08x %08x %08x %08x %08x\n",
|
||||
pidr[0], pidr[1], pidr[2], pidr[3],
|
||||
pidr[4], pidr[5], pidr[6]);
|
||||
rtems_debugger_printf(" CIDR: %08x %08x %08x %08x\n",
|
||||
cidr[0], cidr[1], cidr[2], cidr[3]);
|
||||
rtems_debugger_printf(" 4KB count: %u\n", pidr4_4KB_count);
|
||||
|
||||
if ((memtype & 0x01) != 0)
|
||||
rtems_debugger_printf(" MEMTYPE sys memory present on bus\n");
|
||||
else
|
||||
rtems_debugger_printf(" MEMTYPE sys memory not present: dedicated debug bus\n");
|
||||
|
||||
/*
|
||||
* Read ROM table entries until we get 0
|
||||
*/
|
||||
for (r = 0; rom[r] != 0; ++r) {
|
||||
uint32_t romentry = rom[r];
|
||||
uint32_t c_pidr[7];
|
||||
uint32_t c_cidr[4];
|
||||
uint32_t* c_base;
|
||||
uint32_t table_type;
|
||||
size_t i;
|
||||
|
||||
c_base = (uint32_t*) ((intptr_t) rom + (romentry & 0xFFFFF000));
|
||||
|
||||
/*
|
||||
* Read the IDs.
|
||||
*/
|
||||
for (i = 0; i < 4; ++i)
|
||||
c_pidr[i] = ROM_READ(c_base, 0xfe0, i) & 0xff;
|
||||
for (i = 0; i < 3; ++i)
|
||||
c_pidr[i + 4] = ROM_READ(c_base, 0xfd0, i) & 0xff;
|
||||
for (i = 0; i < 4; ++i)
|
||||
c_cidr[i] = ROM_READ(c_base, 0xff0, i) & 0xff;
|
||||
|
||||
table_type = ROM_READ(c_base, 0xfcc, 0);
|
||||
|
||||
rtems_debugger_printf(" > Base: %p, start: 0x%" PRIx32 "\n",
|
||||
c_base,
|
||||
/* component may take multiple 4K pages */
|
||||
(uint32_t)((intptr_t) c_base - 0x1000 * (c_pidr[4] >> 4)));
|
||||
rtems_debugger_printf(" Class is 0x%x, %s\n",
|
||||
(c_cidr[1] >> 4) & 0xf, table_class[(c_cidr[1] >> 4) & 0xf]);
|
||||
|
||||
if (((c_cidr[1] >> 4) & 0x0f) == 1) {
|
||||
arm_debug_dump_rom_table(c_base, depth + 1);
|
||||
}
|
||||
else if (((c_cidr[1] >> 4) & 0x0f) == 9) {
|
||||
const char* major = "reserved";
|
||||
const char* subtype = "reserved";
|
||||
unsigned minor = (table_type >> 4) & 0x0f;
|
||||
|
||||
switch (table_type & 0x0f) {
|
||||
case 0:
|
||||
major = "Miscellaneous";
|
||||
switch (minor) {
|
||||
case 0:
|
||||
subtype = "other";
|
||||
break;
|
||||
case 4:
|
||||
subtype = "Validation component";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
major = "Trace Sink";
|
||||
switch (minor) {
|
||||
case 0:
|
||||
subtype = "other";
|
||||
break;
|
||||
case 1:
|
||||
subtype = "Port";
|
||||
break;
|
||||
case 2:
|
||||
subtype = "Buffer";
|
||||
break;
|
||||
case 3:
|
||||
subtype = "Router";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
major = "Trace Link";
|
||||
switch (minor) {
|
||||
case 0:
|
||||
subtype = "other";
|
||||
break;
|
||||
case 1:
|
||||
subtype = "Funnel, router";
|
||||
break;
|
||||
case 2:
|
||||
subtype = "Filter";
|
||||
break;
|
||||
case 3:
|
||||
subtype = "FIFO, buffer";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
major = "Trace Source";
|
||||
switch (minor) {
|
||||
case 0:
|
||||
subtype = "other";
|
||||
break;
|
||||
case 1:
|
||||
subtype = "Processor";
|
||||
break;
|
||||
case 2:
|
||||
subtype = "DSP";
|
||||
break;
|
||||
case 3:
|
||||
subtype = "Engine/Coprocessor";
|
||||
break;
|
||||
case 4:
|
||||
subtype = "Bus";
|
||||
break;
|
||||
case 6:
|
||||
subtype = "Software";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
major = "Debug Control";
|
||||
switch (minor) {
|
||||
case 0:
|
||||
subtype = "other";
|
||||
break;
|
||||
case 1:
|
||||
subtype = "Trigger Matrix";
|
||||
break;
|
||||
case 2:
|
||||
subtype = "Debug Auth";
|
||||
break;
|
||||
case 3:
|
||||
subtype = "Power Requestor";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 5:
|
||||
major = "Debug Logic";
|
||||
switch (minor) {
|
||||
case 0:
|
||||
subtype = "other";
|
||||
break;
|
||||
case 1:
|
||||
subtype = "Processor";
|
||||
break;
|
||||
case 2:
|
||||
subtype = "DSP";
|
||||
break;
|
||||
case 3:
|
||||
subtype = "Engine/Coprocessor";
|
||||
break;
|
||||
case 4:
|
||||
subtype = "Bus";
|
||||
break;
|
||||
case 5:
|
||||
subtype = "Memory";
|
||||
}
|
||||
break;
|
||||
case 6:
|
||||
major = "Perfomance Monitor";
|
||||
switch (minor) {
|
||||
case 0:
|
||||
subtype = "other";
|
||||
break;
|
||||
case 1:
|
||||
subtype = "Processor";
|
||||
break;
|
||||
case 2:
|
||||
subtype = "DSP";
|
||||
break;
|
||||
case 3:
|
||||
subtype = "Engine/Coprocessor";
|
||||
break;
|
||||
case 4:
|
||||
subtype = "Bus";
|
||||
break;
|
||||
case 5:
|
||||
subtype = "Memory";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
rtems_debugger_printf(" Type: 0x%02" PRIx32 ", %s, %s\n",
|
||||
table_type & 0xff, major, subtype);
|
||||
rtems_debugger_printf(" PID[4..0]: %02x %02x %02x %02x %02x\n",
|
||||
c_pidr[4], c_pidr[3], c_pidr[2], c_pidr[1], c_pidr[0]);
|
||||
|
||||
if (((c_cidr[1] >> 4) & 0x0f) == 1) {
|
||||
arm_debug_dump_rom_table(c_base, depth + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
arm_debug_rom_discover(uint32_t* rom, uint32_t comp, uint32_t** addr, int* index)
|
||||
{
|
||||
size_t r = 0;
|
||||
*addr = 0;
|
||||
while ((rom[r] & 1) != 0) {
|
||||
uint32_t* c_base = (uint32_t*) ((intptr_t) rom + (rom[r] & 0xfffff000));
|
||||
uint32_t c_cid1 = c_base[0xff4 / sizeof(uint32_t)];
|
||||
uint32_t type;
|
||||
if (((c_cid1 >> 4) & 0x0f) == 1) {
|
||||
if (arm_debug_rom_discover(c_base, comp, addr, index))
|
||||
return true;
|
||||
}
|
||||
type = c_base[0xfcc / sizeof(uint32_t)] & 0xff;
|
||||
if (comp == type) {
|
||||
if (*index > 0)
|
||||
--(*index);
|
||||
else {
|
||||
*addr = c_base;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
++r;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static int
|
||||
arm_debug_mmap_enable(rtems_debugger_target* target, uint32_t dbgdidr)
|
||||
{
|
||||
uint32_t rom;
|
||||
uint32_t val;
|
||||
void* abort_handler;
|
||||
int rc = -1;
|
||||
@@ -562,15 +832,29 @@ arm_debug_mmap_enable(rtems_debugger_target* target, uint32_t dbgdidr)
|
||||
arm_debug_retries = 5;
|
||||
|
||||
/*
|
||||
* The DBGDSAR is a signed offset from DBGDRAR. Both need to be
|
||||
* valid for the debug register address to be valid. Currently there
|
||||
* is no support to decode a ROM table.
|
||||
* The DBGDSAR (DSAR) is a signed offset from DBGDRAR. Both need to
|
||||
* be valid for the debug register address to be valid. Read the
|
||||
* DBGRAR first.
|
||||
*/
|
||||
ARM_CP14_READ(rom, 1, 0, 0);
|
||||
if ((rom & 3) == 3) {
|
||||
ARM_CP14_READ(val, 2, 0, 0);
|
||||
if ((val & 3) == 3 ) {
|
||||
debug_registers = (void*) ((rom & ~3) + ((int32_t) (val & ~3)));
|
||||
ARM_CP14_READ(val, 1, 0, 0);
|
||||
if ((val & 3) == 3) {
|
||||
uint32_t* rom = (uint32_t*) (val & 0xfffff000);
|
||||
uint32_t* comp_base = NULL;
|
||||
int core = (int) _SMP_Get_current_processor();
|
||||
|
||||
if (ARM_DUMP_ROM_TABLES)
|
||||
arm_debug_dump_rom_table(rom, 0);
|
||||
|
||||
debug_registers = NULL;
|
||||
|
||||
if (arm_debug_rom_discover(rom, 0x15, &comp_base, &core)) {
|
||||
debug_registers = comp_base;
|
||||
rtems_debugger_printf("rtems-db: ram debug: ROM Base: %p\n", comp_base);
|
||||
} else {
|
||||
ARM_CP14_READ(val, 2, 0, 0);
|
||||
if ((val & 3) == 3 ) {
|
||||
debug_registers = (void*) ((intptr_t) rom + (val & ~3));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -580,6 +864,7 @@ arm_debug_mmap_enable(rtems_debugger_target* target, uint32_t dbgdidr)
|
||||
rtems_debugger_printf("rtems-db: arm debug: no valid register map\n");
|
||||
return -1;
|
||||
}
|
||||
rtems_debugger_printf("rtems-db: arm debug: BSP Base: %p\n", debug_registers);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Reference in New Issue
Block a user