diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c index 9f4c36e965..c6f13f647e 100644 --- a/hw/intc/riscv_aclint.c +++ b/hw/intc/riscv_aclint.c @@ -297,7 +297,12 @@ static void riscv_aclint_mtimer_realize(DeviceState *dev, Error **errp) s->timecmp = g_new0(uint64_t, s->num_harts); /* Claim timer interrupt bits */ for (i = 0; i < s->num_harts; i++) { - RISCVCPU *cpu = RISCV_CPU(cpu_by_arch_id(s->hartid_base + i)); + CPUState *cpu_by_hartid = cpu_by_arch_id(s->hartid_base + i); + if (cpu_by_hartid == NULL) { + /* Valid for sparse hart layouts - skip this hart ID */ + continue; + } + RISCVCPU *cpu = RISCV_CPU(cpu_by_hartid); if (riscv_cpu_claim_interrupts(cpu, MIP_MTIP) < 0) { error_report("MTIP already claimed"); exit(1); @@ -489,7 +494,12 @@ static void riscv_aclint_swi_realize(DeviceState *dev, Error **errp) /* Claim software interrupt bits */ for (i = 0; i < swi->num_harts; i++) { - RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(swi->hartid_base + i)); + CPUState *cpu_by_hartid = cpu_by_arch_id(swi->hartid_base + i); + if (cpu_by_hartid == NULL) { + /* Valid for sparse hart layouts - skip this hart ID */ + continue; + } + RISCVCPU *cpu = RISCV_CPU(cpu_by_hartid); /* We don't claim mip.SSIP because it is writable by software */ if (riscv_cpu_claim_interrupts(cpu, swi->sswi ? 0 : MIP_MSIP) < 0) { error_report("MSIP already claimed"); @@ -553,6 +563,10 @@ DeviceState *riscv_aclint_swi_create(hwaddr addr, uint32_t hartid_base, for (i = 0; i < num_harts; i++) { CPUState *cpu = cpu_by_arch_id(hartid_base + i); + if (cpu == NULL) { + /* Valid for sparse hart layouts - skip this hart ID */ + continue; + } RISCVCPU *rvcpu = RISCV_CPU(cpu); qdev_connect_gpio_out(dev, i, diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c index a1d9fa5085..a2041e7022 100644 --- a/hw/intc/riscv_aplic.c +++ b/hw/intc/riscv_aplic.c @@ -96,7 +96,7 @@ (APLIC_xMSICFGADDR_PPN_HHX_MASK(__hhxw) << \ APLIC_xMSICFGADDR_PPN_HHX_SHIFT(__hhxs)) -#define APLIC_xMSICFGADDRH_VALID_MASK \ +#define APLIC_MMSICFGADDRH_VALID_MASK \ (APLIC_xMSICFGADDRH_L | \ (APLIC_xMSICFGADDRH_HHXS_MASK << APLIC_xMSICFGADDRH_HHXS_SHIFT) | \ (APLIC_xMSICFGADDRH_LHXS_MASK << APLIC_xMSICFGADDRH_LHXS_SHIFT) | \ @@ -104,6 +104,10 @@ (APLIC_xMSICFGADDRH_LHXW_MASK << APLIC_xMSICFGADDRH_LHXW_SHIFT) | \ APLIC_xMSICFGADDRH_BAPPN_MASK) +#define APLIC_SMSICFGADDRH_VALID_MASK \ + ((APLIC_xMSICFGADDRH_LHXS_MASK << APLIC_xMSICFGADDRH_LHXS_SHIFT) | \ + APLIC_xMSICFGADDRH_BAPPN_MASK) + #define APLIC_SETIP_BASE 0x1c00 #define APLIC_SETIPNUM 0x1cdc @@ -184,7 +188,7 @@ void riscv_aplic_set_kvm_msicfgaddr(RISCVAPLICState *aplic, hwaddr addr) addr >>= APLIC_xMSICFGADDR_PPN_SHIFT; aplic->kvm_msicfgaddr = extract64(addr, 0, 32); aplic->kvm_msicfgaddrH = extract64(addr, 32, 32) & - APLIC_xMSICFGADDRH_VALID_MASK; + APLIC_MMSICFGADDRH_VALID_MASK; } #endif } @@ -409,13 +413,8 @@ static void riscv_aplic_msi_send(RISCVAPLICState *aplic, msicfgaddr = aplic->kvm_msicfgaddr; msicfgaddrH = ((uint64_t)aplic->kvm_msicfgaddrH << 32); } else { - if (aplic->mmode) { - msicfgaddr = aplic_m->mmsicfgaddr; - msicfgaddrH = aplic_m->mmsicfgaddrH; - } else { - msicfgaddr = aplic_m->smsicfgaddr; - msicfgaddrH = aplic_m->smsicfgaddrH; - } + msicfgaddr = aplic_m->mmsicfgaddr; + msicfgaddrH = aplic_m->mmsicfgaddrH; } lhxs = (msicfgaddrH >> APLIC_xMSICFGADDRH_LHXS_SHIFT) & @@ -427,6 +426,14 @@ static void riscv_aplic_msi_send(RISCVAPLICState *aplic, hhxw = (msicfgaddrH >> APLIC_xMSICFGADDRH_HHXW_SHIFT) & APLIC_xMSICFGADDRH_HHXW_MASK; + if (!aplic->kvm_splitmode && !aplic->mmode) { + msicfgaddrH = aplic_m->smsicfgaddrH; + msicfgaddr = aplic_m->smsicfgaddr; + + lhxs = (msicfgaddrH >> APLIC_xMSICFGADDRH_LHXS_SHIFT) & + APLIC_xMSICFGADDRH_LHXS_MASK; + } + group_idx = hart_idx >> lhxw; addr = msicfgaddr; @@ -771,7 +778,7 @@ static void riscv_aplic_write(void *opaque, hwaddr addr, uint64_t value, } else if (aplic->mmode && aplic->msimode && (addr == APLIC_MMSICFGADDRH)) { if (!(aplic->mmsicfgaddrH & APLIC_xMSICFGADDRH_L)) { - aplic->mmsicfgaddrH = value & APLIC_xMSICFGADDRH_VALID_MASK; + aplic->mmsicfgaddrH = value & APLIC_MMSICFGADDRH_VALID_MASK; } } else if (aplic->mmode && aplic->msimode && (addr == APLIC_SMSICFGADDR)) { @@ -792,7 +799,7 @@ static void riscv_aplic_write(void *opaque, hwaddr addr, uint64_t value, (addr == APLIC_SMSICFGADDRH)) { if (aplic->num_children && !(aplic->mmsicfgaddrH & APLIC_xMSICFGADDRH_L)) { - aplic->smsicfgaddrH = value & APLIC_xMSICFGADDRH_VALID_MASK; + aplic->smsicfgaddrH = value & APLIC_SMSICFGADDRH_VALID_MASK; } } else if ((APLIC_SETIP_BASE <= addr) && (addr < (APLIC_SETIP_BASE + aplic->bitfield_words * 4))) { @@ -903,9 +910,12 @@ static void riscv_aplic_realize(DeviceState *dev, Error **errp) if (!aplic->msimode) { /* Claim the CPU interrupt to be triggered by this APLIC */ for (i = 0; i < aplic->num_harts; i++) { - RISCVCPU *cpu; - - cpu = RISCV_CPU(cpu_by_arch_id(aplic->hartid_base + i)); + CPUState *temp = cpu_by_arch_id(aplic->hartid_base + i); + if (temp == NULL) { + /* Valid for sparse hart layouts - skip this hart ID */ + continue; + } + RISCVCPU *cpu = RISCV_CPU(temp); if (riscv_cpu_claim_interrupts(cpu, (aplic->mmode) ? MIP_MEIP : MIP_SEIP) < 0) { error_report("%s already claimed", @@ -1088,6 +1098,10 @@ DeviceState *riscv_aplic_create(hwaddr addr, hwaddr size, if (!msimode) { for (i = 0; i < num_harts; i++) { CPUState *cpu = cpu_by_arch_id(hartid_base + i); + if (cpu == NULL) { + /* Valid for sparse hart layouts - skip this hart ID */ + continue; + } qdev_connect_gpio_out_named(dev, NULL, i, qdev_get_gpio_in(DEVICE(cpu), diff --git a/hw/net/cadence_gem.c b/hw/net/cadence_gem.c index 44446666de..44896f1801 100644 --- a/hw/net/cadence_gem.c +++ b/hw/net/cadence_gem.c @@ -1477,7 +1477,10 @@ static void gem_reset(DeviceState *d) s->regs[R_TXPARTIALSF] = 0x000003ff; s->regs[R_RXPARTIALSF] = 0x000003ff; s->regs[R_MODID] = s->revision; - s->regs[R_DESCONF] = 0x02D00111; + s->regs[R_DESCONF] = 0x02D00110; + if (!s->pcs_enabled) { + s->regs[R_DESCONF] |= 0x00000001; + } s->regs[R_DESCONF2] = 0x2ab10000 | s->jumbo_max_len; s->regs[R_DESCONF5] = 0x002f2045; s->regs[R_DESCONF6] = R_DESCONF6_DMA_ADDR_64B_MASK; @@ -1541,12 +1544,20 @@ static void gem_handle_phy_access(CadenceGEMState *s) { uint32_t val = s->regs[R_PHYMNTNC]; uint32_t phy_addr, reg_num; + CadenceGEMState *ps = s; + uint32_t op; phy_addr = FIELD_EX32(val, PHYMNTNC, PHY_ADDR); + op = FIELD_EX32(val, PHYMNTNC, OP); - if (phy_addr != s->phy_addr) { - /* no phy at this address */ - if (FIELD_EX32(val, PHYMNTNC, OP) == MDIO_OP_READ) { + /* Switch phy to consumer interface if there is an address match */ + if (s->phy_consumer && phy_addr == s->phy_consumer->phy_addr) { + ps = s->phy_consumer; + } + + if (!s->phy_connected || phy_addr != ps->phy_addr) { + /* phy not connected or no phy at this address */ + if (op == MDIO_OP_READ) { s->regs[R_PHYMNTNC] = FIELD_DP32(val, PHYMNTNC, DATA, 0xffff); } return; @@ -1554,14 +1565,14 @@ static void gem_handle_phy_access(CadenceGEMState *s) reg_num = FIELD_EX32(val, PHYMNTNC, REG_ADDR); - switch (FIELD_EX32(val, PHYMNTNC, OP)) { + switch (op) { case MDIO_OP_READ: s->regs[R_PHYMNTNC] = FIELD_DP32(val, PHYMNTNC, DATA, - gem_phy_read(s, reg_num)); + gem_phy_read(ps, reg_num)); break; case MDIO_OP_WRITE: - gem_phy_write(s, reg_num, val); + gem_phy_write(ps, reg_num, val); break; default: @@ -1813,6 +1824,12 @@ static const Property gem_properties[] = { num_type2_screeners, 4), DEFINE_PROP_UINT16("jumbo-max-len", CadenceGEMState, jumbo_max_len, 10240), + DEFINE_PROP_BOOL("pcs-enabled", CadenceGEMState, + pcs_enabled, false), + DEFINE_PROP_BOOL("phy-connected", CadenceGEMState, phy_connected, true), + DEFINE_PROP_LINK("phy-consumer", CadenceGEMState, phy_consumer, + TYPE_CADENCE_GEM, CadenceGEMState *), + DEFINE_PROP_LINK("dma", CadenceGEMState, dma_mr, TYPE_MEMORY_REGION, MemoryRegion *), }; diff --git a/hw/riscv/microchip_pfsoc.c b/hw/riscv/microchip_pfsoc.c index 2e74783fce..4c939d8e96 100644 --- a/hw/riscv/microchip_pfsoc.c +++ b/hw/riscv/microchip_pfsoc.c @@ -414,6 +414,9 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp) object_property_set_int(OBJECT(&s->gem0), "revision", GEM_REVISION, errp); object_property_set_int(OBJECT(&s->gem0), "phy-addr", 8, errp); + object_property_set_bool(OBJECT(&s->gem0), "phy-connected", false, errp); + object_property_set_bool(OBJECT(&s->gem0), "pcs-enabled", true, errp); + sysbus_realize(SYS_BUS_DEVICE(&s->gem0), errp); sysbus_mmio_map(SYS_BUS_DEVICE(&s->gem0), 0, memmap[MICROCHIP_PFSOC_GEM0].base); @@ -422,6 +425,9 @@ static void microchip_pfsoc_soc_realize(DeviceState *dev, Error **errp) object_property_set_int(OBJECT(&s->gem1), "revision", GEM_REVISION, errp); object_property_set_int(OBJECT(&s->gem1), "phy-addr", 9, errp); + object_property_set_link(OBJECT(&s->gem1), "phy-consumer", + OBJECT(&s->gem0), errp); + object_property_set_bool(OBJECT(&s->gem1), "pcs-enabled", true, errp); sysbus_realize(SYS_BUS_DEVICE(&s->gem1), errp); sysbus_mmio_map(SYS_BUS_DEVICE(&s->gem1), 0, memmap[MICROCHIP_PFSOC_GEM1].base); diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c index d69f942cfb..3e1ed209ca 100644 --- a/hw/riscv/sifive_u.c +++ b/hw/riscv/sifive_u.c @@ -176,7 +176,7 @@ static void create_fdt(SiFiveUState *s, const MemMapEntry *memmap, if (is_32_bit) { qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv32"); } else { - qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv48"); + qemu_fdt_setprop_string(fdt, nodename, "mmu-type", "riscv,sv39"); } riscv_isa_write_fdt(&s->soc.u_cpus.harts[cpu - 1], fdt, nodename); } else { diff --git a/include/hw/net/cadence_gem.h b/include/hw/net/cadence_gem.h index 91ebb5c8ae..e63941f18f 100644 --- a/include/hw/net/cadence_gem.h +++ b/include/hw/net/cadence_gem.h @@ -62,6 +62,7 @@ struct CadenceGEMState { uint8_t num_type2_screeners; uint32_t revision; uint16_t jumbo_max_len; + bool pcs_enabled; /* GEM registers backing store */ uint32_t regs[CADENCE_GEM_MAXREG]; @@ -81,6 +82,9 @@ struct CadenceGEMState { uint8_t phy_loop; /* Are we in phy loopback? */ + bool phy_connected; /* true if connected */ + struct CadenceGEMState *phy_consumer; + /* The current DMA descriptor pointers */ uint32_t rx_desc_addr[MAX_PRIORITY_QUEUES]; uint32_t tx_desc_addr[MAX_PRIORITY_QUEUES]; diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index a877018ab0..73d4280d7c 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1121,6 +1121,7 @@ static void riscv_cpu_init(Object *obj) cpu->cfg.cbop_blocksize = 64; cpu->cfg.cboz_blocksize = 64; cpu->cfg.pmp_regions = 16; + cpu->cfg.pmp_granularity = MIN_RISCV_PMP_GRANULARITY; cpu->env.vext_ver = VEXT_VERSION_1_00_0; cpu->cfg.max_satp_mode = -1; @@ -1606,6 +1607,43 @@ static const PropertyInfo prop_num_pmp_regions = { .set = prop_num_pmp_regions_set, }; +static void prop_pmp_granularity_set(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + RISCVCPU *cpu = RISCV_CPU(obj); + uint32_t value; + + visit_type_uint32(v, name, &value, errp); + + if ((value < MIN_RISCV_PMP_GRANULARITY) && (value & (value - 1))) { + error_setg(errp, "PMP granularity must be a power of 2 and at least %d", + MIN_RISCV_PMP_GRANULARITY); + return; + } + + if (cpu->cfg.pmp_granularity != value && riscv_cpu_is_vendor(obj)) { + cpu_set_prop_err(cpu, name, errp); + return; + } + + cpu_option_add_user_setting(name, value); + cpu->cfg.pmp_granularity = value; +} + +static void prop_pmp_granularity_get(Object *obj, Visitor *v, const char *name, + void *opaque, Error **errp) +{ + uint32_t value = RISCV_CPU(obj)->cfg.pmp_granularity; + + visit_type_uint32(v, name, &value, errp); +} + +static const PropertyInfo prop_pmp_granularity = { + .description = "pmp-granularity", + .get = prop_pmp_granularity_get, + .set = prop_pmp_granularity_set, +}; + static int priv_spec_from_str(const char *priv_spec_str) { int priv_version = -1; @@ -2606,6 +2644,7 @@ static const Property riscv_cpu_properties[] = { {.name = "mmu", .info = &prop_mmu}, {.name = "pmp", .info = &prop_pmp}, {.name = "num-pmp-regions", .info = &prop_num_pmp_regions}, + {.name = "pmp-granularity", .info = &prop_pmp_granularity}, {.name = "priv_spec", .info = &prop_priv_spec}, {.name = "vext_spec", .info = &prop_vext_spec}, diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 4c13012442..36e7f10037 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -176,6 +176,7 @@ extern RISCVCPUImpliedExtsRule *riscv_multi_ext_implied_rules[]; #define MAX_RISCV_PMPS (64) #define OLD_MAX_RISCV_PMPS (16) +#define MIN_RISCV_PMP_GRANULARITY 4 #if !defined(CONFIG_USER_ONLY) #include "pmp.h" diff --git a/target/riscv/cpu_cfg_fields.h.inc b/target/riscv/cpu_cfg_fields.h.inc index e2d116f0df..a154ecdc79 100644 --- a/target/riscv/cpu_cfg_fields.h.inc +++ b/target/riscv/cpu_cfg_fields.h.inc @@ -166,6 +166,7 @@ TYPED_FIELD(uint16_t, cbom_blocksize, 0) TYPED_FIELD(uint16_t, cbop_blocksize, 0) TYPED_FIELD(uint16_t, cboz_blocksize, 0) TYPED_FIELD(uint8_t, pmp_regions, 0) +TYPED_FIELD(uint32_t, pmp_granularity, 0) TYPED_FIELD(int8_t, max_satp_mode, -1) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 3479a62cc7..360db133e2 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -443,8 +443,7 @@ int riscv_cpu_mirq_pending(CPURISCVState *env) int riscv_cpu_sirq_pending(CPURISCVState *env) { - uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg & - ~(MIP_VSSIP | MIP_VSTIP | MIP_VSEIP); + uint64_t irqs = riscv_cpu_all_pending(env) & env->mideleg & ~env->hideleg; uint64_t irqs_f = env->mvip & env->mvien & ~env->mideleg & env->sie; return riscv_cpu_pending_to_irq(env, IRQ_S_EXT, IPRIO_DEFAULT_S, diff --git a/target/riscv/insn_trans/trans_rva.c.inc b/target/riscv/insn_trans/trans_rva.c.inc index 9cf3ae8019..a7a3278d24 100644 --- a/target/riscv/insn_trans/trans_rva.c.inc +++ b/target/riscv/insn_trans/trans_rva.c.inc @@ -34,6 +34,9 @@ static bool gen_lr(DisasContext *ctx, arg_atomic *a, MemOp mop) { TCGv src1; + mop |= MO_ALIGN; + mop |= mo_endian(ctx); + decode_save_opc(ctx, 0); src1 = get_address(ctx, a->rs1, 0); if (a->rl) { @@ -61,6 +64,9 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop) TCGLabel *l1 = gen_new_label(); TCGLabel *l2 = gen_new_label(); + mop |= MO_ALIGN; + mop |= mo_endian(ctx); + decode_save_opc(ctx, 0); src1 = get_address(ctx, a->rs1, 0); tcg_gen_brcond_tl(TCG_COND_NE, load_res, src1, l1); @@ -99,142 +105,142 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop) static bool trans_lr_w(DisasContext *ctx, arg_lr_w *a) { REQUIRE_A_OR_ZALRSC(ctx); - return gen_lr(ctx, a, (MO_ALIGN | MO_TESL)); + return gen_lr(ctx, a, MO_SL); } static bool trans_sc_w(DisasContext *ctx, arg_sc_w *a) { REQUIRE_A_OR_ZALRSC(ctx); - return gen_sc(ctx, a, (MO_ALIGN | MO_TESL)); + return gen_sc(ctx, a, MO_SL); } static bool trans_amoswap_w(DisasContext *ctx, arg_amoswap_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_TESL); + return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_SL); } static bool trans_amoadd_w(DisasContext *ctx, arg_amoadd_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_TESL); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_SL); } static bool trans_amoxor_w(DisasContext *ctx, arg_amoxor_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_TESL); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_SL); } static bool trans_amoand_w(DisasContext *ctx, arg_amoand_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_TESL); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_SL); } static bool trans_amoor_w(DisasContext *ctx, arg_amoor_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_TESL); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_SL); } static bool trans_amomin_w(DisasContext *ctx, arg_amomin_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_TESL); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_SL); } static bool trans_amomax_w(DisasContext *ctx, arg_amomax_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_TESL); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_SL); } static bool trans_amominu_w(DisasContext *ctx, arg_amominu_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_TESL); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_SL); } static bool trans_amomaxu_w(DisasContext *ctx, arg_amomaxu_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_TESL); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_SL); } static bool trans_lr_d(DisasContext *ctx, arg_lr_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZALRSC(ctx); - return gen_lr(ctx, a, MO_ALIGN | MO_TEUQ); + return gen_lr(ctx, a, MO_UQ); } static bool trans_sc_d(DisasContext *ctx, arg_sc_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZALRSC(ctx); - return gen_sc(ctx, a, (MO_ALIGN | MO_TEUQ)); + return gen_sc(ctx, a, MO_UQ); } static bool trans_amoswap_d(DisasContext *ctx, arg_amoswap_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_TEUQ); + return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_UQ); } static bool trans_amoadd_d(DisasContext *ctx, arg_amoadd_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_TEUQ); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_UQ); } static bool trans_amoxor_d(DisasContext *ctx, arg_amoxor_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_TEUQ); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_UQ); } static bool trans_amoand_d(DisasContext *ctx, arg_amoand_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_TEUQ); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_UQ); } static bool trans_amoor_d(DisasContext *ctx, arg_amoor_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_TEUQ); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_UQ); } static bool trans_amomin_d(DisasContext *ctx, arg_amomin_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_TEUQ); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_UQ); } static bool trans_amomax_d(DisasContext *ctx, arg_amomax_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_TEUQ); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_UQ); } static bool trans_amominu_d(DisasContext *ctx, arg_amominu_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_TEUQ); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_UQ); } static bool trans_amomaxu_d(DisasContext *ctx, arg_amomaxu_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_TEUQ); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_UQ); } diff --git a/target/riscv/insn_trans/trans_rvd.c.inc b/target/riscv/insn_trans/trans_rvd.c.inc index 30883ea37c..ffea0c2a1f 100644 --- a/target/riscv/insn_trans/trans_rvd.c.inc +++ b/target/riscv/insn_trans/trans_rvd.c.inc @@ -42,7 +42,7 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a) { TCGv addr; - MemOp memop = MO_TEUQ; + MemOp memop = MO_UQ; REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); @@ -60,6 +60,7 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a) } else { memop |= MO_ATOM_IFALIGN; } + memop |= mo_endian(ctx); decode_save_opc(ctx, 0); addr = get_address(ctx, a->rs1, a->imm); @@ -72,7 +73,7 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a) static bool trans_fsd(DisasContext *ctx, arg_fsd *a) { TCGv addr; - MemOp memop = MO_TEUQ; + MemOp memop = MO_UQ; REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); @@ -84,6 +85,7 @@ static bool trans_fsd(DisasContext *ctx, arg_fsd *a) } else { memop |= MO_ATOM_IFALIGN; } + memop |= mo_endian(ctx); decode_save_opc(ctx, 0); addr = get_address(ctx, a->rs1, a->imm); diff --git a/target/riscv/insn_trans/trans_rvf.c.inc b/target/riscv/insn_trans/trans_rvf.c.inc index ed73afe089..89fb0f604a 100644 --- a/target/riscv/insn_trans/trans_rvf.c.inc +++ b/target/riscv/insn_trans/trans_rvf.c.inc @@ -43,11 +43,12 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a) { TCGv_i64 dest; TCGv addr; - MemOp memop = MO_TEUL; + MemOp memop = MO_UL; REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); + memop |= mo_endian(ctx); if (ctx->cfg_ptr->ext_zama16b) { memop |= MO_ATOM_WITHIN16; } @@ -65,11 +66,12 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a) static bool trans_fsw(DisasContext *ctx, arg_fsw *a) { TCGv addr; - MemOp memop = MO_TEUL; + MemOp memop = MO_UL; REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); + memop |= mo_endian(ctx); if (ctx->cfg_ptr->ext_zama16b) { memop |= MO_ATOM_WITHIN16; } diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index b9c7160468..54b9b4f241 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -402,6 +402,7 @@ static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop) { bool out; + memop |= mo_endian(ctx); if (ctx->cfg_ptr->ext_zama16b) { memop |= MO_ATOM_WITHIN16; } @@ -426,24 +427,24 @@ static bool trans_lb(DisasContext *ctx, arg_lb *a) static bool trans_lh(DisasContext *ctx, arg_lh *a) { - return gen_load(ctx, a, MO_TESW); + return gen_load(ctx, a, MO_SW); } static bool trans_lw(DisasContext *ctx, arg_lw *a) { - return gen_load(ctx, a, MO_TESL); + return gen_load(ctx, a, MO_SL); } static bool trans_ld(DisasContext *ctx, arg_ld *a) { REQUIRE_64_OR_128BIT(ctx); - return gen_load(ctx, a, MO_TESQ); + return gen_load(ctx, a, MO_SQ); } static bool trans_lq(DisasContext *ctx, arg_lq *a) { REQUIRE_128BIT(ctx); - return gen_load(ctx, a, MO_TEUO); + return gen_load(ctx, a, MO_UO); } static bool trans_lbu(DisasContext *ctx, arg_lbu *a) @@ -453,19 +454,19 @@ static bool trans_lbu(DisasContext *ctx, arg_lbu *a) static bool trans_lhu(DisasContext *ctx, arg_lhu *a) { - return gen_load(ctx, a, MO_TEUW); + return gen_load(ctx, a, MO_UW); } static bool trans_lwu(DisasContext *ctx, arg_lwu *a) { REQUIRE_64_OR_128BIT(ctx); - return gen_load(ctx, a, MO_TEUL); + return gen_load(ctx, a, MO_UL); } static bool trans_ldu(DisasContext *ctx, arg_ldu *a) { REQUIRE_128BIT(ctx); - return gen_load(ctx, a, MO_TEUQ); + return gen_load(ctx, a, MO_UQ); } static bool gen_store_tl(DisasContext *ctx, arg_sb *a, MemOp memop) @@ -503,6 +504,7 @@ static bool gen_store_i128(DisasContext *ctx, arg_sb *a, MemOp memop) static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop) { + memop |= mo_endian(ctx); if (ctx->cfg_ptr->ext_zama16b) { memop |= MO_ATOM_WITHIN16; } @@ -521,24 +523,24 @@ static bool trans_sb(DisasContext *ctx, arg_sb *a) static bool trans_sh(DisasContext *ctx, arg_sh *a) { - return gen_store(ctx, a, MO_TESW); + return gen_store(ctx, a, MO_SW); } static bool trans_sw(DisasContext *ctx, arg_sw *a) { - return gen_store(ctx, a, MO_TESL); + return gen_store(ctx, a, MO_SL); } static bool trans_sd(DisasContext *ctx, arg_sd *a) { REQUIRE_64_OR_128BIT(ctx); - return gen_store(ctx, a, MO_TEUQ); + return gen_store(ctx, a, MO_UQ); } static bool trans_sq(DisasContext *ctx, arg_sq *a) { REQUIRE_128BIT(ctx); - return gen_store(ctx, a, MO_TEUO); + return gen_store(ctx, a, MO_UO); } static bool trans_addd(DisasContext *ctx, arg_addd *a) diff --git a/target/riscv/insn_trans/trans_rvzabha.c.inc b/target/riscv/insn_trans/trans_rvzabha.c.inc index ce8edcba62..302c63f2a3 100644 --- a/target/riscv/insn_trans/trans_rvzabha.c.inc +++ b/target/riscv/insn_trans/trans_rvzabha.c.inc @@ -79,55 +79,55 @@ static bool trans_amomaxu_b(DisasContext *ctx, arg_amomaxu_b *a) static bool trans_amoswap_h(DisasContext *ctx, arg_amoswap_h *a) { REQUIRE_ZABHA(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_TESW); + return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_SW); } static bool trans_amoadd_h(DisasContext *ctx, arg_amoadd_h *a) { REQUIRE_ZABHA(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_TESW); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_SW); } static bool trans_amoxor_h(DisasContext *ctx, arg_amoxor_h *a) { REQUIRE_ZABHA(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_TESW); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_SW); } static bool trans_amoand_h(DisasContext *ctx, arg_amoand_h *a) { REQUIRE_ZABHA(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_TESW); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_SW); } static bool trans_amoor_h(DisasContext *ctx, arg_amoor_h *a) { REQUIRE_ZABHA(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_TESW); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_SW); } static bool trans_amomin_h(DisasContext *ctx, arg_amomin_h *a) { REQUIRE_ZABHA(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_TESW); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_SW); } static bool trans_amomax_h(DisasContext *ctx, arg_amomax_h *a) { REQUIRE_ZABHA(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_TESW); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_SW); } static bool trans_amominu_h(DisasContext *ctx, arg_amominu_h *a) { REQUIRE_ZABHA(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_TESW); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_SW); } static bool trans_amomaxu_h(DisasContext *ctx, arg_amomaxu_h *a) { REQUIRE_ZABHA(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_TESW); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_SW); } static bool trans_amocas_b(DisasContext *ctx, arg_amocas_b *a) @@ -141,5 +141,5 @@ static bool trans_amocas_h(DisasContext *ctx, arg_amocas_h *a) { REQUIRE_ZACAS(ctx); REQUIRE_ZABHA(ctx); - return gen_cmpxchg(ctx, a, MO_ALIGN | MO_TESW); + return gen_cmpxchg(ctx, a, MO_ALIGN | MO_SW); } diff --git a/target/riscv/insn_trans/trans_rvzacas.c.inc b/target/riscv/insn_trans/trans_rvzacas.c.inc index 15e688a033..8d94b83ce9 100644 --- a/target/riscv/insn_trans/trans_rvzacas.c.inc +++ b/target/riscv/insn_trans/trans_rvzacas.c.inc @@ -25,7 +25,7 @@ static bool trans_amocas_w(DisasContext *ctx, arg_amocas_w *a) { REQUIRE_ZACAS(ctx); - return gen_cmpxchg(ctx, a, MO_ALIGN | MO_TESL); + return gen_cmpxchg(ctx, a, MO_ALIGN | MO_SL); } static TCGv_i64 get_gpr_pair(DisasContext *ctx, int reg_num) @@ -76,6 +76,7 @@ static bool gen_cmpxchg64(DisasContext *ctx, arg_atomic *a, MemOp mop) TCGv src1 = get_address(ctx, a->rs1, 0); TCGv_i64 src2 = get_gpr_pair(ctx, a->rs2); + mop |= mo_endian(ctx); decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); tcg_gen_atomic_cmpxchg_i64(dest, src1, dest, src2, ctx->mem_idx, mop); @@ -88,10 +89,10 @@ static bool trans_amocas_d(DisasContext *ctx, arg_amocas_d *a) REQUIRE_ZACAS(ctx); switch (get_ol(ctx)) { case MXL_RV32: - return gen_cmpxchg64(ctx, a, MO_ALIGN | MO_TEUQ); + return gen_cmpxchg64(ctx, a, MO_ALIGN | MO_UQ); case MXL_RV64: case MXL_RV128: - return gen_cmpxchg(ctx, a, MO_ALIGN | MO_TEUQ); + return gen_cmpxchg(ctx, a, MO_ALIGN | MO_UQ); default: g_assert_not_reached(); } @@ -118,12 +119,13 @@ static bool trans_amocas_q(DisasContext *ctx, arg_amocas_q *a) TCGv_i64 src2h = get_gpr(ctx, a->rs2 == 0 ? 0 : a->rs2 + 1, EXT_NONE); TCGv_i64 destl = get_gpr(ctx, a->rd, EXT_NONE); TCGv_i64 desth = get_gpr(ctx, a->rd == 0 ? 0 : a->rd + 1, EXT_NONE); + MemOp memop = MO_ALIGN | MO_UO; + memop |= mo_endian(ctx); tcg_gen_concat_i64_i128(src2, src2l, src2h); tcg_gen_concat_i64_i128(dest, destl, desth); decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); - tcg_gen_atomic_cmpxchg_i128(dest, src1, dest, src2, ctx->mem_idx, - (MO_ALIGN | MO_TEUO)); + tcg_gen_atomic_cmpxchg_i128(dest, src1, dest, src2, ctx->mem_idx, memop); tcg_gen_extr_i128_i64(destl, desth, dest); diff --git a/target/riscv/insn_trans/trans_rvzce.c.inc b/target/riscv/insn_trans/trans_rvzce.c.inc index dd15af0f54..0d3ba40e52 100644 --- a/target/riscv/insn_trans/trans_rvzce.c.inc +++ b/target/riscv/insn_trans/trans_rvzce.c.inc @@ -88,13 +88,13 @@ static bool trans_c_lbu(DisasContext *ctx, arg_c_lbu *a) static bool trans_c_lhu(DisasContext *ctx, arg_c_lhu *a) { REQUIRE_ZCB(ctx); - return gen_load(ctx, a, MO_TEUW); + return gen_load(ctx, a, MO_UW); } static bool trans_c_lh(DisasContext *ctx, arg_c_lh *a) { REQUIRE_ZCB(ctx); - return gen_load(ctx, a, MO_TESW); + return gen_load(ctx, a, MO_SW); } static bool trans_c_sb(DisasContext *ctx, arg_c_sb *a) @@ -106,7 +106,7 @@ static bool trans_c_sb(DisasContext *ctx, arg_c_sb *a) static bool trans_c_sh(DisasContext *ctx, arg_c_sh *a) { REQUIRE_ZCB(ctx); - return gen_store(ctx, a, MO_TEUW); + return gen_store(ctx, a, MO_UW); } #define X_S0 8 @@ -175,7 +175,7 @@ static bool gen_pop(DisasContext *ctx, arg_cmpp *a, bool ret, bool ret_val) return false; } - MemOp memop = get_ol(ctx) == MXL_RV32 ? MO_TEUL : MO_TEUQ; + MemOp memop = get_ol(ctx) == MXL_RV32 ? MO_UL : MO_UQ; int reg_size = memop_size(memop); target_ulong stack_adj = ROUND_UP(ctpop32(reg_bitmap) * reg_size, 16) + a->spimm; @@ -185,6 +185,7 @@ static bool gen_pop(DisasContext *ctx, arg_cmpp *a, bool ret, bool ret_val) tcg_gen_addi_tl(addr, sp, stack_adj - reg_size); + memop |= mo_endian(ctx); for (i = X_Sn + 11; i >= 0; i--) { if (reg_bitmap & (1 << i)) { TCGv dest = dest_gpr(ctx, i); @@ -228,7 +229,7 @@ static bool trans_cm_push(DisasContext *ctx, arg_cm_push *a) return false; } - MemOp memop = get_ol(ctx) == MXL_RV32 ? MO_TEUL : MO_TEUQ; + MemOp memop = get_ol(ctx) == MXL_RV32 ? MO_UL : MO_UQ; int reg_size = memop_size(memop); target_ulong stack_adj = ROUND_UP(ctpop32(reg_bitmap) * reg_size, 16) + a->spimm; @@ -238,6 +239,7 @@ static bool trans_cm_push(DisasContext *ctx, arg_cm_push *a) tcg_gen_subi_tl(addr, sp, reg_size); + memop |= mo_endian(ctx); for (i = X_Sn + 11; i >= 0; i--) { if (reg_bitmap & (1 << i)) { TCGv val = get_gpr(ctx, i, EXT_NONE); diff --git a/target/riscv/insn_trans/trans_rvzfh.c.inc b/target/riscv/insn_trans/trans_rvzfh.c.inc index bece48e600..791ee51f65 100644 --- a/target/riscv/insn_trans/trans_rvzfh.c.inc +++ b/target/riscv/insn_trans/trans_rvzfh.c.inc @@ -42,12 +42,14 @@ static bool trans_flh(DisasContext *ctx, arg_flh *a) { + MemOp memop = MO_UW; TCGv_i64 dest; TCGv t0; REQUIRE_FPU; REQUIRE_ZFHMIN_OR_ZFBFMIN(ctx); + memop |= mo_endian(ctx); decode_save_opc(ctx, 0); t0 = get_gpr(ctx, a->rs1, EXT_NONE); if (a->imm) { @@ -57,7 +59,7 @@ static bool trans_flh(DisasContext *ctx, arg_flh *a) } dest = cpu_fpr[a->rd]; - tcg_gen_qemu_ld_i64(dest, t0, ctx->mem_idx, MO_TEUW); + tcg_gen_qemu_ld_i64(dest, t0, ctx->mem_idx, memop); gen_nanbox_h(dest, dest); mark_fs_dirty(ctx); @@ -66,11 +68,13 @@ static bool trans_flh(DisasContext *ctx, arg_flh *a) static bool trans_fsh(DisasContext *ctx, arg_fsh *a) { + MemOp memop = MO_UW; TCGv t0; REQUIRE_FPU; REQUIRE_ZFHMIN_OR_ZFBFMIN(ctx); + memop |= mo_endian(ctx); decode_save_opc(ctx, 0); t0 = get_gpr(ctx, a->rs1, EXT_NONE); if (a->imm) { @@ -79,7 +83,7 @@ static bool trans_fsh(DisasContext *ctx, arg_fsh *a) t0 = temp; } - tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, MO_TEUW); + tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], t0, ctx->mem_idx, memop); return true; } diff --git a/target/riscv/insn_trans/trans_rvzicfiss.c.inc b/target/riscv/insn_trans/trans_rvzicfiss.c.inc index f4a1c12ca0..0b6ad57965 100644 --- a/target/riscv/insn_trans/trans_rvzicfiss.c.inc +++ b/target/riscv/insn_trans/trans_rvzicfiss.c.inc @@ -100,12 +100,13 @@ static bool trans_ssamoswap_w(DisasContext *ctx, arg_amoswap_w *a) TCGv dest = dest_gpr(ctx, a->rd); TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE); + MemOp memop = MO_ALIGN | MO_SL; decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); src1 = get_address(ctx, a->rs1, 0); - tcg_gen_atomic_xchg_tl(dest, src1, src2, SS_MMU_INDEX(ctx), - (MO_ALIGN | MO_TESL)); + memop |= mo_endian(ctx); + tcg_gen_atomic_xchg_tl(dest, src1, src2, SS_MMU_INDEX(ctx), memop); gen_set_gpr(ctx, a->rd, dest); return true; } @@ -129,12 +130,13 @@ static bool trans_ssamoswap_d(DisasContext *ctx, arg_amoswap_w *a) TCGv dest = dest_gpr(ctx, a->rd); TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE); + MemOp memop = MO_ALIGN | MO_SQ; decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); src1 = get_address(ctx, a->rs1, 0); - tcg_gen_atomic_xchg_tl(dest, src1, src2, SS_MMU_INDEX(ctx), - (MO_ALIGN | MO_TESQ)); + memop |= mo_endian(ctx); + tcg_gen_atomic_xchg_tl(dest, src1, src2, SS_MMU_INDEX(ctx), memop); gen_set_gpr(ctx, a->rd, dest); return true; } diff --git a/target/riscv/insn_trans/trans_xthead.c.inc b/target/riscv/insn_trans/trans_xthead.c.inc index 22488412d4..f8b95c6498 100644 --- a/target/riscv/insn_trans/trans_xthead.c.inc +++ b/target/riscv/insn_trans/trans_xthead.c.inc @@ -349,6 +349,7 @@ static bool gen_fload_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop, TCGv_i64 rd = cpu_fpr[a->rd]; TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs); + memop |= mo_endian(ctx); tcg_gen_qemu_ld_i64(rd, addr, ctx->mem_idx, memop); if ((memop & MO_SIZE) == MO_32) { gen_nanbox_s(rd, rd); @@ -369,6 +370,7 @@ static bool gen_fstore_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop, TCGv_i64 rd = cpu_fpr[a->rd]; TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs); + memop |= mo_endian(ctx); tcg_gen_qemu_st_i64(rd, addr, ctx->mem_idx, memop); return true; @@ -379,7 +381,7 @@ static bool trans_th_flrd(DisasContext *ctx, arg_th_memidx *a) REQUIRE_XTHEADFMEMIDX(ctx); REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - return gen_fload_idx(ctx, a, MO_TEUQ, false); + return gen_fload_idx(ctx, a, MO_UQ, false); } static bool trans_th_flrw(DisasContext *ctx, arg_th_memidx *a) @@ -387,7 +389,7 @@ static bool trans_th_flrw(DisasContext *ctx, arg_th_memidx *a) REQUIRE_XTHEADFMEMIDX(ctx); REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - return gen_fload_idx(ctx, a, MO_TEUL, false); + return gen_fload_idx(ctx, a, MO_UL, false); } static bool trans_th_flurd(DisasContext *ctx, arg_th_memidx *a) @@ -395,7 +397,7 @@ static bool trans_th_flurd(DisasContext *ctx, arg_th_memidx *a) REQUIRE_XTHEADFMEMIDX(ctx); REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - return gen_fload_idx(ctx, a, MO_TEUQ, true); + return gen_fload_idx(ctx, a, MO_UQ, true); } static bool trans_th_flurw(DisasContext *ctx, arg_th_memidx *a) @@ -403,7 +405,7 @@ static bool trans_th_flurw(DisasContext *ctx, arg_th_memidx *a) REQUIRE_XTHEADFMEMIDX(ctx); REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - return gen_fload_idx(ctx, a, MO_TEUL, true); + return gen_fload_idx(ctx, a, MO_UL, true); } static bool trans_th_fsrd(DisasContext *ctx, arg_th_memidx *a) @@ -411,7 +413,7 @@ static bool trans_th_fsrd(DisasContext *ctx, arg_th_memidx *a) REQUIRE_XTHEADFMEMIDX(ctx); REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - return gen_fstore_idx(ctx, a, MO_TEUQ, false); + return gen_fstore_idx(ctx, a, MO_UQ, false); } static bool trans_th_fsrw(DisasContext *ctx, arg_th_memidx *a) @@ -419,7 +421,7 @@ static bool trans_th_fsrw(DisasContext *ctx, arg_th_memidx *a) REQUIRE_XTHEADFMEMIDX(ctx); REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - return gen_fstore_idx(ctx, a, MO_TEUL, false); + return gen_fstore_idx(ctx, a, MO_UL, false); } static bool trans_th_fsurd(DisasContext *ctx, arg_th_memidx *a) @@ -427,7 +429,7 @@ static bool trans_th_fsurd(DisasContext *ctx, arg_th_memidx *a) REQUIRE_XTHEADFMEMIDX(ctx); REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); - return gen_fstore_idx(ctx, a, MO_TEUQ, true); + return gen_fstore_idx(ctx, a, MO_UQ, true); } static bool trans_th_fsurw(DisasContext *ctx, arg_th_memidx *a) @@ -435,7 +437,7 @@ static bool trans_th_fsurw(DisasContext *ctx, arg_th_memidx *a) REQUIRE_XTHEADFMEMIDX(ctx); REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); - return gen_fstore_idx(ctx, a, MO_TEUL, true); + return gen_fstore_idx(ctx, a, MO_UL, true); } /* XTheadFmv */ @@ -568,6 +570,7 @@ static bool gen_load_inc(DisasContext *ctx, arg_th_meminc *a, MemOp memop, TCGv rd = dest_gpr(ctx, a->rd); TCGv rs1 = get_gpr(ctx, a->rs1, EXT_NONE); + memop |= mo_endian(ctx); tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop); tcg_gen_addi_tl(rs1, rs1, imm); gen_set_gpr(ctx, a->rd, rd); @@ -588,6 +591,7 @@ static bool gen_store_inc(DisasContext *ctx, arg_th_meminc *a, MemOp memop, TCGv data = get_gpr(ctx, a->rd, EXT_NONE); TCGv rs1 = get_gpr(ctx, a->rs1, EXT_NONE); + memop |= mo_endian(ctx); tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop); tcg_gen_addi_tl(rs1, rs1, imm); gen_set_gpr(ctx, a->rs1, rs1); @@ -598,64 +602,64 @@ static bool trans_th_ldia(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); REQUIRE_64BIT(ctx); - return gen_load_inc(ctx, a, MO_TESQ, false); + return gen_load_inc(ctx, a, MO_SQ, false); } static bool trans_th_ldib(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); REQUIRE_64BIT(ctx); - return gen_load_inc(ctx, a, MO_TESQ, true); + return gen_load_inc(ctx, a, MO_SQ, true); } static bool trans_th_lwia(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_load_inc(ctx, a, MO_TESL, false); + return gen_load_inc(ctx, a, MO_SL, false); } static bool trans_th_lwib(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_load_inc(ctx, a, MO_TESL, true); + return gen_load_inc(ctx, a, MO_SL, true); } static bool trans_th_lwuia(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); REQUIRE_64BIT(ctx); - return gen_load_inc(ctx, a, MO_TEUL, false); + return gen_load_inc(ctx, a, MO_UL, false); } static bool trans_th_lwuib(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); REQUIRE_64BIT(ctx); - return gen_load_inc(ctx, a, MO_TEUL, true); + return gen_load_inc(ctx, a, MO_UL, true); } static bool trans_th_lhia(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_load_inc(ctx, a, MO_TESW, false); + return gen_load_inc(ctx, a, MO_SW, false); } static bool trans_th_lhib(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_load_inc(ctx, a, MO_TESW, true); + return gen_load_inc(ctx, a, MO_SW, true); } static bool trans_th_lhuia(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_load_inc(ctx, a, MO_TEUW, false); + return gen_load_inc(ctx, a, MO_UW, false); } static bool trans_th_lhuib(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_load_inc(ctx, a, MO_TEUW, true); + return gen_load_inc(ctx, a, MO_UW, true); } static bool trans_th_lbia(DisasContext *ctx, arg_th_meminc *a) @@ -686,38 +690,38 @@ static bool trans_th_sdia(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); REQUIRE_64BIT(ctx); - return gen_store_inc(ctx, a, MO_TESQ, false); + return gen_store_inc(ctx, a, MO_SQ, false); } static bool trans_th_sdib(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); REQUIRE_64BIT(ctx); - return gen_store_inc(ctx, a, MO_TESQ, true); + return gen_store_inc(ctx, a, MO_SQ, true); } static bool trans_th_swia(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_store_inc(ctx, a, MO_TESL, false); + return gen_store_inc(ctx, a, MO_SL, false); } static bool trans_th_swib(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_store_inc(ctx, a, MO_TESL, true); + return gen_store_inc(ctx, a, MO_SL, true); } static bool trans_th_shia(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_store_inc(ctx, a, MO_TESW, false); + return gen_store_inc(ctx, a, MO_SW, false); } static bool trans_th_shib(DisasContext *ctx, arg_th_meminc *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_store_inc(ctx, a, MO_TESW, true); + return gen_store_inc(ctx, a, MO_SW, true); } static bool trans_th_sbia(DisasContext *ctx, arg_th_meminc *a) @@ -743,6 +747,7 @@ static bool gen_load_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop, TCGv rd = dest_gpr(ctx, a->rd); TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs); + memop |= mo_endian(ctx); tcg_gen_qemu_ld_tl(rd, addr, ctx->mem_idx, memop); gen_set_gpr(ctx, a->rd, rd); @@ -760,6 +765,7 @@ static bool gen_store_idx(DisasContext *ctx, arg_th_memidx *a, MemOp memop, TCGv data = get_gpr(ctx, a->rd, EXT_NONE); TCGv addr = get_th_address_indexed(ctx, a->rs1, a->rs2, a->imm2, zext_offs); + memop |= mo_endian(ctx); tcg_gen_qemu_st_tl(data, addr, ctx->mem_idx, memop); return true; @@ -769,32 +775,32 @@ static bool trans_th_lrd(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); REQUIRE_64BIT(ctx); - return gen_load_idx(ctx, a, MO_TESQ, false); + return gen_load_idx(ctx, a, MO_SQ, false); } static bool trans_th_lrw(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_load_idx(ctx, a, MO_TESL, false); + return gen_load_idx(ctx, a, MO_SL, false); } static bool trans_th_lrwu(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); REQUIRE_64BIT(ctx); - return gen_load_idx(ctx, a, MO_TEUL, false); + return gen_load_idx(ctx, a, MO_UL, false); } static bool trans_th_lrh(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_load_idx(ctx, a, MO_TESW, false); + return gen_load_idx(ctx, a, MO_SW, false); } static bool trans_th_lrhu(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_load_idx(ctx, a, MO_TEUW, false); + return gen_load_idx(ctx, a, MO_UW, false); } static bool trans_th_lrb(DisasContext *ctx, arg_th_memidx *a) @@ -813,19 +819,19 @@ static bool trans_th_srd(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); REQUIRE_64BIT(ctx); - return gen_store_idx(ctx, a, MO_TESQ, false); + return gen_store_idx(ctx, a, MO_SQ, false); } static bool trans_th_srw(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_store_idx(ctx, a, MO_TESL, false); + return gen_store_idx(ctx, a, MO_SL, false); } static bool trans_th_srh(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_store_idx(ctx, a, MO_TESW, false); + return gen_store_idx(ctx, a, MO_SW, false); } static bool trans_th_srb(DisasContext *ctx, arg_th_memidx *a) @@ -837,32 +843,32 @@ static bool trans_th_lurd(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); REQUIRE_64BIT(ctx); - return gen_load_idx(ctx, a, MO_TESQ, true); + return gen_load_idx(ctx, a, MO_SQ, true); } static bool trans_th_lurw(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_load_idx(ctx, a, MO_TESL, true); + return gen_load_idx(ctx, a, MO_SL, true); } static bool trans_th_lurwu(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); REQUIRE_64BIT(ctx); - return gen_load_idx(ctx, a, MO_TEUL, true); + return gen_load_idx(ctx, a, MO_UL, true); } static bool trans_th_lurh(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_load_idx(ctx, a, MO_TESW, true); + return gen_load_idx(ctx, a, MO_SW, true); } static bool trans_th_lurhu(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_load_idx(ctx, a, MO_TEUW, true); + return gen_load_idx(ctx, a, MO_UW, true); } static bool trans_th_lurb(DisasContext *ctx, arg_th_memidx *a) @@ -881,19 +887,19 @@ static bool trans_th_surd(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); REQUIRE_64BIT(ctx); - return gen_store_idx(ctx, a, MO_TESQ, true); + return gen_store_idx(ctx, a, MO_SQ, true); } static bool trans_th_surw(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_store_idx(ctx, a, MO_TESL, true); + return gen_store_idx(ctx, a, MO_SL, true); } static bool trans_th_surh(DisasContext *ctx, arg_th_memidx *a) { REQUIRE_XTHEADMEMIDX(ctx); - return gen_store_idx(ctx, a, MO_TESW, true); + return gen_store_idx(ctx, a, MO_SW, true); } static bool trans_th_surb(DisasContext *ctx, arg_th_memidx *a) @@ -920,6 +926,7 @@ static bool gen_loadpair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop, addr1 = get_address(ctx, a->rs, imm); addr2 = get_address(ctx, a->rs, memop_size(memop) + imm); + memop |= mo_endian(ctx); tcg_gen_qemu_ld_tl(t1, addr1, ctx->mem_idx, memop); tcg_gen_qemu_ld_tl(t2, addr2, ctx->mem_idx, memop); gen_set_gpr(ctx, a->rd1, t1); @@ -931,19 +938,19 @@ static bool trans_th_ldd(DisasContext *ctx, arg_th_pair *a) { REQUIRE_XTHEADMEMPAIR(ctx); REQUIRE_64BIT(ctx); - return gen_loadpair_tl(ctx, a, MO_TESQ, 4); + return gen_loadpair_tl(ctx, a, MO_SQ, 4); } static bool trans_th_lwd(DisasContext *ctx, arg_th_pair *a) { REQUIRE_XTHEADMEMPAIR(ctx); - return gen_loadpair_tl(ctx, a, MO_TESL, 3); + return gen_loadpair_tl(ctx, a, MO_SL, 3); } static bool trans_th_lwud(DisasContext *ctx, arg_th_pair *a) { REQUIRE_XTHEADMEMPAIR(ctx); - return gen_loadpair_tl(ctx, a, MO_TEUL, 3); + return gen_loadpair_tl(ctx, a, MO_UL, 3); } static bool gen_storepair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop, @@ -958,6 +965,7 @@ static bool gen_storepair_tl(DisasContext *ctx, arg_th_pair *a, MemOp memop, addr1 = get_address(ctx, a->rs, imm); addr2 = get_address(ctx, a->rs, memop_size(memop) + imm); + memop |= mo_endian(ctx); tcg_gen_qemu_st_tl(data1, addr1, ctx->mem_idx, memop); tcg_gen_qemu_st_tl(data2, addr2, ctx->mem_idx, memop); return true; @@ -967,13 +975,13 @@ static bool trans_th_sdd(DisasContext *ctx, arg_th_pair *a) { REQUIRE_XTHEADMEMPAIR(ctx); REQUIRE_64BIT(ctx); - return gen_storepair_tl(ctx, a, MO_TESQ, 4); + return gen_storepair_tl(ctx, a, MO_SQ, 4); } static bool trans_th_swd(DisasContext *ctx, arg_th_pair *a) { REQUIRE_XTHEADMEMPAIR(ctx); - return gen_storepair_tl(ctx, a, MO_TESL, 3); + return gen_storepair_tl(ctx, a, MO_SL, 3); } /* XTheadSync */ diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 0dd0d59d41..000e44b2b7 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -705,6 +705,7 @@ static void kvm_riscv_reset_regs_csr(CPURISCVState *env) env->satp = 0; env->scounteren = 0; env->senvcfg = 0; + env->priv = PRV_S; } static int kvm_riscv_get_regs_fp(CPUState *cs) diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 8382aa94cb..6ccc127c30 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -28,6 +28,20 @@ #include "exec/tlb-flags.h" #include "trace.h" +#ifndef CONFIG_USER_ONLY +static inline MemOp mo_endian_env(CPURISCVState *env) +{ + /* + * A couple of bits in MSTATUS set the endianness: + * - MSTATUS_UBE (User-mode), + * - MSTATUS_SBE (Supervisor-mode), + * - MSTATUS_MBE (Machine-mode) + * but we don't implement that yet. + */ + return MO_TE; +} +#endif + /* Exceptions processing helpers */ G_NORETURN void riscv_raise_exception(CPURISCVState *env, RISCVException exception, @@ -633,7 +647,7 @@ target_ulong helper_hyp_hlv_hu(CPURISCVState *env, target_ulong addr) { uintptr_t ra = GETPC(); int mmu_idx = check_access_hlsv(env, false, ra); - MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx); + MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UW, mmu_idx); return cpu_ldw_mmu(env, adjust_addr_virt(env, addr), oi, ra); } @@ -642,7 +656,7 @@ target_ulong helper_hyp_hlv_wu(CPURISCVState *env, target_ulong addr) { uintptr_t ra = GETPC(); int mmu_idx = check_access_hlsv(env, false, ra); - MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx); + MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UL, mmu_idx); return cpu_ldl_mmu(env, adjust_addr_virt(env, addr), oi, ra); } @@ -651,7 +665,7 @@ target_ulong helper_hyp_hlv_d(CPURISCVState *env, target_ulong addr) { uintptr_t ra = GETPC(); int mmu_idx = check_access_hlsv(env, false, ra); - MemOpIdx oi = make_memop_idx(MO_TEUQ, mmu_idx); + MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UQ, mmu_idx); return cpu_ldq_mmu(env, adjust_addr_virt(env, addr), oi, ra); } @@ -669,7 +683,7 @@ void helper_hyp_hsv_h(CPURISCVState *env, target_ulong addr, target_ulong val) { uintptr_t ra = GETPC(); int mmu_idx = check_access_hlsv(env, false, ra); - MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx); + MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UW, mmu_idx); cpu_stw_mmu(env, adjust_addr_virt(env, addr), val, oi, ra); } @@ -678,7 +692,7 @@ void helper_hyp_hsv_w(CPURISCVState *env, target_ulong addr, target_ulong val) { uintptr_t ra = GETPC(); int mmu_idx = check_access_hlsv(env, false, ra); - MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx); + MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UL, mmu_idx); cpu_stl_mmu(env, adjust_addr_virt(env, addr), val, oi, ra); } @@ -687,7 +701,7 @@ void helper_hyp_hsv_d(CPURISCVState *env, target_ulong addr, target_ulong val) { uintptr_t ra = GETPC(); int mmu_idx = check_access_hlsv(env, false, ra); - MemOpIdx oi = make_memop_idx(MO_TEUQ, mmu_idx); + MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UQ, mmu_idx); cpu_stq_mmu(env, adjust_addr_virt(env, addr), val, oi, ra); } @@ -703,7 +717,7 @@ target_ulong helper_hyp_hlvx_hu(CPURISCVState *env, target_ulong addr) { uintptr_t ra = GETPC(); int mmu_idx = check_access_hlsv(env, true, ra); - MemOpIdx oi = make_memop_idx(MO_TEUW, mmu_idx); + MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UW, mmu_idx); return cpu_ldw_code_mmu(env, addr, oi, GETPC()); } @@ -712,7 +726,7 @@ target_ulong helper_hyp_hlvx_wu(CPURISCVState *env, target_ulong addr) { uintptr_t ra = GETPC(); int mmu_idx = check_access_hlsv(env, true, ra); - MemOpIdx oi = make_memop_idx(MO_TEUL, mmu_idx); + MemOpIdx oi = make_memop_idx(mo_endian_env(env) | MO_UL, mmu_idx); return cpu_ldl_code_mmu(env, addr, oi, ra); } diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c index 72f1372a49..3ef62d26ad 100644 --- a/target/riscv/pmp.c +++ b/target/riscv/pmp.c @@ -108,6 +108,17 @@ static int pmp_is_invalid_smepmp_cfg(CPURISCVState *env, uint8_t val) g_assert_not_reached(); } } +/* + * Calculate PMP granularity value 'g' + * + * The granularity value 'g' is defined as log2(granularity) - 2, where + * granularity is the minimum alignment requirement for PMP regions in bytes. + */ +static inline int pmp_get_granularity_g(CPURISCVState *env) +{ + return __builtin_ctz(riscv_cpu_cfg(env)->pmp_granularity >> 2); +} + /* * Count the number of active rules. @@ -153,6 +164,15 @@ static bool pmp_write_cfg(CPURISCVState *env, uint32_t pmp_index, uint8_t val) qemu_log_mask(LOG_GUEST_ERROR, "ignoring pmpcfg write - invalid\n"); } else { + uint8_t a_field = pmp_get_a_field(val); + /* + * When granularity g >= 1 (i.e., granularity > 4 bytes), + * the NA4 (Naturally Aligned 4-byte) mode is not selectable + */ + if ((riscv_cpu_cfg(env)->pmp_granularity > + MIN_RISCV_PMP_GRANULARITY) && (a_field == PMP_AMATCH_NA4)) { + return false; + } env->pmp_state.pmp[pmp_index].cfg_reg = val; pmp_update_rule_addr(env, pmp_index); return true; @@ -199,6 +219,7 @@ void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index) target_ulong prev_addr = 0u; hwaddr sa = 0u; hwaddr ea = 0u; + int g = pmp_get_granularity_g(env); if (pmp_index >= 1u) { prev_addr = env->pmp_state.pmp[pmp_index - 1].addr_reg; @@ -211,6 +232,11 @@ void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index) break; case PMP_AMATCH_TOR: + /* Bits pmpaddr[G-1:0] do not affect the TOR address-matching logic. */ + if (g >= 1) { + prev_addr &= ~((1ULL << g) - 1ULL); + this_addr &= ~((1ULL << g) - 1ULL); + } if (prev_addr >= this_addr) { sa = ea = 0u; break; @@ -577,6 +603,7 @@ void pmpaddr_csr_write(CPURISCVState *env, uint32_t addr_index, /* * Handle a read from a pmpaddr CSR + * Change A field of pmpcfg affects the read value of pmpaddr */ target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index) { @@ -585,6 +612,25 @@ target_ulong pmpaddr_csr_read(CPURISCVState *env, uint32_t addr_index) if (addr_index < pmp_regions) { val = env->pmp_state.pmp[addr_index].addr_reg; + int g = pmp_get_granularity_g(env); + switch (pmp_get_a_field(env->pmp_state.pmp[addr_index].cfg_reg)) { + case PMP_AMATCH_OFF: + /* fallthrough */ + case PMP_AMATCH_TOR: + /* Bit [g-1:0] read all zero */ + if (g >= 1 && g < TARGET_LONG_BITS) { + val &= ~((1ULL << g) - 1ULL); + } + break; + case PMP_AMATCH_NAPOT: + /* Bit [g-2:0] read all one */ + if (g >= 2 && g < TARGET_LONG_BITS) { + val |= ((1ULL << (g - 1)) - 1ULL); + } + break; + default: + break; + } trace_pmpaddr_csr_read(env->mhartid, addr_index, val); } else { qemu_log_mask(LOG_GUEST_ERROR, diff --git a/target/riscv/riscv-qmp-cmds.c b/target/riscv/riscv-qmp-cmds.c index c499f9b9a7..d5e9bec0f8 100644 --- a/target/riscv/riscv-qmp-cmds.c +++ b/target/riscv/riscv-qmp-cmds.c @@ -273,12 +273,13 @@ static bool reg_is_ulong_integer(CPURISCVState *env, const char *name, } for (int i = 0; i < 32; i++) { - g_autofree char *reg_name = g_strdup(reg_names[i]); - char *reg1 = strtok(reg_name, "/"); - char *reg2 = strtok(NULL, "/"); + g_auto(GStrv) reg_name = g_strsplit(reg_names[i], "/", 2); - if (strcasecmp(reg1, name) == 0 || - (reg2 && strcasecmp(reg2, name) == 0)) { + g_assert(reg_name[0]); + g_assert(reg_name[1]); + + if (g_ascii_strcasecmp(reg_name[0], name) == 0 || + g_ascii_strcasecmp(reg_name[1], name) == 0) { *val = vals[i]; return true; } @@ -294,12 +295,13 @@ static bool reg_is_u64_fpu(CPURISCVState *env, const char *name, uint64_t *val) } for (int i = 0; i < 32; i++) { - g_autofree char *reg_name = g_strdup(riscv_fpr_regnames[i]); - char *reg1 = strtok(reg_name, "/"); - char *reg2 = strtok(NULL, "/"); + g_auto(GStrv) reg_name = g_strsplit(riscv_fpr_regnames[i], "/", 2); - if (strcasecmp(reg1, name) == 0 || - (reg2 && strcasecmp(reg2, name) == 0)) { + g_assert(reg_name[0]); + g_assert(reg_name[1]); + + if (g_ascii_strcasecmp(reg_name[0], name) == 0 || + g_ascii_strcasecmp(reg_name[1], name) == 0) { *val = env->fpr[i]; return true; } diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 1150bd1469..d3968251fa 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -426,6 +426,8 @@ static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg, min_vlen = 64; } else if (cfg->ext_zve32x) { min_vlen = 32; + } else { + return; } if (vlen > RV_VLEN_MAX || vlen < min_vlen) { @@ -676,12 +678,10 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) return; } - if (cpu->cfg.ext_zve32x) { - riscv_cpu_validate_v(env, &cpu->cfg, &local_err); - if (local_err != NULL) { - error_propagate(errp, local_err); - return; - } + riscv_cpu_validate_v(env, &cpu->cfg, &local_err); + if (local_err != NULL) { + error_propagate(errp, local_err); + return; } /* The Zve64d extension depends on the Zve64f extension */ diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 9a53aecbfe..e1f4dc5ffd 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -126,6 +126,18 @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext) return ctx->misa_ext & ext; } +static inline MemOp mo_endian(DisasContext *ctx) +{ + /* + * A couple of bits in MSTATUS set the endianness: + * - MSTATUS_UBE (User-mode), + * - MSTATUS_SBE (Supervisor-mode), + * - MSTATUS_MBE (Machine-mode) + * but we don't implement that yet. + */ + return MO_TE; +} + #ifdef TARGET_RISCV32 #define get_xl(ctx) MXL_RV32 #elif defined(CONFIG_USER_ONLY) @@ -142,7 +154,7 @@ static inline bool has_ext(DisasContext *ctx, uint32_t ext) #define get_address_xl(ctx) ((ctx)->address_xl) #endif -#define mxl_memop(ctx) ((get_xl(ctx) + 1) | MO_TE) +#define mxl_memop(ctx) ((get_xl(ctx) + 1) | mo_endian(ctx)) /* The word size for this machine mode. */ static inline int __attribute__((unused)) get_xlen(DisasContext *ctx) @@ -1135,6 +1147,7 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a, TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE); MemOp size = mop & MO_SIZE; + mop |= mo_endian(ctx); if (ctx->cfg_ptr->ext_zama16b && size >= MO_32) { mop |= MO_ATOM_WITHIN16; } else { @@ -1155,6 +1168,7 @@ static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop) TCGv src1 = get_address(ctx, a->rs1, 0); TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); + mop |= mo_endian(ctx); decode_save_opc(ctx, RISCV_UW2_ALWAYS_STORE_AMO); tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop);