summaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2018-05-08 13:34:03 +0100
committerPeter Maydell <peter.maydell@linaro.org>2018-05-08 13:34:03 +0100
commit3add3f7edccf1526b0a562a294c2749fd7385c15 (patch)
tree0fc95e08c68e9536e225d8d776c72a6bf5b4834a /target
parent302a84e878e89e11531eb4dff51156e3bee39c49 (diff)
parent5aec3247c190f10654250203a1742490ae7343a2 (diff)
downloadqemu-3add3f7edccf1526b0a562a294c2749fd7385c15.tar.gz
Merge remote-tracking branch 'remotes/riscv/tags/riscv-qemu-2.13-pull-20180506' into staging
RISC-V: QEMU 2.13 Privileged ISA emulation updates Several code cleanups, minor specification conformance changes, fixes to make ROM read-only and add device-tree size checks. * Honour privileged ISA v1.10 counter enable CSRs. * Implements WARL behavior for CSRs that don't support writes * Past behavior of raising traps was non-conformant with the RISC-V Privileged ISA Specification v1.10. * Allow S-mode access to sstatus.MXR when priv ISA >= v1.10 * Sets mtval/stval to zero on exceptions without addresses * Past behavior of leaving the last value was non-conformant with the RISC-V Privileged ISA Specition v1.10. mtval/stval must be set on all exceptions; to zero if not supported. * Make ROMs read-only and implement device-tree size checks * Uses memory_region_init_rom and rom_add_blob_fixed_as * Adds hexidecimal instruction bytes to disassembly output. * Fixes missing break statement for rv128 disassembly. * Several code cleanups * Replacing hard-coded constants with enums * Dead-code elimination This is an incremental pull that contains 20 reviewed changes out of 38 changes currently queued in the qemu-2.13-for-upstream branch. # gpg: Signature made Sun 06 May 2018 00:27:37 BST # gpg: using DSA key 6BF1D7B357EF3E4F # gpg: Good signature from "Michael Clark <michaeljclark@mac.com>" # gpg: aka "Michael Clark <mjc@sifive.com>" # gpg: aka "Michael Clark <michael@metaparadigm.com>" # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 7C99 930E B17C D8BA 073D 5EFA 6BF1 D7B3 57EF 3E4F * remotes/riscv/tags/riscv-qemu-2.13-pull-20180506: RISC-V: Mark ROM read-only after copying in code RISC-V: No traps on writes to misa,minstret,mcycle RISC-V: Make mtvec/stvec ignore vectored traps RISC-V: Add mcycle/minstret support for -icount auto RISC-V: Use [ms]counteren CSRs when priv ISA >= v1.10 RISC-V: Allow S-mode mxr access when priv ISA >= v1.10 RISC-V: Clear mtval/stval on exceptions without info RISC-V: Hardwire satp to 0 for no-mmu case RISC-V: Update E and I extension order RISC-V: Remove erroneous comment from translate.c RISC-V: Remove EM_RISCV ELF_MACHINE indirection RISC-V: Make virt header comment title consistent RISC-V: Make some header guards more specific RISC-V: Fix missing break statement in disassembler RISC-V: Include instruction hex in disassembly RISC-V: Remove unused class definitions RISC-V: Remove identity_translate from load_elf RISC-V: Use ROM base address and size from memmap RISC-V: Make virt board description match spike RISC-V: Replace hardcoded constants with enum values Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/riscv/cpu.c2
-rw-r--r--target/riscv/cpu.h8
-rw-r--r--target/riscv/helper.c8
-rw-r--r--target/riscv/op_helper.c143
-rw-r--r--target/riscv/translate.c3
5 files changed, 119 insertions, 45 deletions
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 5a527fbba0..4e5a56d4e3 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -26,7 +26,7 @@
/* RISC-V CPU definitions */
-static const char riscv_exts[26] = "IMAFDQECLBJTPVNSUHKORWXYZG";
+static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
const char * const riscv_int_regnames[] = {
"zero", "ra ", "sp ", "gp ", "tp ", "t0 ", "t1 ", "t2 ",
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 41e06ac0f9..34abc383e3 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -34,7 +34,6 @@
#define TCG_GUEST_DEFAULT_MO 0
-#define ELF_MACHINE EM_RISCV
#define CPUArchState struct CPURISCVState
#include "qemu-common.h"
@@ -72,6 +71,7 @@
#define RV(x) ((target_ulong)1 << (x - 'A'))
#define RVI RV('I')
+#define RVE RV('E') /* E and I are mutually exclusive */
#define RVM RV('M')
#define RVA RV('A')
#define RVF RV('F')
@@ -151,10 +151,8 @@ struct CPURISCVState {
target_ulong mcause;
target_ulong mtval; /* since: priv-1.10.0 */
- uint32_t mucounteren;
- uint32_t mscounteren;
- target_ulong scounteren; /* since: priv-1.10.0 */
- target_ulong mcounteren; /* since: priv-1.10.0 */
+ target_ulong scounteren;
+ target_ulong mcounteren;
target_ulong sscratch;
target_ulong mscratch;
diff --git a/target/riscv/helper.c b/target/riscv/helper.c
index 02cbcea2b7..95889f23b9 100644
--- a/target/riscv/helper.c
+++ b/target/riscv/helper.c
@@ -466,6 +466,10 @@ void riscv_cpu_do_interrupt(CPUState *cs)
": badaddr 0x" TARGET_FMT_lx, env->mhartid, env->badaddr);
}
env->sbadaddr = env->badaddr;
+ } else {
+ /* otherwise we must clear sbadaddr/stval
+ * todo: support populating stval on illegal instructions */
+ env->sbadaddr = 0;
}
target_ulong s = env->mstatus;
@@ -487,6 +491,10 @@ void riscv_cpu_do_interrupt(CPUState *cs)
": badaddr 0x" TARGET_FMT_lx, env->mhartid, env->badaddr);
}
env->mbadaddr = env->badaddr;
+ } else {
+ /* otherwise we must clear mbadaddr/mtval
+ * todo: support populating mtval on illegal instructions */
+ env->mbadaddr = 0;
}
target_ulong s = env->mstatus;
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index 7c6068bac9..3abf52453c 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -213,28 +213,41 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
break;
}
case CSR_MINSTRET:
- qemu_log_mask(LOG_UNIMP, "CSR_MINSTRET: write not implemented");
- goto do_illegal;
+ /* minstret is WARL so unsupported writes are ignored */
+ break;
case CSR_MCYCLE:
- qemu_log_mask(LOG_UNIMP, "CSR_MCYCLE: write not implemented");
- goto do_illegal;
+ /* mcycle is WARL so unsupported writes are ignored */
+ break;
+#if defined(TARGET_RISCV32)
case CSR_MINSTRETH:
- qemu_log_mask(LOG_UNIMP, "CSR_MINSTRETH: write not implemented");
- goto do_illegal;
+ /* minstreth is WARL so unsupported writes are ignored */
+ break;
case CSR_MCYCLEH:
- qemu_log_mask(LOG_UNIMP, "CSR_MCYCLEH: write not implemented");
- goto do_illegal;
- case CSR_MUCOUNTEREN:
- env->mucounteren = val_to_write;
+ /* mcycleh is WARL so unsupported writes are ignored */
break;
+#endif
+ case CSR_MUCOUNTEREN:
+ if (env->priv_ver <= PRIV_VERSION_1_09_1) {
+ env->scounteren = val_to_write;
+ break;
+ } else {
+ goto do_illegal;
+ }
case CSR_MSCOUNTEREN:
- env->mscounteren = val_to_write;
- break;
+ if (env->priv_ver <= PRIV_VERSION_1_09_1) {
+ env->mcounteren = val_to_write;
+ break;
+ } else {
+ goto do_illegal;
+ }
case CSR_SSTATUS: {
target_ulong ms = env->mstatus;
target_ulong mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE
| SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS
- | SSTATUS_SUM | SSTATUS_MXR | SSTATUS_SD;
+ | SSTATUS_SUM | SSTATUS_SD;
+ if (env->priv_ver >= PRIV_VERSION_1_10_0) {
+ mask |= SSTATUS_MXR;
+ }
ms = (ms & ~mask) | (val_to_write & mask);
csr_write_helper(env, ms, CSR_MSTATUS);
break;
@@ -255,7 +268,7 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
}
case CSR_SATP: /* CSR_SPTBR */ {
if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
- goto do_illegal;
+ break;
}
if (env->priv_ver <= PRIV_VERSION_1_09_1 && (val_to_write ^ env->sptbr))
{
@@ -276,15 +289,20 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
env->sepc = val_to_write;
break;
case CSR_STVEC:
- if (val_to_write & 1) {
+ /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
+ if ((val_to_write & 3) == 0) {
+ env->stvec = val_to_write >> 2 << 2;
+ } else {
qemu_log_mask(LOG_UNIMP, "CSR_STVEC: vectored traps not supported");
- goto do_illegal;
}
- env->stvec = val_to_write >> 2 << 2;
break;
case CSR_SCOUNTEREN:
- env->scounteren = val_to_write;
- break;
+ if (env->priv_ver >= PRIV_VERSION_1_10_0) {
+ env->scounteren = val_to_write;
+ break;
+ } else {
+ goto do_illegal;
+ }
case CSR_SSCRATCH:
env->sscratch = val_to_write;
break;
@@ -298,15 +316,20 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
env->mepc = val_to_write;
break;
case CSR_MTVEC:
- if (val_to_write & 1) {
+ /* bits [1:0] indicate mode; 0 = direct, 1 = vectored, 2 >= reserved */
+ if ((val_to_write & 3) == 0) {
+ env->mtvec = val_to_write >> 2 << 2;
+ } else {
qemu_log_mask(LOG_UNIMP, "CSR_MTVEC: vectored traps not supported");
- goto do_illegal;
}
- env->mtvec = val_to_write >> 2 << 2;
break;
case CSR_MCOUNTEREN:
- env->mcounteren = val_to_write;
- break;
+ if (env->priv_ver >= PRIV_VERSION_1_10_0) {
+ env->mcounteren = val_to_write;
+ break;
+ } else {
+ goto do_illegal;
+ }
case CSR_MSCRATCH:
env->mscratch = val_to_write;
break;
@@ -316,10 +339,9 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
case CSR_MBADADDR:
env->mbadaddr = val_to_write;
break;
- case CSR_MISA: {
- qemu_log_mask(LOG_UNIMP, "CSR_MISA: misa writes not supported");
- goto do_illegal;
- }
+ case CSR_MISA:
+ /* misa is WARL so unsupported writes are ignored */
+ break;
case CSR_PMPCFG0:
case CSR_PMPCFG1:
case CSR_PMPCFG2:
@@ -344,6 +366,8 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
case CSR_PMPADDR15:
pmpaddr_csr_write(env, csrno - CSR_PMPADDR0, val_to_write);
break;
+#endif
+#if !defined(CONFIG_USER_ONLY)
do_illegal:
#endif
default:
@@ -359,8 +383,8 @@ void csr_write_helper(CPURISCVState *env, target_ulong val_to_write,
target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno)
{
#ifndef CONFIG_USER_ONLY
- target_ulong ctr_en = env->priv == PRV_U ? env->mucounteren :
- env->priv == PRV_S ? env->mscounteren : -1U;
+ target_ulong ctr_en = env->priv == PRV_U ? env->scounteren :
+ env->priv == PRV_S ? env->mcounteren : -1U;
#else
target_ulong ctr_en = -1;
#endif
@@ -413,35 +437,67 @@ target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno)
case CSR_INSTRET:
case CSR_CYCLE:
if (ctr_ok) {
+#if !defined(CONFIG_USER_ONLY)
+ if (use_icount) {
+ return cpu_get_icount();
+ } else {
+ return cpu_get_host_ticks();
+ }
+#else
return cpu_get_host_ticks();
+#endif
}
break;
#if defined(TARGET_RISCV32)
case CSR_INSTRETH:
case CSR_CYCLEH:
if (ctr_ok) {
+#if !defined(CONFIG_USER_ONLY)
+ if (use_icount) {
+ return cpu_get_icount() >> 32;
+ } else {
+ return cpu_get_host_ticks() >> 32;
+ }
+#else
return cpu_get_host_ticks() >> 32;
+#endif
}
break;
#endif
#ifndef CONFIG_USER_ONLY
case CSR_MINSTRET:
case CSR_MCYCLE:
- return cpu_get_host_ticks();
+ if (use_icount) {
+ return cpu_get_icount();
+ } else {
+ return cpu_get_host_ticks();
+ }
case CSR_MINSTRETH:
case CSR_MCYCLEH:
#if defined(TARGET_RISCV32)
- return cpu_get_host_ticks() >> 32;
+ if (use_icount) {
+ return cpu_get_icount() >> 32;
+ } else {
+ return cpu_get_host_ticks() >> 32;
+ }
#endif
break;
case CSR_MUCOUNTEREN:
- return env->mucounteren;
+ if (env->priv_ver <= PRIV_VERSION_1_09_1) {
+ return env->scounteren;
+ } else {
+ break; /* illegal instruction */
+ }
case CSR_MSCOUNTEREN:
- return env->mscounteren;
+ if (env->priv_ver <= PRIV_VERSION_1_09_1) {
+ return env->mcounteren;
+ } else {
+ break; /* illegal instruction */
+ }
case CSR_SSTATUS: {
target_ulong mask = SSTATUS_SIE | SSTATUS_SPIE | SSTATUS_UIE
| SSTATUS_UPIE | SSTATUS_SPP | SSTATUS_FS | SSTATUS_XS
- | SSTATUS_SUM | SSTATUS_SD;
+ | SSTATUS_SUM | SSTATUS_SD;
if (env->priv_ver >= PRIV_VERSION_1_10_0) {
mask |= SSTATUS_MXR;
}
@@ -462,10 +518,17 @@ target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno)
case CSR_STVEC:
return env->stvec;
case CSR_SCOUNTEREN:
- return env->scounteren;
+ if (env->priv_ver >= PRIV_VERSION_1_10_0) {
+ return env->scounteren;
+ } else {
+ break; /* illegal instruction */
+ }
case CSR_SCAUSE:
return env->scause;
- case CSR_SPTBR:
+ case CSR_SATP: /* CSR_SPTBR */
+ if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
+ return 0;
+ }
if (env->priv_ver >= PRIV_VERSION_1_10_0) {
return env->satp;
} else {
@@ -504,7 +567,11 @@ target_ulong csr_read_helper(CPURISCVState *env, target_ulong csrno)
case CSR_MTVEC:
return env->mtvec;
case CSR_MCOUNTEREN:
- return env->mcounteren;
+ if (env->priv_ver >= PRIV_VERSION_1_10_0) {
+ return env->mcounteren;
+ } else {
+ break; /* illegal instruction */
+ }
case CSR_MEDELEG:
return env->medeleg;
case CSR_MIDELEG:
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 808eab7f50..c0e6a044d3 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -280,7 +280,6 @@ static void gen_arith(DisasContext *ctx, uint32_t opc, int rd, int rs1,
tcg_gen_andi_tl(source2, source2, 0x1F);
tcg_gen_sar_tl(source1, source1, source2);
break;
- /* fall through to SRA */
#endif
case OPC_RISC_SRA:
tcg_gen_andi_tl(source2, source2, TARGET_LONG_BITS - 1);
@@ -1391,6 +1390,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
break;
default:
tcg_gen_movi_tl(imm_rs1, rs1);
+ gen_io_start();
switch (opc) {
case OPC_RISC_CSRRW:
gen_helper_csrrw(dest, cpu_env, source1, csr_store);
@@ -1414,6 +1414,7 @@ static void gen_system(CPURISCVState *env, DisasContext *ctx, uint32_t opc,
gen_exception_illegal(ctx);
return;
}
+ gen_io_end();
gen_set_gpr(rd, dest);
/* end tb since we may be changing priv modes, to get mmu_index right */
tcg_gen_movi_tl(cpu_pc, ctx->next_pc);