diff options
author | Tim Newsome <tim@sifive.com> | 2017-10-04 12:52:21 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-10-04 12:52:21 -0700 |
commit | abe7eba25a7e8ae0c9daae6785ef2d204b626825 (patch) | |
tree | 527431161b87560b0ad228a2a4bd09aab5d6b6dc | |
parent | a3c26250bf3a319e0241daa7feb5ea155279fb29 (diff) | |
parent | e64bb8c44a6e2b6b9b39426c4c77e00edceac5aa (diff) | |
download | riscv-openocd-abe7eba25a7e8ae0c9daae6785ef2d204b626825.zip riscv-openocd-abe7eba25a7e8ae0c9daae6785ef2d204b626825.tar.gz riscv-openocd-abe7eba25a7e8ae0c9daae6785ef2d204b626825.tar.bz2 |
Merge pull request #118 from riscv/priv
Fix priv access
-rw-r--r-- | src/target/riscv/gdb_regs.h | 2 | ||||
-rw-r--r-- | src/target/riscv/riscv-011.c | 96 | ||||
-rw-r--r-- | src/target/riscv/riscv-013.c | 6 |
3 files changed, 47 insertions, 57 deletions
diff --git a/src/target/riscv/gdb_regs.h b/src/target/riscv/gdb_regs.h index 0ad02e9..2952e10 100644 --- a/src/target/riscv/gdb_regs.h +++ b/src/target/riscv/gdb_regs.h @@ -1,6 +1,8 @@ #ifndef TARGET__RISCV__GDB_REGS_H #define TARGET__RISCV__GDB_REGS_H +// gdb's register list is defined in riscv_gdb_reg_names gdb/riscv-tdep.c in +// its source tree. We must interpret the numbers the same here. enum gdb_regno { GDB_REGNO_XPR0 = 0, GDB_REGNO_X0 = GDB_REGNO_XPR0 + 0, diff --git a/src/target/riscv/riscv-011.c b/src/target/riscv/riscv-011.c index 4f2e3a6..7ac8561 100644 --- a/src/target/riscv/riscv-011.c +++ b/src/target/riscv/riscv-011.c @@ -21,6 +21,7 @@ #include "helper/time_support.h" #include "riscv.h" #include "asm.h" +#include "gdb_regs.h" /** * Since almost everything can be accomplish by scanning the dbus register, all @@ -155,21 +156,6 @@ typedef enum slot { #define DBUS_ADDRESS_UNKNOWN 0xffff -// gdb's register list is defined in riscv_gdb_reg_names gdb/riscv-tdep.c in -// its source tree. We must interpret the numbers the same here. -enum { - REG_XPR0 = 0, - REG_XPR31 = 31, - REG_PC = 32, - REG_FPR0 = 33, - REG_FPR31 = 64, - REG_CSR0 = 65, - REG_MSTATUS = CSR_MSTATUS + REG_CSR0, - REG_CSR4095 = 4160, - REG_PRIV = 4161, - REG_COUNT -}; - #define DRAM_CACHE_SIZE 16 struct trigger { @@ -1118,7 +1104,7 @@ static int execute_resume(struct target *target, bool step) return ERROR_FAIL; } - struct reg *mstatus_reg = &target->reg_cache->reg_list[REG_MSTATUS]; + struct reg *mstatus_reg = &target->reg_cache->reg_list[GDB_REGNO_MSTATUS]; if (mstatus_reg->valid) { uint64_t mstatus_user = buf_get_u64(mstatus_reg->value, 0, riscv_xlen(target)); if (mstatus_user != info->mstatus_actual) { @@ -1202,15 +1188,15 @@ static void update_reg_list(struct target *target) if (info->reg_values) { free(info->reg_values); } - info->reg_values = malloc(REG_COUNT * riscv_xlen(target) / 4); + info->reg_values = malloc(GDB_REGNO_COUNT * riscv_xlen(target) / 4); - for (unsigned int i = 0; i < REG_COUNT; i++) { + for (unsigned int i = 0; i < GDB_REGNO_COUNT; i++) { struct reg *r = &target->reg_cache->reg_list[i]; r->value = info->reg_values + i * riscv_xlen(target) / 4; if (r->dirty) { LOG_ERROR("Register %d was dirty. Its value is lost.", i); } - if (i == REG_PRIV) { + if (i == GDB_REGNO_PRIV) { r->size = 8; } else { r->size = riscv_xlen(target); @@ -1242,7 +1228,7 @@ static void reg_cache_set(struct target *target, unsigned int number, static int update_mstatus_actual(struct target *target) { - struct reg *mstatus_reg = &target->reg_cache->reg_list[REG_MSTATUS]; + struct reg *mstatus_reg = &target->reg_cache->reg_list[GDB_REGNO_MSTATUS]; if (mstatus_reg->valid) { // We previously made it valid. return ERROR_OK; @@ -1250,7 +1236,7 @@ static int update_mstatus_actual(struct target *target) // Force reading the register. In that process mstatus_actual will be // updated. - return register_get(&target->reg_cache->reg_list[REG_MSTATUS]); + return register_get(&target->reg_cache->reg_list[GDB_REGNO_MSTATUS]); } /*** OpenOCD target functions. ***/ @@ -1258,8 +1244,8 @@ static int update_mstatus_actual(struct target *target) static int register_read(struct target *target, riscv_reg_t *value, int regnum) { riscv011_info_t *info = get_info(target); - if (regnum >= REG_CSR0 && regnum <= REG_CSR4095) { - cache_set32(target, 0, csrr(S0, regnum - REG_CSR0)); + if (regnum >= GDB_REGNO_CSR0 && regnum <= GDB_REGNO_CSR4095) { + cache_set32(target, 0, csrr(S0, regnum - GDB_REGNO_CSR0)); cache_set_store(target, 1, S0, SLOT0); cache_set_jump(target, 2); } else { @@ -1282,7 +1268,7 @@ static int register_read(struct target *target, riscv_reg_t *value, int regnum) *value = cache_get(target, SLOT0); LOG_DEBUG("reg[%d]=0x%" PRIx64, regnum, *value); - if (regnum == REG_MSTATUS) { + if (regnum == GDB_REGNO_MSTATUS) { info->mstatus_actual = *value; } @@ -1297,13 +1283,13 @@ static int register_get(struct reg *reg) maybe_write_tselect(target); riscv_reg_t value = ~0; - if (reg->number <= REG_XPR31) { + if (reg->number <= GDB_REGNO_XPR31) { value = reg_cache_get(target, reg->number); LOG_DEBUG("%s=0x%" PRIx64, reg->name, reg_cache_get(target, reg->number)); - } else if (reg->number == REG_PC) { + } else if (reg->number == GDB_REGNO_PC) { value = info->dpc; LOG_DEBUG("%s=0x%" PRIx64 " (cached)", reg->name, info->dpc); - } else if (reg->number >= REG_FPR0 && reg->number <= REG_FPR31) { + } else if (reg->number >= GDB_REGNO_FPR0 && reg->number <= GDB_REGNO_FPR31) { int result = update_mstatus_actual(target); if (result != ERROR_OK) { return result; @@ -1317,22 +1303,24 @@ static int register_get(struct reg *reg) } if (riscv_xlen(target) == 32) { - cache_set32(target, i++, fsw(reg->number - REG_FPR0, 0, DEBUG_RAM_START + 16)); + cache_set32(target, i++, fsw(reg->number - GDB_REGNO_FPR0, 0, DEBUG_RAM_START + 16)); } else { - cache_set32(target, i++, fsd(reg->number - REG_FPR0, 0, DEBUG_RAM_START + 16)); + cache_set32(target, i++, fsd(reg->number - GDB_REGNO_FPR0, 0, DEBUG_RAM_START + 16)); } cache_set_jump(target, i++); if (cache_write(target, 4, true) != ERROR_OK) { return ERROR_FAIL; } + } else if (reg->number == GDB_REGNO_PRIV) { + value = get_field(info->dcsr, DCSR_PRV); } else { if (register_read(target, &value, reg->number) != ERROR_OK) return ERROR_FAIL; } buf_set_u64(reg->value, 0, riscv_xlen(target), value); - if (reg->number == REG_MSTATUS) { + if (reg->number == GDB_REGNO_MSTATUS) { reg->valid = true; } @@ -1355,13 +1343,13 @@ static int register_write(struct target *target, unsigned int number, cache_set_load(target, 0, S0, SLOT0); cache_set_store(target, 1, S0, SLOT_LAST); cache_set_jump(target, 2); - } else if (number <= REG_XPR31) { - cache_set_load(target, 0, number - REG_XPR0, SLOT0); + } else if (number <= GDB_REGNO_XPR31) { + cache_set_load(target, 0, number - GDB_REGNO_XPR0, SLOT0); cache_set_jump(target, 1); - } else if (number == REG_PC) { + } else if (number == GDB_REGNO_PC) { info->dpc = value; return ERROR_OK; - } else if (number >= REG_FPR0 && number <= REG_FPR31) { + } else if (number >= GDB_REGNO_FPR0 && number <= GDB_REGNO_FPR31) { int result = update_mstatus_actual(target); if (result != ERROR_OK) { return result; @@ -1375,20 +1363,20 @@ static int register_write(struct target *target, unsigned int number, } if (riscv_xlen(target) == 32) { - cache_set32(target, i++, flw(number - REG_FPR0, 0, DEBUG_RAM_START + 16)); + cache_set32(target, i++, flw(number - GDB_REGNO_FPR0, 0, DEBUG_RAM_START + 16)); } else { - cache_set32(target, i++, fld(number - REG_FPR0, 0, DEBUG_RAM_START + 16)); + cache_set32(target, i++, fld(number - GDB_REGNO_FPR0, 0, DEBUG_RAM_START + 16)); } cache_set_jump(target, i++); - } else if (number >= REG_CSR0 && number <= REG_CSR4095) { + } else if (number >= GDB_REGNO_CSR0 && number <= GDB_REGNO_CSR4095) { cache_set_load(target, 0, S0, SLOT0); - cache_set32(target, 1, csrw(S0, number - REG_CSR0)); + cache_set32(target, 1, csrw(S0, number - GDB_REGNO_CSR0)); cache_set_jump(target, 2); - if (number == REG_MSTATUS) { + if (number == GDB_REGNO_MSTATUS) { info->mstatus_actual = value; } - } else if (number == REG_PRIV) { + } else if (number == GDB_REGNO_PRIV) { info->dcsr = set_field(info->dcsr, DCSR_PRV, value); return ERROR_OK; } else { @@ -1482,16 +1470,16 @@ static int init_target(struct command_context *cmd_ctx, target->reg_cache = calloc(1, sizeof(*target->reg_cache)); target->reg_cache->name = "RISC-V registers"; - target->reg_cache->num_regs = REG_COUNT; + target->reg_cache->num_regs = GDB_REGNO_COUNT; - target->reg_cache->reg_list = calloc(REG_COUNT, sizeof(struct reg)); + target->reg_cache->reg_list = calloc(GDB_REGNO_COUNT, sizeof(struct reg)); const unsigned int max_reg_name_len = 12; - info->reg_names = calloc(1, REG_COUNT * max_reg_name_len); + info->reg_names = calloc(1, GDB_REGNO_COUNT * max_reg_name_len); char *reg_name = info->reg_names; info->reg_values = NULL; - for (unsigned int i = 0; i < REG_COUNT; i++) { + for (unsigned int i = 0; i < GDB_REGNO_COUNT; i++) { struct reg *r = &target->reg_cache->reg_list[i]; r->number = i; r->caller_save = true; @@ -1500,22 +1488,22 @@ static int init_target(struct command_context *cmd_ctx, r->exist = true; r->type = &riscv_reg_arch_type; r->arch_info = target; - if (i <= REG_XPR31) { + if (i <= GDB_REGNO_XPR31) { sprintf(reg_name, "x%d", i); - } else if (i == REG_PC) { + } else if (i == GDB_REGNO_PC) { sprintf(reg_name, "pc"); - } else if (i >= REG_FPR0 && i <= REG_FPR31) { - sprintf(reg_name, "f%d", i - REG_FPR0); - } else if (i >= REG_CSR0 && i <= REG_CSR4095) { - sprintf(reg_name, "csr%d", i - REG_CSR0); - } else if (i == REG_PRIV) { + } else if (i >= GDB_REGNO_FPR0 && i <= GDB_REGNO_FPR31) { + sprintf(reg_name, "f%d", i - GDB_REGNO_FPR0); + } else if (i >= GDB_REGNO_CSR0 && i <= GDB_REGNO_CSR4095) { + sprintf(reg_name, "csr%d", i - GDB_REGNO_CSR0); + } else if (i == GDB_REGNO_PRIV) { sprintf(reg_name, "priv"); } if (reg_name[0]) { r->name = reg_name; } reg_name += strlen(reg_name) + 1; - assert(reg_name < info->reg_names + REG_COUNT * max_reg_name_len); + assert(reg_name < info->reg_names + GDB_REGNO_COUNT * max_reg_name_len); } return ERROR_OK; @@ -1580,7 +1568,7 @@ static int step(struct target *target, int current, target_addr_t address, LOG_WARNING("Asked to resume at 32-bit PC on %d-bit target.", riscv_xlen(target)); } - int result = register_write(target, REG_PC, address); + int result = register_write(target, GDB_REGNO_PC, address); if (result != ERROR_OK) return result; } @@ -2007,7 +1995,7 @@ static int riscv011_resume(struct target *target, int current, LOG_WARNING("Asked to resume at 32-bit PC on %d-bit target.", riscv_xlen(target)); } - int result = register_write(target, REG_PC, address); + int result = register_write(target, GDB_REGNO_PC, address); if (result != ERROR_OK) return result; } diff --git a/src/target/riscv/riscv-013.c b/src/target/riscv/riscv-013.c index 9d7d77b..f17ef72 100644 --- a/src/target/riscv/riscv-013.c +++ b/src/target/riscv/riscv-013.c @@ -1732,7 +1732,7 @@ static riscv_reg_t riscv013_get_register(struct target *target, int hid, int rid LOG_DEBUG("read PC from DPC: 0x%016" PRIx64, out); } else if (rid == GDB_REGNO_PRIV) { uint64_t dcsr; - register_read_direct(target, &dcsr, CSR_DCSR); + register_read_direct(target, &dcsr, GDB_REGNO_DCSR); buf_set_u64((unsigned char *)&out, 0, 8, get_field(dcsr, CSR_DCSR_PRV)); } else { int result = register_read_direct(target, &out, rid); @@ -1766,9 +1766,9 @@ static void riscv013_set_register(struct target *target, int hid, int rid, uint6 assert(value == actual_value); } else if (rid == GDB_REGNO_PRIV) { uint64_t dcsr; - register_read_direct(target, &dcsr, CSR_DCSR); + register_read_direct(target, &dcsr, GDB_REGNO_DCSR); dcsr = set_field(dcsr, CSR_DCSR_PRV, value); - register_write_direct(target, CSR_DCSR, dcsr); + register_write_direct(target, GDB_REGNO_DCSR, dcsr); } else { register_write_direct(target, rid, value); } |