Help add patch for openocd in cortex_a a8 a9 watchpoint~~

how to implement in cortex_a.c ?

////

in cortex_m.h

#define DWT_COMP0 0xE0001020

#define DWT_MASK0 0xE0001024

#define DWT_FUNCTION0 0xE0001028

//

in cortex_m.c

for (i = 0; i < cm->dwt_num_comp; i++, comparator++)

{

int j;

comparator->dwt_comparator_address = DWT_COMP0 + 0x10 * i;

for (j = 0; j < 3; j++, reg++)

cortex_m_dwt_addreg(target, cache->reg_list + reg, dwt_comp + 3 * i + j);

target_write_u32(target, comparator->dwt_comparator_address + 8, 0);

}

//do add watchpoint

comparator->comp = watchpoint->address;

target_write_u32(target, comparator->dwt_comparator_address + 0, comparator->comp);

comparator->mask = mask;

target_write_u32(target, comparator->dwt_comparator_address + 4, comparator->mask);

switch (watchpoint->rw)

{

case WPT_READ:

comparator->function = 5;

break;

case WPT_WRITE:

comparator->function = 6;

break;

case WPT_ACCESS:

comparator->function = 7;

break;

}

target_write_u32(target, comparator->dwt_comparator_address + 8, comparator->function);

////////////////////////////

in armv7a.h for cortex a8 a9

#define CPUDBG_WVR_BASE 0x180

#define CPUDBG_WCR_BASE 0x1C0

how to implement in cortex_a.c ?

  1. the address/mask/function is CPUDBG_WVR_BASE+0 / CPUDBG_WVR_BASE+4 / CPUDBG_WVR_BASE+8 ?

  2. the address/mask/function is CPUDBG_WCR_BASE+0 …+4…+8?

  3. WPT_READ/WPT_WRITE/WPT_ACCESS is 5/6/7 on cortex a8 a9?

ok may a little idea here

break

http://infocenter.arm.com/help/index.js … cdabj.html

watch

http://infocenter.arm.com/help/index.js … hjfhh.html

looks

break point reg / watch point reg

Breakpoint address mask = Watchpoint address mask

Secure state access control = Secure state access control

Byte address select = Byte address select

sp =sp

B = W

only implement watch point L/S → Load store access

good~~~ will do it right~~~

//ok done

you need use eclipse into GDB HARDWARE DEBUGGING console key in

After trigger watchpoint you must remove again or will be looping trigger

monitor wp address sizeof(unit) r/w/a(read/write/access)

ex:

//add wtahcpoint on 0x8144be4c sizeof(unsigned int) access

monitor wp 0x8144be4c 4 a

monitor wp 0x8144be4c 4 w

//remove wtahcpoint on 0x8144be4c

monitor rwp 0x8144be4c

patch

http://fatalfeel.blogspot.tw/2015/12/op … el-of.html

demo photo:

https://picasaweb.google.com/1061855410 … 8141165858

int cortex_a_set_watchpoint(struct target *target, struct watchpoint *watchpoint)

{

int retval;

int wrp_i = 0;

uint32_t control;

uint8_t access_mode;

uint8_t byte_addr_select = 0x0F;

struct cortex_a_common* cortex_a = target_to_cortex_a(target);

struct armv7a_common* armv7a = &cortex_a->armv7a_common;

struct cortex_a_wrp* wrp_list = cortex_a->wrp_list;

if (watchpoint->set)

{

LOG_WARNING(“breakpoint already set”);

return ERROR_OK;

}

while (wrp_list[wrp_i].used && (wrp_i < cortex_a->wrp_num))

wrp_i++;

if (wrp_i >= cortex_a->wrp_num)

{

LOG_ERROR(“ERROR Can not find free Watchpoint Register Pair”);

return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;

}

watchpoint->set = wrp_i + 1;

if (watchpoint->length == 2)

byte_addr_select = (3 << (watchpoint->address & 0x02));

access_mode = watchpoint->rw+1;

control = (byte_addr_select << 5) | (access_mode << 3) | (3 << 1) | 1;

wrp_list[wrp_i].used = 1;

wrp_list[wrp_i].value = (watchpoint->address & 0xFFFFFFFC);

wrp_list[wrp_i].control = control;

retval = cortex_a_dap_write_memap_register_u32(target,

armv7a->debug_base + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].WRPn,

wrp_list[wrp_i].value);

if (retval != ERROR_OK)

return retval;

retval = cortex_a_dap_write_memap_register_u32(target,

armv7a->debug_base + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].WRPn,

wrp_list[wrp_i].control);

if (retval != ERROR_OK)

return retval;

