diff options
Diffstat (limited to 'target')
-rw-r--r-- | target/arm/helper.c | 2 | ||||
-rw-r--r-- | target/arm/kvm.c | 38 | ||||
-rw-r--r-- | target/arm/trace-events | 3 | ||||
-rw-r--r-- | target/arm/translate-a64.c | 12 | ||||
-rw-r--r-- | target/arm/translate.c | 17 | ||||
-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 |
10 files changed, 182 insertions, 54 deletions
diff --git a/target/arm/helper.c b/target/arm/helper.c index 52a88e0297..0fef5d4d06 100644 --- a/target/arm/helper.c +++ b/target/arm/helper.c @@ -5347,7 +5347,7 @@ void register_cp_regs_for_features(ARMCPU *cpu) for (r = id_cp_reginfo; r->type != ARM_CP_SENTINEL; r++) { r->access = PL1_RW; } - id_tlbtr_reginfo.access = PL1_RW; + id_mpuir_reginfo.access = PL1_RW; id_tlbtr_reginfo.access = PL1_RW; } if (arm_feature(env, ARM_FEATURE_V8)) { diff --git a/target/arm/kvm.c b/target/arm/kvm.c index ecc39ac295..5141d0adc5 100644 --- a/target/arm/kvm.c +++ b/target/arm/kvm.c @@ -20,8 +20,10 @@ #include "sysemu/kvm.h" #include "kvm_arm.h" #include "cpu.h" +#include "trace.h" #include "internals.h" #include "hw/arm/arm.h" +#include "hw/pci/pci.h" #include "exec/memattrs.h" #include "exec/address-spaces.h" #include "hw/boards.h" @@ -649,7 +651,41 @@ int kvm_arm_vgic_probe(void) int kvm_arch_fixup_msi_route(struct kvm_irq_routing_entry *route, uint64_t address, uint32_t data, PCIDevice *dev) { - return 0; + AddressSpace *as = pci_device_iommu_address_space(dev); + hwaddr xlat, len, doorbell_gpa; + MemoryRegionSection mrs; + MemoryRegion *mr; + int ret = 1; + + if (as == &address_space_memory) { + return 0; + } + + /* MSI doorbell address is translated by an IOMMU */ + + rcu_read_lock(); + mr = address_space_translate(as, address, &xlat, &len, true); + if (!mr) { + goto unlock; + } + mrs = memory_region_find(mr, xlat, 1); + if (!mrs.mr) { + goto unlock; + } + + doorbell_gpa = mrs.offset_within_address_space; + memory_region_unref(mrs.mr); + + route->u.msi.address_lo = doorbell_gpa; + route->u.msi.address_hi = doorbell_gpa >> 32; + + trace_kvm_arm_fixup_msi_route(address, doorbell_gpa); + + ret = 0; + +unlock: + rcu_read_unlock(); + return ret; } int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route, diff --git a/target/arm/trace-events b/target/arm/trace-events index 9e37131115..6b759f9d4f 100644 --- a/target/arm/trace-events +++ b/target/arm/trace-events @@ -8,3 +8,6 @@ arm_gt_tval_write(int timer, uint64_t value) "gt_tval_write: timer %d value 0x%" arm_gt_ctl_write(int timer, uint64_t value) "gt_ctl_write: timer %d value 0x%" PRIx64 arm_gt_imask_toggle(int timer, int irqstate) "gt_ctl_write: timer %d IMASK toggle, new irqstate %d" arm_gt_cntvoff_write(uint64_t value) "gt_cntvoff_write: value 0x%" PRIx64 + +# target/arm/kvm.c +kvm_arm_fixup_msi_route(uint64_t iova, uint64_t gpa) "MSI iova = 0x%"PRIx64" is translated into 0x%"PRIx64 diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c index bff4e13bf6..6d49f30b4a 100644 --- a/target/arm/translate-a64.c +++ b/target/arm/translate-a64.c @@ -9019,11 +9019,7 @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u, unallocated_encoding(s); return; } - - if (size > 3 && !is_q) { - unallocated_encoding(s); - return; - } + tcg_debug_assert(size <= 3); if (!fp_access_check(s)) { return; @@ -11477,7 +11473,11 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) /* All 64-bit element operations can be shared with scalar 2misc */ int pass; - for (pass = 0; pass < (is_q ? 2 : 1); pass++) { + /* Coverity claims (size == 3 && !is_q) has been eliminated + * from all paths leading to here. + */ + tcg_debug_assert(is_q); + for (pass = 0; pass < 2; pass++) { TCGv_i64 tcg_op = tcg_temp_new_i64(); TCGv_i64 tcg_res = tcg_temp_new_i64(); diff --git a/target/arm/translate.c b/target/arm/translate.c index 9bc2ce1a0b..ad208867a7 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -10795,8 +10795,23 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn) /* Coprocessor. */ if (arm_dc_feature(s, ARM_FEATURE_M)) { /* We don't currently implement M profile FP support, - * so this entire space should give a NOCP fault. + * so this entire space should give a NOCP fault, with + * the exception of the v8M VLLDM and VLSTM insns, which + * must be NOPs in Secure state and UNDEF in Nonsecure state. */ + if (arm_dc_feature(s, ARM_FEATURE_V8) && + (insn & 0xffa00f00) == 0xec200a00) { + /* 0b1110_1100_0x1x_xxxx_xxxx_1010_xxxx_xxxx + * - VLLDM, VLSTM + * We choose to UNDEF if the RAZ bits are non-zero. + */ + if (!s->v8m_secure || (insn & 0x0040f0ff)) { + goto illegal_op; + } + /* Just NOP since FP support is not implemented */ + break; + } + /* All other insns: NOCP */ gen_exception_insn(s, 4, EXCP_NOCP, syn_uncategorized(), default_exception_el(s)); break; 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); |