aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Newsome <tim@sifive.com>2017-10-04 12:52:21 -0700
committerGitHub <noreply@github.com>2017-10-04 12:52:21 -0700
commitabe7eba25a7e8ae0c9daae6785ef2d204b626825 (patch)
tree527431161b87560b0ad228a2a4bd09aab5d6b6dc
parenta3c26250bf3a319e0241daa7feb5ea155279fb29 (diff)
parente64bb8c44a6e2b6b9b39426c4c77e00edceac5aa (diff)
downloadriscv-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.h2
-rw-r--r--src/target/riscv/riscv-011.c96
-rw-r--r--src/target/riscv/riscv-013.c6
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);
}