return ERROR_OK;

}

int cortex_a_unset_watchpoint(struct target *target, struct watchpoint *watchpoint)

{

int retval;

struct cortex_a_common *cortex_a = target_to_cortex_a(target);

struct armv7a_common *armv7a = &cortex_a->armv7a_common;

struct cortex_a_wrp *wrp_list = cortex_a->wrp_list;

if (!watchpoint->set)

{

LOG_WARNING(“watchpoint not set”);

return ERROR_OK;

}

int wrp_i = watchpoint->set - 1;

if ((wrp_i < 0) || (wrp_i >= cortex_a->wrp_num))

{

LOG_DEBUG(“Invalid BRP number in watchpoint”);

return ERROR_OK;

}

LOG_DEBUG(“rbp %i control 0x%0” PRIx32 " value 0x%0" PRIx32, wrp_i, wrp_list[wrp_i].control, wrp_list[wrp_i].value);

wrp_list[wrp_i].used = 0;

wrp_list[wrp_i].value = 0;

wrp_list[wrp_i].control = 0;

retval = cortex_a_dap_write_memap_register_u32(target,

armv7a->debug_base + CPUDBG_WCR_BASE + 4 * wrp_list[wrp_i].WRPn,

wrp_list[wrp_i].control);

if (retval != ERROR_OK)

return retval;

retval = cortex_a_dap_write_memap_register_u32(target,

armv7a->debug_base + CPUDBG_WVR_BASE + 4 * wrp_list[wrp_i].WRPn,

wrp_list[wrp_i].value);

if (retval != ERROR_OK)

return retval;

watchpoint->set = 0;

return ERROR_OK;

}

int cortex_a_add_watchpoint(struct target *target, struct watchpoint *watchpoint)

{

struct cortex_a_common* cortex_a = target_to_cortex_a(target);

if (cortex_a->wrp_num_available < 1)

{

LOG_INFO(“no hardware breakpoint available”);

return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;

}

//if (breakpoint->type == BKPT_HARD)

cortex_a->wrp_num_available–;

return cortex_a_set_watchpoint(target, watchpoint);

}

int cortex_a_remove_watchpoint(struct target *target, struct watchpoint *watchpoint)

{

struct cortex_a_common* cortex_a = target_to_cortex_a(target);

if (watchpoint->set)

{

//if (breakpoint->type == BKPT_HARD)

cortex_a_unset_watchpoint(target, watchpoint);

cortex_a->wrp_num_available++;

}

return ERROR_OK;

}

struct target_type cortexa_target = {

.name = “cortex_a”,

.deprecated_name = “cortex_a8”,

.poll = cortex_a_poll,

.arch_state = armv7a_arch_state,

.halt = cortex_a_halt,

.resume = cortex_a_resume,

.step = cortex_a_step,

.assert_reset = cortex_a_assert_reset,

.deassert_reset = cortex_a_deassert_reset,

/* REVISIT allow exporting VFP3 registers … */

.get_gdb_reg_list = arm_get_gdb_reg_list,

.read_memory = cortex_a_read_memory,

.write_memory = cortex_a_write_memory,

.checksum_memory = arm_checksum_memory,

.blank_check_memory = arm_blank_check_memory,

.run_algorithm = armv4_5_run_algorithm,

.add_breakpoint = cortex_a_add_breakpoint,

.add_context_breakpoint = cortex_a_add_context_breakpoint,

.add_hybrid_breakpoint = cortex_a_add_hybrid_breakpoint,

.remove_breakpoint = cortex_a_remove_breakpoint,

.add_watchpoint = cortex_a_add_watchpoint,

.remove_watchpoint = cortex_a_remove_watchpoint,

.commands = cortex_a_command_handlers,

.target_create = cortex_a_target_create,

.init_target = cortex_a_init_target,

.examine = cortex_a_examine,

.read_phys_memory = cortex_a_read_phys_memory,

.write_phys_memory = cortex_a_write_phys_memory,

.mmu = cortex_a_mmu,

.virt2phys = cortex_a_virt2phys,

};

static int cortex_a_examine_first(struct target *target)

