Skip to content

Commit

Permalink
impove support for ELA and halting-debug
Browse files Browse the repository at this point in the history
  • Loading branch information
algrant-arm committed Oct 5, 2021
1 parent 2b85fde commit 478ea29
Show file tree
Hide file tree
Showing 8 changed files with 327 additions and 22 deletions.
163 changes: 159 additions & 4 deletions coresight-tools/csscan.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
---
Copyright (C) ARM Ltd. 2018-2021. All rights reserved.
SPDX-License-Identifer: Apache 2.0
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Expand Down Expand Up @@ -179,6 +181,17 @@ def bits_set(w,m):
assert bits_set(0x011,{0:"x",2:"y",4:"z"}) == "x z"


def decode_one_hot(x,n):
bs = []
for i in range(n):
if bit(x,i):
bs.append(i)
if len(bs) == 1:
return str(bs[0])
else:
return "?%s" % str(bs)


class DevicePhy:
"""
Access a memory-mapped device
Expand Down Expand Up @@ -1045,6 +1058,8 @@ def show_coresight_device(self, d):
if (edprsr & 0x4) == 1:
print(" halted", end="")
if not core_powered_off:
midr = d.read32(0xD00)
print(" midr=0x%08x" % midr, end="")
pfr = d.read32x2(0xD24,0xD20) # EDPFR: External Debug Processor Feature Register
if True or o_verbose:
print(" pfr=0x%x" % (pfr), end="")
Expand Down Expand Up @@ -1193,10 +1208,21 @@ def show_coresight_device(self, d):
if rombase not in [0x0,0x2]:
print(" ROM:%#x" % rombase, end="")
elif d.is_arm_architecture(ARM_ARCHID_ELA):
rwidth = bits(devid,8,8)
print(" devid:0x%08x entries:%u" % (devid, (1<<rwidth)), end="")
devid1 = d.read32(0xFC4)
devid2 = d.read32(0xFC0)
ram_addr_width = bits(devid,8,8) # SRAM address width in bits, e.g. 6 bits => 64 entries
print(" devid:0x%08x entries:%u" % (devid, (1<<ram_addr_width)), end="")
print(" trace-format-%u" % bits(devid,4,4), end="")
if bits(devid,0,4):
print(" ATB", end="")
if bits(devid,16,4):
print(" COND_TRIG:%u" % bits(devid,16,5), end="")
if bits(devid,25,4) == 1:
print(" scrambler", end="")
print(" groupwidth=%u" % ((bits(devid1,8,8)+1)*8), end="")
print(" trigstates=%u" % bits(devid1,16,8), end="")
if bits(devid2,8,8):
print(" compwidth=%u" % ((bits(devid2,8,8)+1)*8), end="")
elif d.is_cti():
# CoreSight CTI (SoC400) or CoreSight CTI (SoC600) or core CTI
# n.b. SoC600 CTI is fixed at 4 channels
Expand Down Expand Up @@ -1262,8 +1288,45 @@ def show_coresight_device(self, d):
integration_regs = []

if d.is_arm_architecture_core():
# Core debug interface
pass
# Core debug interface: show the current status
dscr = d.read32(0x088)
dstatus = dscr & 0x3f
dstatus_str = {
0x1: "PE restarting",
0x2: "PE in non-debug state",
0x7: "breakpoint",
0x13: "external debug request",
0x1b: "halting step, normal",
0x1f: "halting step, exclusive",
0x23: "OS unlock catch",
0x27: "reset catch",
0x2b: "watchpoint",
0x2f: "HLT instruction",
0x33: "software access to debug register",
0x37: "exception catch",
0x3b: "halting step, no syndrome"
}
if dstatus in dstatus_str:
sd = dstatus_str[dstatus]
else:
sd = "status 0x%x?" % dstatus
print(" dscr: 0x%08x (%s)" % (dscr, sd))
print(" halting debug for bkpt/wpt/hlt (HDE): %s" % ["disabled","enabled"][bit(dscr,14)])
print(" secure debug (SDD): %s" % ["enabled","disabled"][bit(dscr,16)])
print(" access mode: %s" % ["normal","memory"][bit(dscr,20)])
if bit(dscr,25):
print(" pipeline advanced")
if bit(dscr,29):
print(" TX full")
if bit(dscr,30):
print(" RX full")
if dstatus != 2:
# in debug state (only), some other status fields are meaningful
print(" EL%u" % bits(dscr,8,2))
if not bit(dscr,18):
print(" Secure")
if bit(dscr,24):
print(" ITR empty")
elif d.is_arm_architecture(ARM_ARCHID_PMU):
pmcr = d.read32(0xE04)
print(" pmcr: 0x%08x" % pmcr)
Expand Down Expand Up @@ -1517,6 +1580,84 @@ def blist(pfx,bs,n=32,inv=False):
else:
# TBD show older ETMs
pass
elif d.is_arm_architecture(ARM_ARCHID_ELA):
n_trig_states = bits(devid1,16,8)
group_width = (bits(devid1,8,8)+1)*8
if bits(devid2,8,8):
comp_width = (bits(devid2,8,8)+1)*8
else:
comp_width = group_width
ctrl = d.read32(0x000)
timectrl = d.read32(0x004)
tssr = d.read32(0x008)
pta = d.read32(0x010)
print(" %s" % ["disabled (programming permitted)","enabled"][bit(ctrl,0)])
print(" PTA: output:0x%x trace:%u stopclock:%u trigout:0x%x" % (bits(pta,4,4), bit(pta,3), bit(pta,2), bits(pta,0,2)))
n_comp_words = comp_width // 32
def print_words(d, off, n):
for j in range(n):
w = n - 1 - j
print(" %08x" % (d.read32(off + (w*4))), end="")
# Show the rules for each trigger state. Each rule has a matching condition and an action.
for i in range(0,n_trig_states):
b = 0x100 + i*0x100
print(" trigger state #%u:" % i)
print(" group:%u ctrl:0x%08x" % (d.read32(b+0x100),d.read32(b+0x104)))
print(" ext: mask:%08x comp:%08x countcomp:%08x" % (d.read32(b+0x130),d.read32(b+0x134),d.read32(b+0x120)))
print(" mask:", end="")
print_words(d, b+0x140, n_comp_words)
print()
print(" comp:", end="")
print_words(d, b+0x180, n_comp_words)
print()
# Now show what happens when the trigger matches
ac = d.read32(b+0x10C)
print(" action:0x%08x (trace:%u stopclock:%u elaout:0x%x ctiout:0x%x) next:0x%x" % (ac,bit(ac,3),bit(ac,2),bits(ac,4,4),bits(ac,0,2),d.read32(b+0x108)))
print(" altaction:%08x altnext:0x%x" % (d.read32(b+0x114),d.read32(b+0x110)))
# Reading CTSR takes a snapshot into CCVR and CAVR
if o_show_sample:
ctsr = d.read32(0x020)
ccvr = d.read32(0x024)
cavr = d.read32(0x028)
print(" state:")
# Trigger state is one-hot in CTSR. ELA-500 TRM says that the trigger state is RAZ when CTRL.RUN=0, but it appears not to be
print(" %s" % ["tracing","stopped"][bit(ctsr,31)])
soh = bits(ctsr,0,n_trig_states)
print(" state:%s" % decode_one_hot(soh,n_trig_states))
print(" counter:0x%x" % ccvr)
print(" captid:0x%x" % d.read32(0x02C))
print(" RAM read:0x%08x write:0x%08x" % (d.read32(0x040), d.read32(0x48)))
if o_show_all_status:
# Show contents of trace SRAM: see ELA-500 2.4.4 "Trace SRAM format"
saved_rra = d.read32(0x040)
ram_addr_width = bits(devid,8,8) # SRAM address width in bits, e.g. 6 bits => 64 entries
n_ram_entries = 1 << ram_addr_width
n_group_words = group_width // 32
d.write_enable()
# Set RRA to the beginning of the internal RAM. "Writes to the RRA cause
# the trace SRAM data at this address to be transferred into the holding register.
# After the SRAM read data is transferred to the holding register,
# RRA increments by one."
d.write32(0x040,0)
# So if we read it back now, it would read back as 1.
# Read out whole captured lines from the RAM.
for i in range(n_ram_entries):
print(" %04x:" % i, end="")
# "The first read of the RRD after an RRA update returns the trace data header byte value"
header = d.read32(0x044)
print(" [%08x]" % header, end="")
rtype = bits(header,0,2) # timestamp or captured group
rstate = bits(header,2,3)
print(" st:%u" % rstate, end="") # trigger state shows what was traced, look at SIGSEL<rstate>
for j in range(n_group_words):
dat = d.read32(0x044) # automatically increments RRA
print(" %08x" % dat, end="")
print()
# After reading all the lines, the RRA is already 0, and reaing the last word via RRD
# causes the next line (i.e. the very first one) to be read to the holding register,
# and the RRA then auto-increments to 1. So that's what we expect to see here.
assert d.read32(0x040) == 0x0001, "RRA should have wrapped: 0x%08x" % d.read32(0x040)
d.write32(0x040,saved_rra)
elif d.is_arm_architecture(ARM_ARCHID_MEMAP):
idr = d.read32(0xDFC)
aptype = bits(idr,0,4)
Expand Down Expand Up @@ -1634,7 +1775,21 @@ def blist(pfx,bs,n=32,inv=False):
# CoreSight CTI or core CTI
n_trigs = (devid>>8) & 0xff
n_channels = (devid>>16) & 0xf
# Pulsed trigger inputs will generally read as 0. We could read the latched
# value from the integration-test input register, but that's destructive.
print(" CTI %s" % (["disabled","enabled"][bit(d.read32(0x000),0)]))
# Show the channel-to-trigger connections and the system gate
for c in range(0,n_channels):
cin = d.read32(0x020 + c*4)
cout = d.read32(0x0A0 + c*4)
if cin:
print(" channel #%u <- %s" % (c, binstr(cin,n_trigs)))
if cout:
print(" channel #%u -> %s" % (c, binstr(cout,n_trigs)))
print(" channel gate: %s" % (binstr(d.read32(0x140),n_channels)))
print(" trigger inputs: %s" % (binstr(d.read32(0x130),n_trigs)))
if o_show_sample:
print(" latched: %s" % (binstr(d.read32(0xEF8),n_trigs)))
print(" trigger outputs: %s" % (binstr(d.read32(0x134),n_trigs)))
print(" channel inputs: %s" % (binstr(d.read32(0x138),n_channels)))
print(" channel outputs: %s" % (binstr(d.read32(0x13C),n_channels)))
Expand Down
32 changes: 32 additions & 0 deletions include/cs_debug_halt.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,38 @@ typedef enum cs_debug_moe {
*/
int cs_debug_is_halted(cs_device_t dev, cs_debug_moe_t * reason);


/**
* Write a 32-bit value to the transfer register
*
* \param dev device descriptor for CPU
* \param data data to write
*/
int cs_debug_send32(cs_device_t dev, uint32_t data);

/**
* Write a 64-bit value to the transfer registers (ARMv8)
*
* \param dev device descriptor for CPU
* \param data data to write
*/
int cs_debug_send64(cs_device_t dev, uint64_t data);

/**
* Read a 32-bit value from the transfer register; ignore errors
*
* \param dev device descriptor for CPU
*/
uint32_t cs_debug_recv32(cs_device_t dev);

/**
* Read a 64-bit value from the transfer registers; ignore errors
*
* \param dev device descriptor for CPU
*/
uint64_t cs_debug_recv64(cs_device_t dev);


/**
* Attempt to check if a CPU is currently executing instructions.
* We do this by clearing a flag that is set by instruction execution
Expand Down
8 changes: 8 additions & 0 deletions include/cs_reg_access.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ unsigned short cs_device_part_number(cs_device_t dev);
*/
uint32_t cs_device_read(cs_device_t dev, unsigned int offset);

/** Read a 64-bit value from a pair of device registers
* \param dev device descriptor
* \param hioff register offset for high word
* \param looff register offset for low word
* \return value in the register pair
*/
uint64_t cs_device_read32x2(cs_device_t dev, unsigned int hioff, unsigned int looff);

/** Write a value to a device register.
*
* This should be used for normal configuration registers that are expected to
Expand Down
76 changes: 72 additions & 4 deletions include/csregisters.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ Common register definitions in the management group of all CoreSight devices
#define CS_DEVTYPE 0xFCC /**< CS Device Type register */
#define CS_DEVID 0xFC8 /**< CS Device ID register */
#define CS_DEVID1 0xFC4 /**< CS Device ID register 1 */
#define CS_DEVID0 0xFC0 /**< CS Device ID register 0 */
#define CS_DEVID2 0xFC0 /**< CS Device ID register 2 */
#define CS_DEVID0 0xFC0 /**< CS Device ID register 0 (old name) */

#define CS_DEVARCH 0xFBC /**< CS device architecture register */

Expand Down Expand Up @@ -691,16 +692,22 @@ The cross trigger matrix does not have any programmable elements so needs no reg
/* CTI */
#define CS_CTICONTROL 0x000 /**< CTI Control Register */
#define CS_CTICONTROL_GLBEN 0x00000001 /**< CTI CTRL bitfield (#CS_CTICONTROL): Enables or disables the ECT */
#define CS_CTIINTACK 0x010 /**< CTI Interrupt Acknowledge Register (SoC-600) */
#define CS_CTIAPPSET 0x014 /**< CTI Application Channel Trigger Set Register */
#define CS_CTIAPPCLEAR 0x018 /**< CTI Application Channel Trigger Clear Register */
#define CS_CTIAPPPULSE 0x01C /**< CTI Application Channel Pulse Register */
#define CS_CTIINEN(n) (0x020 + (n)*4) /**< CTI Input Trigger (n) to Channel Enable */
#define CS_CTIOUTEN(n) (0x0A0 + (n)*4) /**< CTI Channel to Output Trigger (n) Enable */
#define CS_CTITRIGINSTATUS 0x130 /**< CTI Trigger In Status Register */
#define CS_CTITRIGINSTATUS 0x130 /**< CTI Trigger In Status Register - for pulsed events, generally 0 */
#define CS_CTITRIGOUTSTATUS 0x134 /**< CTI Trigger Out Status Register */
#define CS_CTICHINSTATUS 0x138 /**< CTI Channel In Status Register */
#define CS_CTICHOUTSTATUS 0x13C /**< CTI Channel Out Status Register */
#define CS_CTIGATE 0x140 /**< Enable CTI Channel Gate Register */
#define CS_CTIITCHOUT 0xEE4 /**< CTI Integration Test Channel Output Register */
#define CS_CTIITTRIGOUT 0xEE8 /**< CTI Integration Test Trigger Output Register */
#define CS_CTIITCHIN 0xEF4 /**< CTI Integration Test Channel Input Register (latched) */
#define CS_CTIITTRIGIN 0xEF8 /**< CTI Integration Test Trigger Input Register (latched) */
#define CS_CTIITCTRL 0xF00 /**< CTI Integration Mode Control Register */

/** CTI Event channel enable bitfield values.
'OR' combine for multiple channel source/sink for event.
Expand Down Expand Up @@ -780,8 +787,8 @@ Register definitions and bitfield values for the Architecture v7 Cortex Core deb
/** @name DBGDRCR Bit Values
see #CS_DBGDRCR
@{*/
#define CS_DBGDRCR_HRQ 0x00000001 /**< Halt */
#define CS_DBGDRCR_RRQ 0x00000002 /**< Restart */
#define CS_DBGDRCR_HRQ 0x00000001 /**< Halt (not v8) */
#define CS_DBGDRCR_RRQ 0x00000002 /**< Restart (not v8) */
#define CS_DBGDRCR_CSE 0x00000004 /**< Clear Sticky Exceptions */
#define CS_DBGDRCR_CSPA 0x00000008 /**< Clear Sticky Pipeline Advance */
#define CS_DBGDRCR_CBRRQ 0x00000010 /**< Cancel Bus Requests */
Expand Down Expand Up @@ -907,6 +914,67 @@ Register definitions and bitfield values for MEM-AP devices.

/** @} */


/** @defgroup cs_ela CoreSight ELA registers
@ingroup reg_defs
Register definitions and bitfield values for ELA devices.
@{
*/

/* Control */
#define CS_ELA_CTRL 0x000 /**< Control register */
#define CS_ELA_CTRL_RUN 0x0001 /**< ELA enabled */
#define CS_ELA_CTRL_TRACE_BUSY 0x0002 /**< Trace busy (ELA-600) */
#define CS_ELA_TIMECTRL 0x004 /**< Timestamp control register */
#define CS_ELA_TSSR 0x008 /**< Trigger state select register */
#define CS_ELA_ATBCTRL 0x00C /**< ATB control (ELA-600) */
#define CS_ELA_ATBCTRL_ATID_VALUE 0x7F00 /**< Set ATID for ATB transactions */
#define CS_ELA_PTACTION 0x010 /**< Pre-trigger action register (use CS_ELA_ACTION fields) */
#define CS_ELA_AUXCTRL 0x014 /**< Auxiliary control (ELA-600) */
#define CS_ELA_CNTSEL 0x018 /**< Counter select (ELA-600) */

/* Current state */
#define CS_ELA_CTSR 0x020 /**< Current trigger state (RO) */
#define CS_ELA_CTSR_FINALSTATE 0x80000000 /**< Trigger states no longer advancing */
#define CS_ELA_CCVR 0x024 /**< Current counter value (RO; sampled by CTSR) */
#define CS_ELA_CAVR 0x028 /**< Current action value (RO; sampled by CTSR) */
#define CS_ELA_RDCAPTID 0x02C /**< Read captured transaction ID */
#define CS_ELA_RDCAPTIDEXT 0x030 /**< Read extended captured transaction ID (ELA-600) */

/* RAM */
#define CS_ELA_RRAR 0x040 /**< RAM read address */
#define CS_ELA_RRDR 0x044 /**< RAM read data */
#define CS_ELA_RWAR 0x048 /**< RAM write address */
#define CS_ELA_RWDR 0x04C /**< RAM write data */

/* Trigger state */
#define _ELATR(n,r) ((0x100*n)+r)
#define CS_ELA_SIGSEL(n) _ELATR(n,0x100) /**< Signal select */
#define CS_ELA_TRIGCTRL(n) _ELATR(n,0x104) /**< Trigger control */
#define CS_ELA_NEXTSTATE(n) _ELATR(n,0x108) /**< Next state */
#define CS_ELA_ACTION _ELATR(n,0x10C) /**< Action */
#define CS_ELA_ACTION_CTTRIGOUT 0x03 /**< Values to drive on CTTRIGOUT[1:0] */
#define CS_ELA_ACTION_STOPCLOCK 0x04 /**< Drive 1 on STOPCLOCK */
#define CS_ELA_ACTION_TRACE 0x08 /**< Trace active */
#define CS_ELA_ACTION_ELAOUTPUT 0xF0 /**< Values to drive on ELAOUTPUT[3:0] */
#define CS_ELA_ALTNEXTSTATE(n) _ELATR(n,0x110) /**< Alt next state */
#define CS_ALTACTION(n) _ELATR(n,0x114) /**< Alt action */
#define CS_COMPCTRL(n) _ELATR(n,0x118) /**< Comparator control (ELA-600) */
#define CS_ALTCOMPCTRL(n) _ELATR(n,0x11C) /**< Alt comparator control (ELA-600) */
#define CS_COUNTCOMP(n) _ELATR(n,0x120) /**< Counter compare */
#define CS_TWBSEL _ELATR(n,0x128) /**< Trace write byte select (ELA-600) */
#define CS_EXTMASK(n) _ELATR(n,0x130) /**< External mask */
#define CS_EXTMASK_CTTRIGIN 0x03 /**< Mask CTTRIGIN[1:0] signals */
#define CS_EXTMASK_EXTTRIG 0xFC /**< Mask EXTTRIG[5:0] signals */
#define CS_EXTCOMP(n) _ELATR(n,0x134) /**< External compare */
#define CS_QUALMASK(n) _ELATR(n,0x138) /**< Qualifier mask (ELA-600) */
#define CS_QUALCOMP(n) _ELATR(n,0x13C) /**< Qualifier compare (ELA-600) */
#define CS_SIGMASK(n) _ELATR(n,0x140) /**< Signal mask (first word) */
#define CS_SIGCOMP(n) _ELATR(n,0x180) /**< Signal compare (first word) */

/** @} */

/** @}*/

#endif /* included */
Expand Down
4 changes: 2 additions & 2 deletions source/cs_access_cmnfns.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ void _diagf(char const *s, ...)
va_list args;
va_start(args, s);
if (s[0] == '!') {
fprintf(stderr, "** csaccess: ");
++s;
fprintf(stderr, "** csaccess: ");
++s;
}
vfprintf(stderr, s, args);
va_end(args);
Expand Down
Loading

0 comments on commit 478ea29

Please sign in to comment.