diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-05-08 13:34:03 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-05-08 13:34:03 +0100 |
commit | 3add3f7edccf1526b0a562a294c2749fd7385c15 (patch) | |
tree | 0fc95e08c68e9536e225d8d776c72a6bf5b4834a /target | |
parent | 302a84e878e89e11531eb4dff51156e3bee39c49 (diff) | |
parent | 5aec3247c190f10654250203a1742490ae7343a2 (diff) |
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.c | 2 | ||||
-rw-r--r-- | target/riscv/cpu.h | 8 | ||||
-rw-r--r-- | target/riscv/helper.c | 8 | ||||
-rw-r--r-- | target/riscv/op_helper.c | 143 | ||||
-rw-r--r-- | target/riscv/translate.c | 3 |
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); |