/* read reg from lakemont core shadow ram, update reg cache if needed */ static int read_hw_reg(struct target *t, int reg, uint32_t *regval, uint8_t cache) { struct x86_32_common *x86_32 = target_to_x86_32(t); struct lakemont_core_reg *arch_info; arch_info = x86_32->cache->reg_list[reg].arch_info; x86_32->flush = 0; /* dont flush scans till we have a batch */ if (submit_reg_pir(t, reg) != ERROR_OK) return ERROR_FAIL; if (submit_instruction_pir(t, SRAMACCESS) != ERROR_OK) return ERROR_FAIL; if (submit_instruction_pir(t, SRAM2PDR) != ERROR_OK) return ERROR_FAIL; x86_32->flush = 1; scan.out[0] = RDWRPDR; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return ERROR_FAIL; if (drscan(t, NULL, scan.out, PDR_SIZE) != ERROR_OK) return ERROR_FAIL; jtag_add_sleep(DELAY_SUBMITPIR); *regval = buf_get_u32(scan.out, 0, 32); if (cache) { buf_set_u32(x86_32->cache->reg_list[reg].value, 0, 32, *regval); x86_32->cache->reg_list[reg].valid = 1; x86_32->cache->reg_list[reg].dirty = 0; } LOG_DEBUG("reg=%s, op=0x%016" PRIx64 ", val=0x%08" PRIx32, x86_32->cache->reg_list[reg].name, arch_info->op, *regval); return ERROR_OK; }
/* write lakemont core shadow ram reg, update reg cache if needed */ static int write_hw_reg(struct target *t, int reg, uint32_t regval, uint8_t cache) { struct x86_32_common *x86_32 = target_to_x86_32(t); struct lakemont_core_reg *arch_info; arch_info = x86_32->cache->reg_list[reg].arch_info; uint8_t reg_buf[4]; if (cache) regval = buf_get_u32(x86_32->cache->reg_list[reg].value, 0, 32); buf_set_u32(reg_buf, 0, 32, regval); LOG_DEBUG("reg=%s, op=0x%016" PRIx64 ", val=0x%08" PRIx32 " cache=0x%08" PRIx8, x86_32->cache->reg_list[reg].name, arch_info->op, regval, cache); x86_32->flush = 0; /* dont flush scans till we have a batch */ if (submit_reg_pir(t, reg) != ERROR_OK) return ERROR_FAIL; if (submit_instruction_pir(t, SRAMACCESS) != ERROR_OK) return ERROR_FAIL; scan.out[0] = RDWRPDR; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return ERROR_FAIL; if (drscan(t, reg_buf, scan.out, PDR_SIZE) != ERROR_OK) return ERROR_FAIL; x86_32->flush = 1; if (submit_instruction_pir(t, PDR2SRAM) != ERROR_OK) return ERROR_FAIL; /* we are writing from the cache so ensure we reset flags */ if (cache) { x86_32->cache->reg_list[reg].dirty = 0; x86_32->cache->reg_list[reg].valid = 0; } return ERROR_OK; }
static int enter_probemode(struct target *t) { uint32_t tapstatus = 0; tapstatus = get_tapstatus(t); LOG_DEBUG("TS before PM enter = 0x%08" PRIx32, tapstatus); if (tapstatus & TS_PM_BIT) { LOG_DEBUG("core already in probemode"); return ERROR_OK; } scan.out[0] = PROBEMODE; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return ERROR_FAIL; scan.out[0] = 1; if (drscan(t, scan.out, scan.in, 1) != ERROR_OK) return ERROR_FAIL; /* HACK */ int cnt = 5; do { tapstatus = get_tapstatus(t); if (tapstatus & TS_PM_BIT) return ERROR_OK; LOG_DEBUG("%s Waiting for PM, TS = 0x%08" PRIx32, __func__, tapstatus); usleep(100000); cnt--; } while (cnt); return ERROR_FAIL; /* TODO: find a nicer way to wait until PM_BIT changes*/ }
static int enter_probemode(struct target *t) { uint32_t tapstatus = 0; tapstatus = get_tapstatus(t); LOG_DEBUG("TS before PM enter = 0x%08" PRIx32, tapstatus); if (tapstatus & TS_PM_BIT) { LOG_DEBUG("core already in probemode"); return ERROR_OK; } scan.out[0] = PROBEMODE; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return ERROR_FAIL; scan.out[0] = 1; if (drscan(t, scan.out, scan.in, 1) != ERROR_OK) return ERROR_FAIL; tapstatus = get_tapstatus(t); LOG_DEBUG("TS after PM enter = 0x%08" PRIx32, tapstatus); if ((tapstatus & TS_PM_BIT) && (!(tapstatus & TS_EN_PM_BIT))) return ERROR_OK; else { LOG_ERROR("%s PM enter error, tapstatus = 0x%08" PRIx32 , __func__, tapstatus); return ERROR_FAIL; } }
static uint32_t get_tapstatus(struct target *t) { scan.out[0] = TAPSTATUS; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return 0; if (drscan(t, NULL, scan.out, TS_SIZE) != ERROR_OK) return 0; return buf_get_u32(scan.out, 0, 32); }
static int exit_probemode(struct target *t) { uint32_t tapstatus = get_tapstatus(t); LOG_DEBUG("TS before PM exit = 0x%08" PRIx32, tapstatus); if (!(tapstatus & TS_PM_BIT)) { LOG_USER("core not in PM"); return ERROR_OK; } scan.out[0] = PROBEMODE; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return ERROR_FAIL; scan.out[0] = 0; if (drscan(t, scan.out, scan.in, 1) != ERROR_OK) return ERROR_FAIL; return ERROR_OK; }
/* * PIR (Probe Mode Instruction Register), SUBMITPIR is an "IR only" TAP * command; there is no corresponding data register */ static int submit_pir(struct target *t, uint64_t op) { struct x86_32_common *x86_32 = target_to_x86_32(t); uint32_t tapstatus = 0; uint8_t op_buf[8]; buf_set_u64(op_buf, 0, 64, op); int flush = x86_32->flush; x86_32->flush = 0; scan.out[0] = WRPIR; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return ERROR_FAIL; if (drscan(t, op_buf, scan.out, PIR_SIZE) != ERROR_OK) return ERROR_FAIL; scan.out[0] = SUBMITPIR; x86_32->flush = flush; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return ERROR_FAIL; jtag_add_sleep(DELAY_SUBMITPIR); /* HACK */ if (x86_32->flush) { int cnt = 10; do { tapstatus = get_tapstatus(t); if (!(tapstatus & TS_PIR_BIT)) return ERROR_OK; LOG_DEBUG("%s Waiting for TS_PIR_BIT, TS = 0x%08" PRIx32, __func__, tapstatus); usleep(100); cnt--; } while (cnt); LOG_ERROR("%s TS_PIR_BIT did not clear, TS = 0x%08" PRIx32, __func__, tapstatus); return ERROR_FAIL; /* TODO: find a nicer way to wait until PM_BIT changes*/ } return ERROR_OK; }
/* * PIR (Probe Mode Instruction Register), SUBMITPIR is an "IR only" TAP * command; there is no corresponding data register */ static int submit_pir(struct target *t, uint64_t op) { struct x86_32_common *x86_32 = target_to_x86_32(t); uint8_t op_buf[8]; buf_set_u64(op_buf, 0, 64, op); int flush = x86_32->flush; x86_32->flush = 0; scan.out[0] = WRPIR; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return ERROR_FAIL; if (drscan(t, op_buf, scan.out, PIR_SIZE) != ERROR_OK) return ERROR_FAIL; scan.out[0] = SUBMITPIR; x86_32->flush = flush; if (irscan(t, scan.out, NULL, LMT_IRLEN) != ERROR_OK) return ERROR_FAIL; jtag_add_sleep(DELAY_SUBMITPIR); return ERROR_OK; }