Skip to content

Commit

Permalink
mips32: add micromips breakpoints support
Browse files Browse the repository at this point in the history
Breakpoint setting based on length (kind) only.
Added 16bit aligned 32bit software breakpoints
support and same filtering before setting
breakpoint.
Set the required isa bit in hardware breakpoints.
Drop the isa bit in software breakpoints.

Change-Id: I7020f27be16015194b76f385d9b8e5af496d0dfc
Signed-off-by: Salvador Arroyo <[email protected]>
Reviewed-on: http://openocd.zylin.com/4124
Tested-by: jenkins
Reviewed-by: Freddie Chopin <[email protected]>
  • Loading branch information
Salvador Arroyo authored and FreddieChopin committed May 8, 2017
1 parent 4831ce4 commit b702b16
Showing 1 changed file with 105 additions and 46 deletions.
151 changes: 105 additions & 46 deletions src/target/mips_m4k.c
Original file line number Diff line number Diff line change
Expand Up @@ -631,6 +631,11 @@ static int mips_m4k_set_breakpoint(struct target *target,
comparator_list[bp_num].used = 1;
comparator_list[bp_num].bp_value = breakpoint->address;

if (breakpoint->length != 4) /* make sure isa bit set */
comparator_list[bp_num].bp_value |= 1;
else /* make sure isa bit cleared */
comparator_list[bp_num].bp_value &= ~1;

/* EJTAG 2.0 uses 30bit IBA. First 2 bits are reserved.
* Warning: there is no IB ASID registers in 2.0.
* Do not set it! :) */
Expand All @@ -648,41 +653,77 @@ static int mips_m4k_set_breakpoint(struct target *target,
bp_num, comparator_list[bp_num].bp_value);
} else if (breakpoint->type == BKPT_SOFT) {
LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id);
if (breakpoint->length == 4) {

uint32_t isa_req = breakpoint->length & 1; /* micro mips request bit */
uint32_t bplength = breakpoint->length & ~1; /* drop micro mips request bit for length */
uint32_t bpaddr = breakpoint->address & ~1; /* drop isa bit from address, if set */

if (bplength == 4) {
uint32_t verify = 0xffffffff;
uint32_t sdbbp32_instr = MIPS32_SDBBP(isa_req);
if (ejtag_info->endianness && isa_req)
sdbbp32_instr = SWAP16(sdbbp32_instr);

retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1,
breakpoint->orig_instr);
if (retval != ERROR_OK)
return retval;
retval = target_write_u32(target, breakpoint->address, MIPS32_SDBBP(ejtag_info->isa));
if (retval != ERROR_OK)
return retval;
if ((breakpoint->address & 3) == 0) { /* word alligned */

retval = target_read_u32(target, breakpoint->address, &verify);
if (retval != ERROR_OK)
return retval;
if (verify != MIPS32_SDBBP(ejtag_info->isa)) {
LOG_ERROR("Unable to set 32-bit breakpoint at address " TARGET_ADDR_FMT
" - check that memory is read/writable", breakpoint->address);
retval = target_read_memory(target, bpaddr, bplength, 1, breakpoint->orig_instr);
if (retval != ERROR_OK)
return retval;

retval = target_write_u32(target, bpaddr, sdbbp32_instr);
if (retval != ERROR_OK)
return retval;

retval = target_read_u32(target, bpaddr, &verify);
if (retval != ERROR_OK)
return retval;

if (verify != sdbbp32_instr)
verify = 0;

} else { /* 16 bit aligned */
retval = target_read_memory(target, bpaddr, 2, 2, breakpoint->orig_instr);
if (retval != ERROR_OK)
return retval;

uint8_t sdbbp_buf[4];
target_buffer_set_u32(target, sdbbp_buf, sdbbp32_instr);

retval = target_write_memory(target, bpaddr, 2, 2, sdbbp_buf);
if (retval != ERROR_OK)
return retval;

retval = target_read_memory(target, bpaddr, 2, 2, sdbbp_buf);
if (retval != ERROR_OK)
return retval;

if (target_buffer_get_u32(target, sdbbp_buf) != sdbbp32_instr)
verify = 0;
}

if (verify == 0) {
LOG_ERROR("Unable to set 32bit breakpoint at address %08" PRIx64
" - check that memory is read/writable", breakpoint->address);
return ERROR_OK;
}

} else {
uint16_t verify = 0xffff;

retval = target_read_memory(target, breakpoint->address, breakpoint->length, 1,
breakpoint->orig_instr);
retval = target_read_memory(target, bpaddr, bplength, 1, breakpoint->orig_instr);
if (retval != ERROR_OK)
return retval;
retval = target_write_u16(target, breakpoint->address, MIPS16_SDBBP(ejtag_info->isa));

retval = target_write_u16(target, bpaddr, MIPS16_SDBBP(isa_req));
if (retval != ERROR_OK)
return retval;

retval = target_read_u16(target, breakpoint->address, &verify);
retval = target_read_u16(target, bpaddr, &verify);
if (retval != ERROR_OK)
return retval;
if (verify != MIPS16_SDBBP(ejtag_info->isa)) {
LOG_ERROR("Unable to set 16-bit breakpoint at address " TARGET_ADDR_FMT

if (verify != MIPS16_SDBBP(isa_req)) {
LOG_ERROR("Unable to set 16bit breakpoint at address %08" PRIx64
" - check that memory is read/writable", breakpoint->address);
return ERROR_OK;
}
Expand Down Expand Up @@ -725,46 +766,58 @@ static int mips_m4k_unset_breakpoint(struct target *target,

} else {
/* restore original instruction (kept in target endianness) */
uint32_t isa_req = breakpoint->length & 1;
uint32_t bplength = breakpoint->length & ~1;
uint8_t current_instr[4];
LOG_DEBUG("bpid: %" PRIu32, breakpoint->unique_id);
if (breakpoint->length == 4) {
uint32_t current_instr;

/* check that user program has not modified breakpoint instruction */
retval = target_read_memory(target, breakpoint->address, 4, 1,
(uint8_t *)&current_instr);
if (retval != ERROR_OK)
return retval;

/**
* target_read_memory() gets us data in _target_ endianess.
* If we want to use this data on the host for comparisons with some macros
* we must first transform it to _host_ endianess using target_buffer_get_u32().
*/
current_instr = target_buffer_get_u32(target, (uint8_t *)&current_instr);

if (current_instr == MIPS32_SDBBP(ejtag_info->isa)) {
retval = target_write_memory(target, breakpoint->address, 4, 1,
breakpoint->orig_instr);
if (bplength == 4) {
uint32_t sdbbp32_instr = MIPS32_SDBBP(isa_req);
if (ejtag_info->endianness && isa_req)
sdbbp32_instr = SWAP16(sdbbp32_instr);

if ((breakpoint->address & 3) == 0) { /* 32bit aligned */
/* check that user program has not modified breakpoint instruction */
retval = target_read_memory(target, breakpoint->address, 4, 1, current_instr);
if (retval != ERROR_OK)
return retval;
/**
* target_read_memory() gets us data in _target_ endianess.
* If we want to use this data on the host for comparisons with some macros
* we must first transform it to _host_ endianess using target_buffer_get_u16().
*/
if (sdbbp32_instr == target_buffer_get_u32(target, current_instr)) {
retval = target_write_memory(target, breakpoint->address, 4, 1,
breakpoint->orig_instr);
if (retval != ERROR_OK)
return retval;
}
} else { /* 16bit alligned */
retval = target_read_memory(target, breakpoint->address, 2, 2, current_instr);
if (retval != ERROR_OK)
return retval;

if (sdbbp32_instr == target_buffer_get_u32(target, current_instr)) {
retval = target_write_memory(target, breakpoint->address, 2, 2,
breakpoint->orig_instr);
if (retval != ERROR_OK)
return retval;
}
}
} else {
uint16_t current_instr;

/* check that user program has not modified breakpoint instruction */
retval = target_read_memory(target, breakpoint->address, 2, 1,
(uint8_t *)&current_instr);
retval = target_read_memory(target, breakpoint->address, 2, 1, current_instr);
if (retval != ERROR_OK)
return retval;
current_instr = target_buffer_get_u16(target, (uint8_t *)&current_instr);
if (current_instr == MIPS16_SDBBP(ejtag_info->isa)) {

if (target_buffer_get_u16(target, current_instr) == MIPS16_SDBBP(isa_req)) {
retval = target_write_memory(target, breakpoint->address, 2, 1,
breakpoint->orig_instr);
breakpoint->orig_instr);
if (retval != ERROR_OK)
return retval;
}
}
}

breakpoint->set = 0;

return ERROR_OK;
Expand All @@ -774,6 +827,12 @@ static int mips_m4k_add_breakpoint(struct target *target, struct breakpoint *bre
{
struct mips32_common *mips32 = target_to_mips32(target);

if ((breakpoint->length > 5 || breakpoint->length < 2) || /* out of range */
(breakpoint->length == 4 && (breakpoint->address & 2)) || /* mips32 unaligned */
(mips32->isa_imp == MIPS32_ONLY && breakpoint->length != 4) || /* misp32 specific */
((mips32->isa_imp & 1) != (breakpoint->length & 1))) /* isa not implemented */
return ERROR_TARGET_RESOURCE_NOT_AVAILABLE;

if (breakpoint->type == BKPT_HARD) {
if (mips32->num_inst_bpoints_avail < 1) {
LOG_INFO("no hardware breakpoint available");
Expand Down

0 comments on commit b702b16

Please sign in to comment.