This is an automated email from Gerrit. Peter Mamonov ([email protected]) just uploaded a new patch set to Gerrit, which you can find at http://openocd.zylin.com/4024
-- gerrit commit 82cf73c9179933da51f05b68861a219d9f7977dc Author: Peter Mamonov <[email protected]> Date: Mon Jan 18 12:21:14 2016 +0300 mips64: implement fastdata upload mechanism Change-Id: I008fa35da50ed3951ed1f2f89d839ad8adf8ee9b Signed-off-by: Peter Mamonov <[email protected]> diff --git a/src/target/mips64.c b/src/target/mips64.c index dff5868..3b7e1f2 100644 --- a/src/target/mips64.c +++ b/src/target/mips64.c @@ -391,6 +391,8 @@ int mips64_init_arch_info(struct target *target, mips64_common_t *mips64, struct mips64->read_core_reg = mips64_read_core_reg; mips64->write_core_reg = mips64_write_core_reg; + mips64->fast_data_area = NULL; + return ERROR_OK; } diff --git a/src/target/mips64.h b/src/target/mips64.h index 315604d..4777833 100644 --- a/src/target/mips64.h +++ b/src/target/mips64.h @@ -55,6 +55,8 @@ typedef struct mips64_common_s { struct mips_ejtag ejtag_info; uint64_t core_regs[MIPS64NUMCOREREGS]; + struct working_area *fast_data_area; + int bp_scanned; int num_inst_bpoints; int num_data_bpoints; @@ -77,6 +79,8 @@ typedef struct mips64_core_reg_s { #define MIPS64_OP_BEQ 0x04 #define MIPS64_OP_BNE 0x05 #define MIPS64_OP_ADDI 0x08 +#define MIPS64_OP_DADDI 24 +#define MIPS64_OP_DADDIU 25 #define MIPS64_OP_AND 0x24 #define MIPS64_OP_LUI 0x0F #define MIPS64_OP_LW 0x23 @@ -92,6 +96,7 @@ typedef struct mips64_core_reg_s { #define MIPS64_OP_SW 0x2B #define MIPS64_OP_SD 0x3F #define MIPS64_OP_ORI 0x0D +#define MIPS64_OP_JR 0x08 #define MIPS64_OP_COP0 0x10 #define MIPS64_OP_COP1 0x11 @@ -111,6 +116,8 @@ typedef struct mips64_core_reg_s { #define MIPS64_NOP 0 #define MIPS64_ADDI(tar, src, val) MIPS64_I_INST(MIPS64_OP_ADDI, src, tar, val) +#define MIPS64_DADDI(tar, src, val) MIPS64_I_INST(MIPS64_OP_DADDI, src, tar, val) +#define MIPS64_DADDIU(tar, src, val) MIPS64_I_INST(MIPS64_OP_DADDIU, src, tar, val) #define MIPS64_AND(reg, off, val) MIPS64_R_INST(0, off, val, reg, 0, MIPS64_OP_AND) #define MIPS64_B(off) MIPS64_BEQ(0, 0, off) #define MIPS64_BEQ(src, tar, off) MIPS64_I_INST(MIPS64_OP_BEQ, src, tar, off) @@ -143,6 +150,7 @@ typedef struct mips64_core_reg_s { #define MIPS64_SD(reg, off, base) MIPS64_I_INST(MIPS64_OP_SD, base, reg, off) #define MIPS64_CACHE(op, reg, off) (47 << 26 | (reg) << 21 | (op) << 16 | (off)) #define MIPS64_SYNCI(reg, off) (1 << 26 | (reg) << 21 | 0x1f << 16 | (off)) +#define MIPS64_JR(reg) MIPS64_R_INST(0, reg, 0, 0, 0, MIPS64_OP_JR) /* ejtag specific instructions */ #define MIPS64_DRET 0x4200001F diff --git a/src/target/mips64_pracc.c b/src/target/mips64_pracc.c index 234b423..cf79990 100644 --- a/src/target/mips64_pracc.c +++ b/src/target/mips64_pracc.c @@ -928,4 +928,171 @@ int mips64_pracc_read_regs(struct mips_ejtag *ejtag_info, uint64_t *regs) 0, NULL, MIPS64NUMCOREREGS, regs, 1); } +/* fastdata upload/download requires an initialized working area + * to load the download code; it should not be called otherwise + * fetch order from the fastdata area + * 1. start addr + * 2. end addr + * 3. data ... + */ +int mips64_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, + struct working_area *source, + int write_t, uint64_t addr, int count, uint64_t *buf) +{ + uint32_t handler_code[] = { + /* caution when editing, table is modified below */ + /* r15 points to the start of this code */ + MIPS64_SD(8, MIPS64_FASTDATA_HANDLER_SIZE - 8, 15), + MIPS64_SD(9, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 2, 15), + MIPS64_SD(10, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 3, 15), + MIPS64_SD(11, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 4, 15), + /* start of fastdata area in t0 */ + MIPS64_LUI(8, UPPER16(MIPS64_PRACC_FASTDATA_AREA)), + MIPS64_ORI(8, 8, LOWER16(MIPS64_PRACC_FASTDATA_AREA)), + MIPS64_LD(9, 0, 8), /* start addr in t1 */ + MIPS64_LD(10, 0, 8), /* end addr to t2 */ + /* loop: */ + /* 8 */ MIPS64_LD(11, 0, 0), /* lw t3,[t8 | r9] */ + /* 9 */ MIPS64_SD(11, 0, 0), /* sw t3,[r9 | r8] */ + MIPS64_BNE(10, 9, NEG16(3)), /* bne $t2,t1,loop */ + MIPS64_DADDIU(9, 9, 8), /* addi t1,t1,4 */ + + MIPS64_LD(8, MIPS64_FASTDATA_HANDLER_SIZE - 8, 15), + MIPS64_LD(9, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 2, 15), + MIPS64_LD(10, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 3, 15), + MIPS64_LD(11, MIPS64_FASTDATA_HANDLER_SIZE - 8 * 4, 15), + + MIPS64_LUI(15, UPPER16(MIPS64_PRACC_TEXT)), + MIPS64_ORI(15, 15, LOWER16(MIPS64_PRACC_TEXT)), + MIPS64_JR(15), /* jr start */ + MIPS64_DMFC0(15, 31, 0), /* move COP0 DeSave to $15 */ + }; + + uint32_t jmp_code[] = { + /* 0 */ MIPS64_LUI(15, 0), /* addr of working area added below */ + /* 1 */ MIPS64_ORI(15, 15, 0), /* addr of working area added below */ + MIPS64_JR(15), /* jump to ram program */ + MIPS64_NOP, + }; + + int retval, i; + uint32_t ejtag_ctrl, address32; + uint64_t address, val; + + if (source->size < MIPS64_FASTDATA_HANDLER_SIZE) + return ERROR_TARGET_RESOURCE_NOT_AVAILABLE; + + if (write_t) { + handler_code[8] = MIPS64_LD(11, 0, 8); /* load data from probe at fastdata area */ + handler_code[9] = MIPS64_SD(11, 0, 9); /* store data to RAM @ r9 */ + } else { + handler_code[8] = MIPS64_LD(11, 0, 9); /* load data from RAM @ r9 */ + handler_code[9] = MIPS64_SD(11, 0, 8); /* store data to probe at fastdata area */ + } + + /* write program into RAM */ + if (write_t != ejtag_info->fast_access_save) { + mips64_pracc_write_mem(ejtag_info, source->address, 4, ARRAY_SIZE(handler_code), handler_code); + /* save previous operation to speed to any consecutive read/writes */ + ejtag_info->fast_access_save = write_t; + } + + LOG_DEBUG("%s using " TARGET_ADDR_FMT " for write handler", __func__, source->address); + LOG_DEBUG("daddiu: %08x", handler_code[11]); + + jmp_code[0] |= UPPER16(source->address); + jmp_code[1] |= LOWER16(source->address); +#if 0 + for (i = 0; i < (int) ARRAY_SIZE(jmp_code); i++) { + uint64_t inst; + retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); + if (retval != ERROR_OK) + return retval; + inst = jmp_code[i]; + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_DATA); + mips_ejtag_drscan_64(ejtag_info, &inst); /* FIXME: excessive nop's */ + + /* Clear the access pending bit (let the processor eat!) */ + ejtag_ctrl = ejtag_info->ejtag_ctrl & ~EJTAG_CTRL_PRACC; + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_CONTROL); + mips_ejtag_drscan_32_out(ejtag_info, ejtag_ctrl); + } + + /* wait PrAcc pending bit for FASTDATA write */ + retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); + if (retval != ERROR_OK) + return retval; +#endif + mips64_pracc_exec(ejtag_info, + ARRAY_SIZE(jmp_code), jmp_code, + 0, NULL, 0, NULL, 1); + + /* next fetch to dmseg should be in FASTDATA_AREA, check */ + address = 0; + + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); + retval = mips_ejtag_drscan_32(ejtag_info, &address32); + if (retval != ERROR_OK) + return retval; + address = 0xffffffffff200000ull | address32; + if ((address & ~7ull) != MIPS64_PRACC_FASTDATA_AREA) { + LOG_ERROR("! @MIPS64_PRACC_FASTDATA_AREA (" TARGET_ADDR_FMT ")", address); + return ERROR_FAIL; + } + /* Send the load start address */ + val = addr; + LOG_DEBUG("start: " TARGET_ADDR_FMT, val); + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA); + mips64_ejtag_fastdata_scan(ejtag_info, 1, &val); + + retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); + if (retval != ERROR_OK) + return retval; + + /* Send the load end address */ + val = addr + (count - 1) * 8; + LOG_DEBUG("stop: " TARGET_ADDR_FMT, val); + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_FASTDATA); + mips64_ejtag_fastdata_scan(ejtag_info, 1, &val); + + unsigned num_clocks = 0; /* like in legacy code */ + if (ejtag_info->mode != 0) + num_clocks = ((uint64_t)(ejtag_info->scan_delay) * jtag_get_speed_khz() + 500000) / 1000000; + LOG_DEBUG("num_clocks=%d", num_clocks); + for (i = 0; i < count; i++) { + jtag_add_clocks(num_clocks); + retval = mips64_ejtag_fastdata_scan(ejtag_info, write_t, buf++); + if (retval != ERROR_OK) { + LOG_ERROR("mips64_ejtag_fastdata_scan failed"); + return retval; + } + } + + retval = jtag_execute_queue(); + if (retval != ERROR_OK) { + LOG_ERROR("jtag_execute_queue failed"); + return retval; + } + + retval = wait_for_pracc_rw(ejtag_info, &ejtag_ctrl); + if (retval != ERROR_OK) { + LOG_ERROR("wait_for_pracc_rw failed"); + return retval; + } + + address = 0; + mips_ejtag_set_instr(ejtag_info, EJTAG_INST_ADDRESS); + retval = mips_ejtag_drscan_32(ejtag_info, &address32); + address = 0xffffffffff200000ull | address32; + if (retval != ERROR_OK) { + LOG_ERROR("mips_ejtag_drscan_32 failed"); + return retval; + } + + if ((address & ~7ull) != MIPS64_PRACC_TEXT) + LOG_ERROR("mini program did not return to start"); + + return retval; +} + #endif /* BUILD_TARGET64 */ diff --git a/src/target/mips64_pracc.h b/src/target/mips64_pracc.h index 00def78..2190495 100644 --- a/src/target/mips64_pracc.h +++ b/src/target/mips64_pracc.h @@ -40,6 +40,9 @@ #undef LOWER16 #define UPPER16(v) ((uint32_t)((v >> 16) & 0xFFFF)) #define LOWER16(v) ((uint32_t)(v & 0xFFFF)) +#define MIPS64_PRACC_FASTDATA_AREA 0xffffffffFF200000 +#define MIPS64_PRACC_FASTDATA_SIZE 16 +#define MIPS64_FASTDATA_HANDLER_SIZE 0x80 /* FIXME: 16-bit NEG */ #undef NEG16 @@ -74,4 +77,10 @@ extern int mips64_pracc_write_regs(struct mips_ejtag *ejtag_info, uint64_t *regs extern int mips64_pracc_exec(struct mips_ejtag *ejtag_info, int code_len, uint32_t *code, int num_param_in, uint64_t *param_in, int num_param_out, uint64_t *param_out, int cycle); + +extern int mips64_pracc_fastdata_xfer(struct mips_ejtag *ejtag_info, + struct working_area *source, + int write_t, uint64_t addr, + int count, uint64_t *buf); + #endif /* OPENOCD_TARGET_MIPS64_PRACC_H */ diff --git a/src/target/mips_ejtag.c b/src/target/mips_ejtag.c index e4ef3c1..fdf320e 100644 --- a/src/target/mips_ejtag.c +++ b/src/target/mips_ejtag.c @@ -514,7 +514,6 @@ int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_ return ERROR_OK; } - #if BUILD_TARGET64 == 1 int mips64_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step) @@ -588,4 +587,41 @@ int mips64_ejtag_exit_debug(struct mips_ejtag *ejtag_info) return ERROR_OK; } +int mips64_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint64_t *data) +{ + struct jtag_tap *tap; + + tap = ejtag_info->tap; + assert(tap != NULL); + + struct scan_field fields[2]; + uint8_t spracc = 0; + uint8_t t[8] = {0, 0, 0, 0, 0, 0, 0, 0}; + + /* fastdata 1-bit register */ + fields[0].num_bits = 1; + fields[0].out_value = &spracc; + fields[0].in_value = NULL; + + /* processor access data register 32 bit */ + fields[1].num_bits = 64; + fields[1].out_value = t; + + if (write_t) { + fields[1].in_value = NULL; + buf_set_u64(t, 0, 64, *data); + } else + fields[1].in_value = (uint8_t *) data; + + jtag_add_dr_scan(tap, 2, fields, TAP_IDLE); + + /* FIXME: mips_le_to_h_u64*/ + if (!write_t && data) + jtag_add_callback(mips_le_to_h_u32, + (jtag_callback_data_t) data); + keep_alive(); + + return ERROR_OK; +} + #endif /* BUILD_TARGET64 */ diff --git a/src/target/mips_ejtag.h b/src/target/mips_ejtag.h index 21b3e68..9dd2f03 100644 --- a/src/target/mips_ejtag.h +++ b/src/target/mips_ejtag.h @@ -238,6 +238,7 @@ int mips_ejtag_drscan_32(struct mips_ejtag *ejtag_info, uint32_t *data); void mips_ejtag_drscan_8_out(struct mips_ejtag *ejtag_info, uint8_t data); int mips_ejtag_drscan_8(struct mips_ejtag *ejtag_info, uint32_t *data); int mips_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint32_t *data); +int mips64_ejtag_fastdata_scan(struct mips_ejtag *ejtag_info, int write_t, uint64_t *data); int mips_ejtag_init(struct mips_ejtag *ejtag_info); int mips_ejtag_config_step(struct mips_ejtag *ejtag_info, int enable_step); @@ -249,4 +250,10 @@ static inline void mips_le_to_h_u32(jtag_callback_data_t arg) *((uint32_t *)arg) = le_to_h_u32(in); } +static inline void mips_le_to_h_u64(jtag_callback_data_t arg) +{ + uint8_t *in = (uint8_t *)arg; + *((uint64_t *)arg) = le_to_h_u64(in); +} + #endif /* OPENOCD_TARGET_MIPS_EJTAG_H */ diff --git a/src/target/mips_mips64.c b/src/target/mips_mips64.c index 26e8342..8153f1a 100644 --- a/src/target/mips_mips64.c +++ b/src/target/mips_mips64.c @@ -741,6 +741,73 @@ static int mips_mips64_read_memory(struct target *target, uint64_t address, return retval; } +static int mips_mips64_bulk_write_memory(struct target *target, target_addr_t address, + uint32_t count, const uint8_t *buffer) +{ + mips64_common_t *mips64 = target->arch_info; + struct mips_ejtag *ejtag_info = &mips64->ejtag_info; + struct working_area *fast_data_area; + int retval; + int write_t = 1; + + LOG_DEBUG("address: " TARGET_ADDR_FMT ", count: 0x%8.8" PRIx32 "", address, count); + + /* check alignment */ + if (address & 0x7u) + return ERROR_TARGET_UNALIGNED_ACCESS; + + if (mips64->fast_data_area == NULL) { + /* Get memory for block write handler + * we preserve this area between calls and gain a speed increase + * of about 3kb/sec when writing flash + * this will be released/nulled by the system when the target is resumed or reset */ + retval = target_alloc_working_area(target, + MIPS64_FASTDATA_HANDLER_SIZE, + &mips64->fast_data_area); + if (retval != ERROR_OK) { + LOG_ERROR("No working area available"); + return retval; + } + + /* reset fastadata state so the algo get reloaded */ + ejtag_info->fast_access_save = -1; + } + + fast_data_area = mips64->fast_data_area; + + if (address <= fast_data_area->address + fast_data_area->size && + fast_data_area->address <= address + count) { + LOG_ERROR("fast_data (" TARGET_ADDR_FMT ") is within write area " + "(" TARGET_ADDR_FMT "-" TARGET_ADDR_FMT ").", + fast_data_area->address, address, address + count); + LOG_ERROR("Change work-area-phys or load_image address!"); + return ERROR_FAIL; + } + + /* mips32_pracc_fastdata_xfer requires uint32_t in host endianness, */ + /* but byte array represents target endianness */ + uint64_t *t = NULL; + t = malloc(count * sizeof(uint64_t)); + if (t == NULL) { + LOG_ERROR("Out of memory"); + return ERROR_FAIL; + } + + target_buffer_get_u64_array(target, buffer, count, t); + + retval = mips64_pracc_fastdata_xfer(ejtag_info, mips64->fast_data_area, + write_t, address, + count, t); + + if (t != NULL) + free(t); + + if (retval != ERROR_OK) + LOG_ERROR("Fastdata access Failed"); + + return retval; +} + static int mips_mips64_write_memory(struct target *target, uint64_t address, uint32_t size, uint32_t count, const uint8_t *buffer) { @@ -755,6 +822,7 @@ static int mips_mips64_write_memory(struct target *target, uint64_t address, return ERROR_TARGET_NOT_HALTED; } + /* sanitize arguments */ if (((size != 8) && (size != 4) && (size != 2) && (size != 1)) || (count == 0) || !(buffer)) return ERROR_COMMAND_ARGUMENT_INVALID; @@ -763,6 +831,16 @@ static int mips_mips64_write_memory(struct target *target, uint64_t address, ((size == 2) && (address & 0x1u))) return ERROR_TARGET_UNALIGNED_ACCESS; + if (size == 8 && count > 8) { + retval = mips_mips64_bulk_write_memory(target, + address, + count, + buffer); + if (retval == ERROR_OK) + return ERROR_OK; + LOG_WARNING("Falling back to non-bulk write"); + } + void *t = NULL; if (size > 1) { /* mips32_..._write_mem with size 4/2 requires uint32_t/uint16_t in host */ diff --git a/src/target/target.h b/src/target/target.h index f0dd723..5848760 100644 --- a/src/target/target.h +++ b/src/target/target.h @@ -656,6 +656,7 @@ void target_buffer_set_u64(struct target *target, uint8_t *buffer, uint64_t valu void target_buffer_set_u32(struct target *target, uint8_t *buffer, uint32_t value); void target_buffer_set_u24(struct target *target, uint8_t *buffer, uint32_t value); void target_buffer_set_u16(struct target *target, uint8_t *buffer, uint16_t value); +void target_buffer_set_array(struct target *target, uint8_t *buffer, uint32_t count, uint32_t size, const uint8_t *srcbuf); void target_buffer_get_u64_array(struct target *target, const uint8_t *buffer, uint32_t count, uint64_t *dstbuf); void target_buffer_get_u32_array(struct target *target, const uint8_t *buffer, uint32_t count, uint32_t *dstbuf); diff --git a/tcl/target/netl_xlp3xx.cfg b/tcl/target/netl_xlp3xx.cfg index 643e964..90ef9ca 100644 --- a/tcl/target/netl_xlp3xx.cfg +++ b/tcl/target/netl_xlp3xx.cfg @@ -36,3 +36,4 @@ proc chipreset {} { jtag configure xlp.jrc -event setup "jtag tapenable xlp.cpu_1" target create xlp.cpu_1 mips_mips64 -endian big -chain-position xlp.cpu_1 +xlp.cpu_1 configure -work-area-phys 0xffffffffa0600000 -work-area-size 0x20000 -- ------------------------------------------------------------------------------ Check out the vibrant tech community on one of the world's most engaging tech sites, SlashDot.org! http://sdm.link/slashdot _______________________________________________ OpenOCD-devel mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/openocd-devel