{

struct cortex_a_common *cortex_a = target_to_cortex_a(target);

struct armv7a_common *armv7a = &cortex_a->armv7a_common;

struct adiv5_dap *swjdp = armv7a->arm.dap;

int i;

int retval = ERROR_OK;

uint32_t didr, ctypr, ttypr, cpuid, dbg_osreg;

/* We do one extra read to ensure DAP is configured,

  • we call ahbap_debugport_init(swjdp) instead

*/

retval = ahbap_debugport_init(swjdp);

if (retval != ERROR_OK)

return retval;

/* Search for the APB-AB - it is needed for access to debug registers */

retval = dap_find_ap(swjdp, AP_TYPE_APB_AP, &armv7a->debug_ap);

if (retval != ERROR_OK) {

LOG_ERROR(“Could not find APB-AP for debug access”);

return retval;

}

/* Search for the AHB-AB */

retval = dap_find_ap(swjdp, AP_TYPE_AHB_AP, &armv7a->memory_ap);

if (retval != ERROR_OK)

{

/* AHB-AP not found - use APB-AP */

LOG_DEBUG(“Could not find AHB-AP - using APB-AP for memory access”);

armv7a->memory_ap_available = false;

}

else

{

armv7a->memory_ap_available = true;

}

if (!target->dbgbase_set) {

uint32_t dbgbase;

/* Get ROM Table base */

uint32_t apid;

int32_t coreidx = target->coreid;

LOG_DEBUG(“%s’s dbgbase is not set, trying to detect using the ROM table”,

target->cmd_name);

retval = dap_get_debugbase(swjdp, 1, &dbgbase, &apid);

if (retval != ERROR_OK)

return retval;

/* Lookup 0x15 – Processor DAP */

retval = dap_lookup_cs_component(swjdp, 1, dbgbase, 0x15,

&armv7a->debug_base, &coreidx);

if (retval != ERROR_OK) {

LOG_ERROR(“Can’t detect %s’s dbgbase from the ROM table; you need to specify it explicitly.”,

target->cmd_name);

return retval;

}

LOG_DEBUG(“Detected core %” PRId32 " dbgbase: %08" PRIx32,

coreidx, armv7a->debug_base);

} else

armv7a->debug_base = target->dbgbase;

retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,

armv7a->debug_base + CPUDBG_CPUID, &cpuid);

if (retval != ERROR_OK)

return retval;

retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,

armv7a->debug_base + CPUDBG_CPUID, &cpuid);

if (retval != ERROR_OK) {

LOG_DEBUG(“Examine %s failed”, “CPUID”);

return retval;

}

retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,

armv7a->debug_base + CPUDBG_CTYPR, &ctypr);

if (retval != ERROR_OK) {

LOG_DEBUG(“Examine %s failed”, “CTYPR”);

return retval;

}

retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,

armv7a->debug_base + CPUDBG_TTYPR, &ttypr);

if (retval != ERROR_OK) {

LOG_DEBUG(“Examine %s failed”, “TTYPR”);

return retval;

}

retval = mem_ap_sel_read_atomic_u32(swjdp,

armv7a->debug_ap,

armv7a->debug_base + CPUDBG_DIDR,

&didr);

if (retval != ERROR_OK)

{

LOG_DEBUG(“Examine %s failed”, “DIDR”);

return retval;

}

LOG_DEBUG(“cpuid = 0x%08” PRIx32, cpuid);

LOG_DEBUG(“ctypr = 0x%08” PRIx32, ctypr);

LOG_DEBUG(“ttypr = 0x%08” PRIx32, ttypr);

LOG_DEBUG(“didr = 0x%08” PRIx32, didr);

cortex_a->cpuid = cpuid;

cortex_a->ctypr = ctypr;

cortex_a->ttypr = ttypr;

cortex_a->didr = didr;

/* Unlocking the debug registers */

if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT ==

CORTEX_A15_PARTNUM) {

retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,

armv7a->debug_base + CPUDBG_OSLAR,

0);

if (retval != ERROR_OK)

return retval;

}

/* Unlocking the debug registers */

if ((cpuid & CORTEX_A_MIDR_PARTNUM_MASK) >> CORTEX_A_MIDR_PARTNUM_SHIFT ==

CORTEX_A7_PARTNUM) {

retval = mem_ap_sel_write_atomic_u32(swjdp, armv7a->debug_ap,

armv7a->debug_base + CPUDBG_OSLAR,

0);

if (retval != ERROR_OK)

return retval;

}

retval = mem_ap_sel_read_atomic_u32(swjdp, armv7a->debug_ap,

armv7a->debug_base + CPUDBG_PRSR, &dbg_osreg);

if (retval != ERROR_OK)

return retval;

LOG_DEBUG(“target->coreid %” PRId32 " DBGPRSR 0x%" PRIx32, target->coreid, dbg_osreg);

armv7a->arm.core_type = ARM_MODE_MON;

retval = cortex_a_dpm_setup(cortex_a, didr);

if (retval != ERROR_OK)

return retval;

/* Setup Breakpoint Register Pairs */

cortex_a->brp_num = ((didr >> 24) & 0x0F) + 1;

