core_debug: Add an address trigger to stop logging at a given address

This compares the address being fetched with the contents of a
register that can be set via DMI, and if they match, stops the
logging.  Since this works on the address being fetched rather than
executed, it is subject to false positives.

Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
cache-tlb-parameters-2
Paul Mackerras 4 years ago
parent 5535257c71
commit 470f1b2140

@ -91,6 +91,7 @@ architecture behave of core_debug is
-- Log buffer address and data registers
constant DBG_CORE_LOG_ADDR : std_ulogic_vector(3 downto 0) := "0110";
constant DBG_CORE_LOG_DATA : std_ulogic_vector(3 downto 0) := "0111";
constant DBG_CORE_LOG_TRIGGER : std_ulogic_vector(3 downto 0) := "1000";

constant LOG_INDEX_BITS : natural := log2(LOG_LENGTH);

@ -108,6 +109,8 @@ architecture behave of core_debug is

signal log_dmi_addr : std_ulogic_vector(31 downto 0) := (others => '0');
signal log_dmi_data : std_ulogic_vector(63 downto 0) := (others => '0');
signal log_dmi_trigger : std_ulogic_vector(63 downto 0) := (others => '0');
signal do_log_trigger : std_ulogic := '0';
signal do_dmi_log_rd : std_ulogic;
signal dmi_read_log_data : std_ulogic;
signal dmi_read_log_data_1 : std_ulogic;
@ -133,6 +136,7 @@ begin
dbg_gpr_data when DBG_CORE_GSPR_DATA,
log_write_addr & log_dmi_addr when DBG_CORE_LOG_ADDR,
log_dmi_data when DBG_CORE_LOG_DATA,
log_dmi_trigger when DBG_CORE_LOG_TRIGGER,
(others => '0') when others;

-- DMI writes
@ -149,6 +153,9 @@ begin
stopping <= '0';
terminated <= '0';
else
if do_log_trigger = '1' then
log_dmi_trigger(1) <= '1';
end if;
-- Edge detect on dmi_req for 1-shot pulses
dmi_req_1 <= dmi_req;
if dmi_req = '1' and dmi_req_1 = '0' then
@ -180,6 +187,8 @@ begin
elsif dmi_addr = DBG_CORE_LOG_ADDR then
log_dmi_addr <= dmi_din(31 downto 0);
do_dmi_log_rd <= '1';
elsif dmi_addr = DBG_CORE_LOG_TRIGGER then
log_dmi_trigger <= dmi_din;
end if;
else
report("DMI read from " & to_string(dmi_addr));
@ -246,7 +255,7 @@ begin

begin
-- Use MSB of read addresses to stop the logging
log_wr_enable <= not (log_read_addr(31) or log_dmi_addr(31));
log_wr_enable <= not (log_read_addr(31) or log_dmi_addr(31) or log_dmi_trigger(1));

log_ram: process(clk)
begin
@ -285,6 +294,12 @@ begin
end if;
log_dmi_read_done <= log_dmi_reading;
log_dmi_reading <= do_dmi_log_rd;
do_log_trigger <= '0';
if log_data(42) = log_dmi_trigger(63) and
log_data(41 downto 0) = log_dmi_trigger(43 downto 2) and
log_dmi_trigger(0) = '1' then
do_log_trigger <= '1';
end if;
end if;
end process;
log_write_addr(LOG_INDEX_BITS - 1 downto 0) <= std_ulogic_vector(log_wr_ptr);

@ -44,6 +44,7 @@

#define DBG_LOG_ADDR 0x16
#define DBG_LOG_DATA 0x17
#define DBG_LOG_TRIGGER 0x18

static bool debug;

@ -466,8 +467,11 @@ static void gpr_read(uint64_t reg, uint64_t count)

static void mem_read(uint64_t addr, uint64_t count)
{
uint64_t data;
int i, rc;
union {
uint64_t data;
unsigned char c[8];
} u;
int i, j, rc;

rc = dmi_write(DBG_WB_CTRL, 0x7ff);
if (rc < 0)
@ -476,12 +480,15 @@ static void mem_read(uint64_t addr, uint64_t count)
if (rc < 0)
return;
for (i = 0; i < count; i++) {
rc = dmi_read(DBG_WB_DATA, &data);
rc = dmi_read(DBG_WB_DATA, &u.data);
if (rc < 0)
return;
printf("%016llx: %016llx\n",
printf("%016llx: %016llx ",
(unsigned long long)addr,
(unsigned long long)data);
(unsigned long long)u.data);
for (j = 0; j < 8; ++j)
putchar(u.c[j] >= 0x20 && u.c[j] < 0x7f? u.c[j]: '.');
putchar('\n');
addr += 8;
}
}
@ -622,6 +629,28 @@ static void log_dump(const char *filename)
check(dmi_write(DBG_LOG_ADDR, orig_laddr), "writing LOG_ADDR");
}

static void ltrig_show(void)
{
uint64_t trig;

check(dmi_read(DBG_LOG_TRIGGER, &trig), "reading LOG_TRIGGER");
if (trig & 1)
printf("log stop trigger at %" PRIx64, trig & ~3);
else
printf("log stop trigger disabled");
printf(", %striggered\n", (trig & 2? "": "not "));
}

static void ltrig_off(void)
{
check(dmi_write(DBG_LOG_TRIGGER, 0), "writing LOG_TRIGGER");
}

static void ltrig_set(uint64_t addr)
{
check(dmi_write(DBG_LOG_TRIGGER, (addr & ~(uint64_t)2) | 1), "writing LOG_TRIGGER");
}

static void usage(const char *cmd)
{
fprintf(stderr, "Usage: %s -b <jtag|sim> <command> <args>\n", cmd);
@ -651,6 +680,9 @@ static void usage(const char *cmd)
fprintf(stderr, " lstart start logging\n");
fprintf(stderr, " lstop stop logging\n");
fprintf(stderr, " ldump <file> dump log to file\n");
fprintf(stderr, " ltrig show logging stop trigger status\n");
fprintf(stderr, " ltrig off clear logging stop trigger address\n");
fprintf(stderr, " ltrig <addr> set logging stop trigger address\n");

fprintf(stderr, "\n");
fprintf(stderr, " JTAG:\n");
@ -801,9 +833,20 @@ int main(int argc, char *argv[])
usage(argv[0]);
filename = argv[++i];
log_dump(filename);
} else if (strcmp(argv[i], "ltrig") == 0) {
uint64_t addr;

if ((i+1) >= argc)
ltrig_show();
else if (strcmp(argv[++i], "off") == 0)
ltrig_off();
else {
addr = strtoul(argv[i], NULL, 16);
ltrig_set(addr);
}
} else {
fprintf(stderr, "Unknown command %s\n", argv[i]);
exit(1);
usage(argv[0]);
}
}
core_status();

Loading…
Cancel
Save