aboutsummaryrefslogtreecommitdiff
path: root/target/riscv
diff options
context:
space:
mode:
Diffstat (limited to 'target/riscv')
-rw-r--r--target/riscv/cpu.c2
-rw-r--r--target/riscv/cpu.h7
-rw-r--r--target/riscv/cpu_helper.c28
-rw-r--r--target/riscv/csr.c5
-rw-r--r--target/riscv/gdbstub.c36
-rw-r--r--target/riscv/pmp.c13
6 files changed, 76 insertions, 15 deletions
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index f13e298..3939963 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -484,7 +484,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data)
cc->gdb_stop_before_watchpoint = true;
cc->disas_set_info = riscv_cpu_disas_set_info;
#ifndef CONFIG_USER_ONLY
- cc->do_unassigned_access = riscv_cpu_unassigned_access;
+ cc->do_transaction_failed = riscv_cpu_do_transaction_failed;
cc->do_unaligned_access = riscv_cpu_do_unaligned_access;
cc->get_phys_page_debug = riscv_cpu_get_phys_page_debug;
#endif
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 124ed33..8c64c68 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -264,8 +264,11 @@ void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
-void riscv_cpu_unassigned_access(CPUState *cpu, hwaddr addr, bool is_write,
- bool is_exec, int unused, unsigned size);
+void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
+ vaddr addr, unsigned size,
+ MMUAccessType access_type,
+ int mmu_idx, MemTxAttrs attrs,
+ MemTxResult response, uintptr_t retaddr);
char *riscv_isa_string(RISCVCPU *cpu);
void riscv_cpu_list(void);
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 87dd6a6..f13131a 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -169,7 +169,8 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
/* NOTE: the env->pc value visible here will not be
* correct, but the value visible to the exception handler
* (riscv_cpu_do_interrupt) is correct */
-
+ MemTxResult res;
+ MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
int mode = mmu_idx;
if (mode == PRV_M && access_type != MMU_INST_FETCH) {
@@ -256,11 +257,16 @@ restart:
1 << MMU_DATA_LOAD, PRV_S)) {
return TRANSLATE_PMP_FAIL;
}
+
#if defined(TARGET_RISCV32)
- target_ulong pte = ldl_phys(cs->as, pte_addr);
+ target_ulong pte = address_space_ldl(cs->as, pte_addr, attrs, &res);
#elif defined(TARGET_RISCV64)
- target_ulong pte = ldq_phys(cs->as, pte_addr);
+ target_ulong pte = address_space_ldq(cs->as, pte_addr, attrs, &res);
#endif
+ if (res != MEMTX_OK) {
+ return TRANSLATE_FAIL;
+ }
+
hwaddr ppn = pte >> PTE_PPN_SHIFT;
if (!(pte & PTE_V)) {
@@ -402,20 +408,23 @@ hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
return phys_addr;
}
-void riscv_cpu_unassigned_access(CPUState *cs, hwaddr addr, bool is_write,
- bool is_exec, int unused, unsigned size)
+void riscv_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
+ vaddr addr, unsigned size,
+ MMUAccessType access_type,
+ int mmu_idx, MemTxAttrs attrs,
+ MemTxResult response, uintptr_t retaddr)
{
RISCVCPU *cpu = RISCV_CPU(cs);
CPURISCVState *env = &cpu->env;
- if (is_write) {
+ if (access_type == MMU_DATA_STORE) {
cs->exception_index = RISCV_EXCP_STORE_AMO_ACCESS_FAULT;
} else {
cs->exception_index = RISCV_EXCP_LOAD_ACCESS_FAULT;
}
env->badaddr = addr;
- riscv_raise_exception(&cpu->env, cs->exception_index, GETPC());
+ riscv_raise_exception(&cpu->env, cs->exception_index, retaddr);
}
void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
@@ -446,9 +455,9 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr)
{
-#ifndef CONFIG_USER_ONLY
RISCVCPU *cpu = RISCV_CPU(cs);
CPURISCVState *env = &cpu->env;
+#ifndef CONFIG_USER_ONLY
hwaddr pa = 0;
int prot;
bool pmp_violation = false;
@@ -499,7 +508,10 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
case MMU_DATA_STORE:
cs->exception_index = RISCV_EXCP_STORE_PAGE_FAULT;
break;
+ default:
+ g_assert_not_reached();
}
+ env->badaddr = address;
cpu_loop_exit_restore(cs, retaddr);
#endif
}
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index f767ad2..974c9c2 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -801,7 +801,10 @@ int riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value,
#if !defined(CONFIG_USER_ONLY)
int csr_priv = get_field(csrno, 0x300);
int read_only = get_field(csrno, 0xC00) == 3;
- if ((write_mask && read_only) || (env->priv < csr_priv)) {
+ if ((!env->debugger) && (env->priv < csr_priv)) {
+ return -1;
+ }
+ if (write_mask && read_only) {
return -1;
}
#endif
diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index ded140e..1a7947e 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -373,6 +373,32 @@ static int riscv_gdb_set_csr(CPURISCVState *env, uint8_t *mem_buf, int n)
return 0;
}
+static int riscv_gdb_get_virtual(CPURISCVState *cs, uint8_t *mem_buf, int n)
+{
+ if (n == 0) {
+#ifdef CONFIG_USER_ONLY
+ return gdb_get_regl(mem_buf, 0);
+#else
+ return gdb_get_regl(mem_buf, cs->priv);
+#endif
+ }
+ return 0;
+}
+
+static int riscv_gdb_set_virtual(CPURISCVState *cs, uint8_t *mem_buf, int n)
+{
+ if (n == 0) {
+#ifndef CONFIG_USER_ONLY
+ cs->priv = ldtul_p(mem_buf) & 0x3;
+ if (cs->priv == PRV_H) {
+ cs->priv = PRV_S;
+ }
+#endif
+ return sizeof(target_ulong);
+ }
+ return 0;
+}
+
void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
{
RISCVCPU *cpu = RISCV_CPU(cs);
@@ -384,7 +410,10 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
}
gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
- 4096, "riscv-32bit-csr.xml", 0);
+ 240, "riscv-32bit-csr.xml", 0);
+
+ gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual,
+ 1, "riscv-32bit-virtual.xml", 0);
#elif defined(TARGET_RISCV64)
if (env->misa & RVF) {
gdb_register_coprocessor(cs, riscv_gdb_get_fpu, riscv_gdb_set_fpu,
@@ -392,6 +421,9 @@ void riscv_cpu_register_gdb_regs_for_features(CPUState *cs)
}
gdb_register_coprocessor(cs, riscv_gdb_get_csr, riscv_gdb_set_csr,
- 4096, "riscv-64bit-csr.xml", 0);
+ 240, "riscv-64bit-csr.xml", 0);
+
+ gdb_register_coprocessor(cs, riscv_gdb_get_virtual, riscv_gdb_set_virtual,
+ 1, "riscv-64bit-virtual.xml", 0);
#endif
}
diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
index d4f1007..0e6b640 100644
--- a/target/riscv/pmp.c
+++ b/target/riscv/pmp.c
@@ -223,6 +223,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
{
int i = 0;
int ret = -1;
+ int pmp_size = 0;
target_ulong s = 0;
target_ulong e = 0;
pmp_priv_t allowed_privs = 0;
@@ -232,11 +233,21 @@ bool pmp_hart_has_privs(CPURISCVState *env, target_ulong addr,
return true;
}
+ /*
+ * if size is unknown (0), assume that all bytes
+ * from addr to the end of the page will be accessed.
+ */
+ if (size == 0) {
+ pmp_size = -(addr | TARGET_PAGE_MASK);
+ } else {
+ pmp_size = size;
+ }
+
/* 1.10 draft priv spec states there is an implicit order
from low to high */
for (i = 0; i < MAX_RISCV_PMPS; i++) {
s = pmp_is_in_range(env, i, addr);
- e = pmp_is_in_range(env, i, addr + size - 1);
+ e = pmp_is_in_range(env, i, addr + pmp_size - 1);
/* partially inside */
if ((s + e) == 1) {