cortex_a->brp_num_context = ((didr >> 20) & 0x0F) + 1;

cortex_a->brp_num_available = cortex_a->brp_num;

free(cortex_a->brp_list);

cortex_a->brp_list = calloc(cortex_a->brp_num, sizeof(struct cortex_a_brp));

/* cortex_a->brb_enabled = ???; */

for (i = 0; i < cortex_a->brp_num; i++)

{

cortex_a->brp_list*.used = 0;*

  • if (i < (cortex_a->brp_num-cortex_a->brp_num_context))*
    cortex_a->brp_list.type = BRP_NORMAL;
    * else*
    cortex_a->brp_list.type = BRP_CONTEXT;
    cortex_a->brp_list.value = 0;
    cortex_a->brp_list.control = 0;
    cortex_a->brp_list.BRPn = i;
    * }*
    * LOG_DEBUG(“Configured %i hw breakpoints”, cortex_a->brp_num);
    _//////////////////////////////////////////////////////////////////////////////////////_
    cortex_a->wrp_num = ((didr >> 28) & 0x0F) + 1;
    cortex_a->wrp_num_available = cortex_a->wrp_num;
    free(cortex_a->wrp_list);
    cortex_a->wrp_list = calloc(cortex_a->wrp_num, sizeof(struct cortex_a_wrp));
    for (i = 0; i < cortex_a->wrp_num; i++)
    _ {_
    cortex_a->wrp_list.used = 0;
    cortex_a->wrp_list.value = 0;
    cortex_a->wrp_list.control = 0;
    cortex_a->wrp_list.WRPn = i;
    _ }_
    LOG_DEBUG(“Configured %i hw watchpoints”, cortex_a->wrp_num);
    target_set_examined(target);
    return ERROR_OK;
    _}
    *_

struct cortex_a_wrp

{

int used;

uint32_t value;

uint32_t control;

uint8_t WRPn;

};

struct cortex_a_common

{

int common_magic;

struct arm_jtag jtag_info;

/* Context information */

uint32_t cpudbg_dscr;

/* Saved cp15 registers */

uint32_t cp15_control_reg;

/* latest cp15 register value written and cpsr processor mode */

uint32_t cp15_control_reg_curr;

enum arm_mode curr_mode;

/* Breakpoint register pairs */

int brp_num_context;

int brp_num;

int brp_num_available;

struct cortex_a_brp *brp_list;

int wrp_num;

int wrp_num_available;

struct cortex_a_wrp* wrp_list;

/* Use cortex_a_read_regs_through_mem for fast register reads */

int fast_reg_read;

uint32_t cpuid;

uint32_t ctypr;

uint32_t ttypr;

uint32_t didr;

struct armv7a_common armv7a_common;

};

int arm_dpm_setup(struct arm_dpm *dpm)

{

struct arm *arm = dpm->arm;

struct target *target = arm->target;

struct reg_cache *cache;

arm->dpm = dpm;

/* register access setup */

arm->full_context = arm_dpm_full_context;

arm->read_core_reg = arm_dpm_read_core_reg;

arm->write_core_reg = arm_dpm_write_core_reg;

cache = arm_build_reg_cache(target, arm);

if (!cache)

return ERROR_FAIL;

*register_get_last_cache_p(&target->reg_cache) = cache;

/* coprocessor access setup */

arm->mrc = dpm_mrc;

arm->mcr = dpm_mcr;

/* breakpoint setup – optional until it works everywhere */

if (!target->type->add_breakpoint)

{

target->type->add_breakpoint = dpm_add_breakpoint;

target->type->remove_breakpoint = dpm_remove_breakpoint;

}

/* watchpoint setup */

if (!target->type->add_watchpoint)

{

target->type->add_watchpoint = dpm_add_watchpoint;

target->type->remove_watchpoint = dpm_remove_watchpoint;

}

/* FIXME add vector catch support */

dpm->nbp = 1 + ((dpm->didr >> 24) & 0xf);

dpm->dbp = calloc(dpm->nbp, sizeof *dpm->dbp);

dpm->nwp = 1 + ((dpm->didr >> 28) & 0xf);

dpm->dwp = calloc(dpm->nwp, sizeof *dpm->dwp);

if (!dpm->dbp || !dpm->dwp) {

free(dpm->dbp);

free(dpm->dwp);

return ERROR_FAIL;

}

LOG_INFO(“%s: hardware has %d breakpoints, %d watchpoints”,

target_name(target), dpm->nbp, dpm->nwp);

/* REVISIT … and some of those breakpoints could match

  • execution context IDs…

*/

return ERROR_OK;

}