Merge remote-tracking branch 'remotes/alistair23/tags/pull-riscv-to-apply-20211022-2' into staging

Fourth RISC-V PR for QEMU 6.2

 - Vector extension bug fixes
 - Bit manipulation extension bug fix
 - Support vhost-user and numa mem options on all boards
 - Rationalise XLEN and operand lengths
 - Bump the OpenTitan FPGA support
 - Remove the Ibex PLIC
 - General code cleanup

# gpg: Signature made Fri 22 Oct 2021 06:36:10 AM PDT
# gpg:                using RSA key F6C4AC46D4934868D3B8CE8F21E10D29DF977054
# gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [full]

* remotes/alistair23/tags/pull-riscv-to-apply-20211022-2: (33 commits)
  hw/riscv: spike: Use MachineState::ram and MachineClass::default_ram_id
  hw/riscv: sifive_u: Use MachineState::ram and MachineClass::default_ram_id
  hw/riscv: sifive_e: Use MachineState::ram and MachineClass::default_ram_id
  hw/riscv: shakti_c: Use MachineState::ram and MachineClass::default_ram_id
  hw/riscv: opentitan: Use MachineState::ram and MachineClass::default_ram_id
  hw/riscv: microchip_pfsoc: Use MachineState::ram and MachineClass::default_ram_id
  hw/intc: sifive_plic: Cleanup the irq_request function
  hw/intc: sifive_plic: Cleanup the realize function
  hw/intc: sifive_plic: Move the properties
  hw/intc: Remove the Ibex PLIC
  hw/riscv: opentitan: Update to the latest build
  target/riscv: Compute mstatus.sd on demand
  target/riscv: Use riscv_csrrw_debug for cpu_dump
  target/riscv: Use gen_shift*_per_ol for RVB, RVI
  target/riscv: Use gen_unary_per_ol for RVB
  target/riscv: Adjust trans_rev8_32 for riscv64
  target/riscv: Use gen_arith_per_ol for RVM
  target/riscv: Replace DisasContext.w with DisasContext.ol
  target/riscv: Replace is_32bit with get_xl/get_xlen
  target/riscv: Properly check SEW in amo_op
  ...

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson
2021-10-22 12:09:17 -07:00
28 changed files with 719 additions and 778 deletions
-307
View File
@@ -1,307 +0,0 @@
/*
* QEMU RISC-V lowRISC Ibex PLIC
*
* Copyright (c) 2020 Western Digital
*
* Documentation avaliable: https://docs.opentitan.org/hw/ip/rv_plic/doc/
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2 or later, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along with
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "qemu/osdep.h"
#include "qemu/log.h"
#include "hw/qdev-properties.h"
#include "hw/core/cpu.h"
#include "hw/boards.h"
#include "hw/pci/msi.h"
#include "target/riscv/cpu_bits.h"
#include "target/riscv/cpu.h"
#include "hw/intc/ibex_plic.h"
#include "hw/irq.h"
static bool addr_between(uint32_t addr, uint32_t base, uint32_t num)
{
uint32_t end = base + (num * 0x04);
if (addr >= base && addr < end) {
return true;
}
return false;
}
static void ibex_plic_irqs_set_pending(IbexPlicState *s, int irq, bool level)
{
int pending_num = irq / 32;
if (!level) {
/*
* If the level is low make sure we clear the hidden_pending.
*/
s->hidden_pending[pending_num] &= ~(1 << (irq % 32));
}
if (s->claimed[pending_num] & 1 << (irq % 32)) {
/*
* The interrupt has been claimed, but not completed.
* The pending bit can't be set.
* Save the pending level for after the interrupt is completed.
*/
s->hidden_pending[pending_num] |= level << (irq % 32);
} else {
s->pending[pending_num] |= level << (irq % 32);
}
}
static bool ibex_plic_irqs_pending(IbexPlicState *s, uint32_t context)
{
int i;
uint32_t max_irq = 0;
uint32_t max_prio = s->threshold;
for (i = 0; i < s->pending_num; i++) {
uint32_t irq_num = ctz64(s->pending[i]) + (i * 32);
if (!(s->pending[i] & s->enable[i])) {
/* No pending and enabled IRQ */
continue;
}
if (s->priority[irq_num] > max_prio) {
max_irq = irq_num;
max_prio = s->priority[irq_num];
}
}
if (max_irq) {
s->claim = max_irq;
return true;
}
return false;
}
static void ibex_plic_update(IbexPlicState *s)
{
int i;
for (i = 0; i < s->num_cpus; i++) {
qemu_set_irq(s->external_irqs[i], ibex_plic_irqs_pending(s, 0));
}
}
static void ibex_plic_reset(DeviceState *dev)
{
IbexPlicState *s = IBEX_PLIC(dev);
s->threshold = 0x00000000;
s->claim = 0x00000000;
}
static uint64_t ibex_plic_read(void *opaque, hwaddr addr,
unsigned int size)
{
IbexPlicState *s = opaque;
int offset;
uint32_t ret = 0;
if (addr_between(addr, s->pending_base, s->pending_num)) {
offset = (addr - s->pending_base) / 4;
ret = s->pending[offset];
} else if (addr_between(addr, s->source_base, s->source_num)) {
qemu_log_mask(LOG_UNIMP,
"%s: Interrupt source mode not supported\n", __func__);
} else if (addr_between(addr, s->priority_base, s->priority_num)) {
offset = (addr - s->priority_base) / 4;
ret = s->priority[offset];
} else if (addr_between(addr, s->enable_base, s->enable_num)) {
offset = (addr - s->enable_base) / 4;
ret = s->enable[offset];
} else if (addr_between(addr, s->threshold_base, 1)) {
ret = s->threshold;
} else if (addr_between(addr, s->claim_base, 1)) {
int pending_num = s->claim / 32;
s->pending[pending_num] &= ~(1 << (s->claim % 32));
/* Set the interrupt as claimed, but not completed */
s->claimed[pending_num] |= 1 << (s->claim % 32);
/* Return the current claimed interrupt */
ret = s->claim;
/* Clear the claimed interrupt */
s->claim = 0x00000000;
/* Update the interrupt status after the claim */
ibex_plic_update(s);
}
return ret;
}
static void ibex_plic_write(void *opaque, hwaddr addr,
uint64_t value, unsigned int size)
{
IbexPlicState *s = opaque;
if (addr_between(addr, s->pending_base, s->pending_num)) {
qemu_log_mask(LOG_GUEST_ERROR,
"%s: Pending registers are read only\n", __func__);
} else if (addr_between(addr, s->source_base, s->source_num)) {
qemu_log_mask(LOG_UNIMP,
"%s: Interrupt source mode not supported\n", __func__);
} else if (addr_between(addr, s->priority_base, s->priority_num)) {
uint32_t irq = ((addr - s->priority_base) >> 2) + 1;
s->priority[irq] = value & 7;
ibex_plic_update(s);
} else if (addr_between(addr, s->enable_base, s->enable_num)) {
uint32_t enable_reg = (addr - s->enable_base) / 4;
s->enable[enable_reg] = value;
} else if (addr_between(addr, s->threshold_base, 1)) {
s->threshold = value & 3;
} else if (addr_between(addr, s->claim_base, 1)) {
if (s->claim == value) {
/* Interrupt was completed */
s->claim = 0;
}
if (s->claimed[value / 32] & 1 << (value % 32)) {
int pending_num = value / 32;
/* This value was already claimed, clear it. */
s->claimed[pending_num] &= ~(1 << (value % 32));
if (s->hidden_pending[pending_num] & (1 << (value % 32))) {
/*
* If the bit in hidden_pending is set then that means we
* received an interrupt between claiming and completing
* the interrupt that hasn't since been de-asserted.
* On hardware this would trigger an interrupt, so let's
* trigger one here as well.
*/
s->pending[pending_num] |= 1 << (value % 32);
}
}
}
ibex_plic_update(s);
}
static const MemoryRegionOps ibex_plic_ops = {
.read = ibex_plic_read,
.write = ibex_plic_write,
.endianness = DEVICE_NATIVE_ENDIAN,
.valid = {
.min_access_size = 4,
.max_access_size = 4
}
};
static void ibex_plic_irq_request(void *opaque, int irq, int level)
{
IbexPlicState *s = opaque;
ibex_plic_irqs_set_pending(s, irq, level > 0);
ibex_plic_update(s);
}
static Property ibex_plic_properties[] = {
DEFINE_PROP_UINT32("num-cpus", IbexPlicState, num_cpus, 1),
DEFINE_PROP_UINT32("num-sources", IbexPlicState, num_sources, 176),
DEFINE_PROP_UINT32("pending-base", IbexPlicState, pending_base, 0),
DEFINE_PROP_UINT32("pending-num", IbexPlicState, pending_num, 6),
DEFINE_PROP_UINT32("source-base", IbexPlicState, source_base, 0x18),
DEFINE_PROP_UINT32("source-num", IbexPlicState, source_num, 6),
DEFINE_PROP_UINT32("priority-base", IbexPlicState, priority_base, 0x30),
DEFINE_PROP_UINT32("priority-num", IbexPlicState, priority_num, 177),
DEFINE_PROP_UINT32("enable-base", IbexPlicState, enable_base, 0x300),
DEFINE_PROP_UINT32("enable-num", IbexPlicState, enable_num, 6),
DEFINE_PROP_UINT32("threshold-base", IbexPlicState, threshold_base, 0x318),
DEFINE_PROP_UINT32("claim-base", IbexPlicState, claim_base, 0x31c),
DEFINE_PROP_END_OF_LIST(),
};
static void ibex_plic_init(Object *obj)
{
IbexPlicState *s = IBEX_PLIC(obj);
memory_region_init_io(&s->mmio, obj, &ibex_plic_ops, s,
TYPE_IBEX_PLIC, 0x400);
sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
}
static void ibex_plic_realize(DeviceState *dev, Error **errp)
{
IbexPlicState *s = IBEX_PLIC(dev);
int i;
s->pending = g_new0(uint32_t, s->pending_num);
s->hidden_pending = g_new0(uint32_t, s->pending_num);
s->claimed = g_new0(uint32_t, s->pending_num);
s->source = g_new0(uint32_t, s->source_num);
s->priority = g_new0(uint32_t, s->priority_num);
s->enable = g_new0(uint32_t, s->enable_num);
qdev_init_gpio_in(dev, ibex_plic_irq_request, s->num_sources);
s->external_irqs = g_malloc(sizeof(qemu_irq) * s->num_cpus);
qdev_init_gpio_out(dev, s->external_irqs, s->num_cpus);
/*
* We can't allow the supervisor to control SEIP as this would allow the
* supervisor to clear a pending external interrupt which will result in
* a lost interrupt in the case a PLIC is attached. The SEIP bit must be
* hardware controlled when a PLIC is attached.
*/
MachineState *ms = MACHINE(qdev_get_machine());
unsigned int smp_cpus = ms->smp.cpus;
for (i = 0; i < smp_cpus; i++) {
RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(i));
if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) {
error_report("SEIP already claimed");
exit(1);
}
}
msi_nonbroken = true;
}
static void ibex_plic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
dc->reset = ibex_plic_reset;
device_class_set_props(dc, ibex_plic_properties);
dc->realize = ibex_plic_realize;
}
static const TypeInfo ibex_plic_info = {
.name = TYPE_IBEX_PLIC,
.parent = TYPE_SYS_BUS_DEVICE,
.instance_size = sizeof(IbexPlicState),
.instance_init = ibex_plic_init,
.class_init = ibex_plic_class_init,
};
static void ibex_plic_register_types(void)
{
type_register_static(&ibex_plic_info);
}
type_init(ibex_plic_register_types)
-1
View File
@@ -32,7 +32,6 @@ specific_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_nvic.c'))
specific_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_vic.c'))
specific_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_gic.c', 'exynos4210_combiner.c'))
specific_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_irqmp.c'))
specific_ss.add(when: 'CONFIG_IBEX', if_true: files('ibex_plic.c'))
specific_ss.add(when: 'CONFIG_IOAPIC', if_true: files('ioapic.c'))
specific_ss.add(when: 'CONFIG_LOONGSON_LIOINTC', if_true: files('loongson_liointc.c'))
specific_ss.add(when: 'CONFIG_MIPS_CPS', if_true: files('mips_gic.c'))
+41 -40
View File
@@ -355,21 +355,6 @@ static const MemoryRegionOps sifive_plic_ops = {
}
};
static Property sifive_plic_properties[] = {
DEFINE_PROP_STRING("hart-config", SiFivePLICState, hart_config),
DEFINE_PROP_UINT32("hartid-base", SiFivePLICState, hartid_base, 0),
DEFINE_PROP_UINT32("num-sources", SiFivePLICState, num_sources, 0),
DEFINE_PROP_UINT32("num-priorities", SiFivePLICState, num_priorities, 0),
DEFINE_PROP_UINT32("priority-base", SiFivePLICState, priority_base, 0),
DEFINE_PROP_UINT32("pending-base", SiFivePLICState, pending_base, 0),
DEFINE_PROP_UINT32("enable-base", SiFivePLICState, enable_base, 0),
DEFINE_PROP_UINT32("enable-stride", SiFivePLICState, enable_stride, 0),
DEFINE_PROP_UINT32("context-base", SiFivePLICState, context_base, 0),
DEFINE_PROP_UINT32("context-stride", SiFivePLICState, context_stride, 0),
DEFINE_PROP_UINT32("aperture-size", SiFivePLICState, aperture_size, 0),
DEFINE_PROP_END_OF_LIST(),
};
/*
* parse PLIC hart/mode address offset config
*
@@ -427,45 +412,46 @@ static void parse_hart_config(SiFivePLICState *plic)
static void sifive_plic_irq_request(void *opaque, int irq, int level)
{
SiFivePLICState *plic = opaque;
if (RISCV_DEBUG_PLIC) {
qemu_log("sifive_plic_irq_request: irq=%d level=%d\n", irq, level);
}
sifive_plic_set_pending(plic, irq, level > 0);
sifive_plic_update(plic);
SiFivePLICState *s = opaque;
sifive_plic_set_pending(s, irq, level > 0);
sifive_plic_update(s);
}
static void sifive_plic_realize(DeviceState *dev, Error **errp)
{
SiFivePLICState *plic = SIFIVE_PLIC(dev);
SiFivePLICState *s = SIFIVE_PLIC(dev);
int i;
memory_region_init_io(&plic->mmio, OBJECT(dev), &sifive_plic_ops, plic,
TYPE_SIFIVE_PLIC, plic->aperture_size);
parse_hart_config(plic);
plic->bitfield_words = (plic->num_sources + 31) >> 5;
plic->num_enables = plic->bitfield_words * plic->num_addrs;
plic->source_priority = g_new0(uint32_t, plic->num_sources);
plic->target_priority = g_new(uint32_t, plic->num_addrs);
plic->pending = g_new0(uint32_t, plic->bitfield_words);
plic->claimed = g_new0(uint32_t, plic->bitfield_words);
plic->enable = g_new0(uint32_t, plic->num_enables);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &plic->mmio);
qdev_init_gpio_in(dev, sifive_plic_irq_request, plic->num_sources);
memory_region_init_io(&s->mmio, OBJECT(dev), &sifive_plic_ops, s,
TYPE_SIFIVE_PLIC, s->aperture_size);
sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->mmio);
plic->s_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts);
qdev_init_gpio_out(dev, plic->s_external_irqs, plic->num_harts);
parse_hart_config(s);
plic->m_external_irqs = g_malloc(sizeof(qemu_irq) * plic->num_harts);
qdev_init_gpio_out(dev, plic->m_external_irqs, plic->num_harts);
s->bitfield_words = (s->num_sources + 31) >> 5;
s->num_enables = s->bitfield_words * s->num_addrs;
s->source_priority = g_new0(uint32_t, s->num_sources);
s->target_priority = g_new(uint32_t, s->num_addrs);
s->pending = g_new0(uint32_t, s->bitfield_words);
s->claimed = g_new0(uint32_t, s->bitfield_words);
s->enable = g_new0(uint32_t, s->num_enables);
qdev_init_gpio_in(dev, sifive_plic_irq_request, s->num_sources);
s->s_external_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
qdev_init_gpio_out(dev, s->s_external_irqs, s->num_harts);
s->m_external_irqs = g_malloc(sizeof(qemu_irq) * s->num_harts);
qdev_init_gpio_out(dev, s->m_external_irqs, s->num_harts);
/* We can't allow the supervisor to control SEIP as this would allow the
* supervisor to clear a pending external interrupt which will result in
* lost a interrupt in the case a PLIC is attached. The SEIP bit must be
* hardware controlled when a PLIC is attached.
*/
for (i = 0; i < plic->num_harts; i++) {
RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(plic->hartid_base + i));
for (i = 0; i < s->num_harts; i++) {
RISCVCPU *cpu = RISCV_CPU(qemu_get_cpu(s->hartid_base + i));
if (riscv_cpu_claim_interrupts(cpu, MIP_SEIP) < 0) {
error_report("SEIP already claimed");
exit(1);
@@ -496,6 +482,21 @@ static const VMStateDescription vmstate_sifive_plic = {
}
};
static Property sifive_plic_properties[] = {
DEFINE_PROP_STRING("hart-config", SiFivePLICState, hart_config),
DEFINE_PROP_UINT32("hartid-base", SiFivePLICState, hartid_base, 0),
DEFINE_PROP_UINT32("num-sources", SiFivePLICState, num_sources, 0),
DEFINE_PROP_UINT32("num-priorities", SiFivePLICState, num_priorities, 0),
DEFINE_PROP_UINT32("priority-base", SiFivePLICState, priority_base, 0),
DEFINE_PROP_UINT32("pending-base", SiFivePLICState, pending_base, 0),
DEFINE_PROP_UINT32("enable-base", SiFivePLICState, enable_base, 0),
DEFINE_PROP_UINT32("enable-stride", SiFivePLICState, enable_stride, 0),
DEFINE_PROP_UINT32("context-base", SiFivePLICState, context_base, 0),
DEFINE_PROP_UINT32("context-stride", SiFivePLICState, context_stride, 0),
DEFINE_PROP_UINT32("aperture-size", SiFivePLICState, aperture_size, 0),
DEFINE_PROP_END_OF_LIST(),
};
static void sifive_plic_class_init(ObjectClass *klass, void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
+1 -1
View File
@@ -35,7 +35,7 @@
bool riscv_is_32bit(RISCVHartArrayState *harts)
{
return riscv_cpu_is_32bit(&harts->harts[0].env);
return harts->harts[0].env.misa_mxl_max == MXL_RV32;
}
target_ulong riscv_calc_kernel_start_addr(RISCVHartArrayState *harts,
+20 -16
View File
@@ -463,7 +463,7 @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
MemoryRegion *mem_low_alias = g_new(MemoryRegion, 1);
MemoryRegion *mem_high = g_new(MemoryRegion, 1);
MemoryRegion *mem_high_alias = g_new(MemoryRegion, 1);
uint64_t mem_high_size;
uint64_t mem_low_size, mem_high_size;
hwaddr firmware_load_addr;
const char *firmware_name;
bool kernel_as_payload = false;
@@ -485,31 +485,34 @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
TYPE_MICROCHIP_PFSOC);
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
/* Split RAM into low and high regions using aliases to machine->ram */
mem_low_size = memmap[MICROCHIP_PFSOC_DRAM_LO].size;
mem_high_size = machine->ram_size - mem_low_size;
memory_region_init_alias(mem_low, NULL,
"microchip.icicle.kit.ram_low", machine->ram,
0, mem_low_size);
memory_region_init_alias(mem_high, NULL,
"microchip.icicle.kit.ram_high", machine->ram,
mem_low_size, mem_high_size);
/* Register RAM */
memory_region_init_ram(mem_low, NULL, "microchip.icicle.kit.ram_low",
memmap[MICROCHIP_PFSOC_DRAM_LO].size,
&error_fatal);
memory_region_init_alias(mem_low_alias, NULL,
"microchip.icicle.kit.ram_low.alias",
mem_low, 0,
memmap[MICROCHIP_PFSOC_DRAM_LO_ALIAS].size);
memory_region_add_subregion(system_memory,
memmap[MICROCHIP_PFSOC_DRAM_LO].base,
mem_low);
memory_region_add_subregion(system_memory,
memmap[MICROCHIP_PFSOC_DRAM_HI].base,
mem_high);
/* Create aliases for the low and high RAM regions */
memory_region_init_alias(mem_low_alias, NULL,
"microchip.icicle.kit.ram_low.alias",
mem_low, 0, mem_low_size);
memory_region_add_subregion(system_memory,
memmap[MICROCHIP_PFSOC_DRAM_LO_ALIAS].base,
mem_low_alias);
mem_high_size = machine->ram_size - 1 * GiB;
memory_region_init_ram(mem_high, NULL, "microchip.icicle.kit.ram_high",
mem_high_size, &error_fatal);
memory_region_init_alias(mem_high_alias, NULL,
"microchip.icicle.kit.ram_high.alias",
mem_high, 0, mem_high_size);
memory_region_add_subregion(system_memory,
memmap[MICROCHIP_PFSOC_DRAM_HI].base,
mem_high);
memory_region_add_subregion(system_memory,
memmap[MICROCHIP_PFSOC_DRAM_HI_ALIAS].base,
mem_high_alias);
@@ -606,6 +609,7 @@ static void microchip_icicle_kit_machine_class_init(ObjectClass *oc, void *data)
MICROCHIP_PFSOC_COMPUTE_CPU_COUNT;
mc->min_cpus = MICROCHIP_PFSOC_MANAGEMENT_CPU_COUNT + 1;
mc->default_cpus = mc->min_cpus;
mc->default_ram_id = "microchip.icicle.kit.ram";
/*
* Map 513 MiB high memory, the mimimum required high memory size, because
+29 -9
View File
@@ -19,6 +19,7 @@
*/
#include "qemu/osdep.h"
#include "qemu/cutils.h"
#include "hw/riscv/opentitan.h"
#include "qapi/error.h"
#include "hw/boards.h"
@@ -46,38 +47,43 @@ static const MemMapEntry ibex_memmap[] = {
[IBEX_DEV_PINMUX] = { 0x40460000, 0x1000 },
[IBEX_DEV_PADCTRL] = { 0x40470000, 0x1000 },
[IBEX_DEV_FLASH_CTRL] = { 0x41000000, 0x1000 },
[IBEX_DEV_PLIC] = { 0x41010000, 0x1000 },
[IBEX_DEV_AES] = { 0x41100000, 0x1000 },
[IBEX_DEV_HMAC] = { 0x41110000, 0x1000 },
[IBEX_DEV_KMAC] = { 0x41120000, 0x1000 },
[IBEX_DEV_KEYMGR] = { 0x41130000, 0x1000 },
[IBEX_DEV_OTBN] = { 0x41130000, 0x10000 },
[IBEX_DEV_KEYMGR] = { 0x41140000, 0x1000 },
[IBEX_DEV_CSRNG] = { 0x41150000, 0x1000 },
[IBEX_DEV_ENTROPY] = { 0x41160000, 0x1000 },
[IBEX_DEV_EDNO] = { 0x41170000, 0x1000 },
[IBEX_DEV_EDN1] = { 0x41180000, 0x1000 },
[IBEX_DEV_ALERT_HANDLER] = { 0x411b0000, 0x1000 },
[IBEX_DEV_NMI_GEN] = { 0x411c0000, 0x1000 },
[IBEX_DEV_OTBN] = { 0x411d0000, 0x10000 },
[IBEX_DEV_PERI] = { 0x411f0000, 0x10000 },
[IBEX_DEV_PLIC] = { 0x48000000, 0x4005000 },
[IBEX_DEV_FLASH_VIRTUAL] = { 0x80000000, 0x80000 },
};
static void opentitan_board_init(MachineState *machine)
{
MachineClass *mc = MACHINE_GET_CLASS(machine);
const MemMapEntry *memmap = ibex_memmap;
OpenTitanState *s = g_new0(OpenTitanState, 1);
MemoryRegion *sys_mem = get_system_memory();
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
if (machine->ram_size != mc->default_ram_size) {
char *sz = size_to_str(mc->default_ram_size);
error_report("Invalid RAM size, should be %s", sz);
g_free(sz);
exit(EXIT_FAILURE);
}
/* Initialize SoC */
object_initialize_child(OBJECT(machine), "soc", &s->soc,
TYPE_RISCV_IBEX_SOC);
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
memory_region_init_ram(main_mem, NULL, "riscv.lowrisc.ibex.ram",
memmap[IBEX_DEV_RAM].size, &error_fatal);
memory_region_add_subregion(sys_mem,
memmap[IBEX_DEV_RAM].base, main_mem);
memmap[IBEX_DEV_RAM].base, machine->ram);
if (machine->firmware) {
riscv_load_firmware(machine->firmware, memmap[IBEX_DEV_RAM].base, NULL);
@@ -95,6 +101,8 @@ static void opentitan_machine_init(MachineClass *mc)
mc->init = opentitan_board_init;
mc->max_cpus = 1;
mc->default_cpu_type = TYPE_RISCV_CPU_IBEX;
mc->default_ram_id = "riscv.lowrisc.ibex.ram";
mc->default_ram_size = ibex_memmap[IBEX_DEV_RAM].size;
}
DEFINE_MACHINE("opentitan", opentitan_machine_init)
@@ -105,7 +113,7 @@ static void lowrisc_ibex_soc_init(Object *obj)
object_initialize_child(obj, "cpus", &s->cpus, TYPE_RISCV_HART_ARRAY);
object_initialize_child(obj, "plic", &s->plic, TYPE_IBEX_PLIC);
object_initialize_child(obj, "plic", &s->plic, TYPE_SIFIVE_PLIC);
object_initialize_child(obj, "uart", &s->uart, TYPE_IBEX_UART);
@@ -145,6 +153,18 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
&s->flash_alias);
/* PLIC */
qdev_prop_set_string(DEVICE(&s->plic), "hart-config", "M");
qdev_prop_set_uint32(DEVICE(&s->plic), "hartid-base", 0);
qdev_prop_set_uint32(DEVICE(&s->plic), "num-sources", 180);
qdev_prop_set_uint32(DEVICE(&s->plic), "num-priorities", 3);
qdev_prop_set_uint32(DEVICE(&s->plic), "priority-base", 0x00);
qdev_prop_set_uint32(DEVICE(&s->plic), "pending-base", 0x1000);
qdev_prop_set_uint32(DEVICE(&s->plic), "enable-base", 0x2000);
qdev_prop_set_uint32(DEVICE(&s->plic), "enable-stride", 0x18);
qdev_prop_set_uint32(DEVICE(&s->plic), "context-base", 0x200004);
qdev_prop_set_uint32(DEVICE(&s->plic), "context-stride", 4);
qdev_prop_set_uint32(DEVICE(&s->plic), "aperture-size", memmap[IBEX_DEV_PLIC].size);
if (!sysbus_realize(SYS_BUS_DEVICE(&s->plic), errp)) {
return;
}
@@ -153,7 +173,7 @@ static void lowrisc_ibex_soc_realize(DeviceState *dev_soc, Error **errp)
for (i = 0; i < ms->smp.cpus; i++) {
CPUState *cpu = qemu_get_cpu(i);
qdev_connect_gpio_out(DEVICE(&s->plic), i,
qdev_connect_gpio_out(DEVICE(&s->plic), ms->smp.cpus + i,
qdev_get_gpio_in(DEVICE(cpu), IRQ_M_EXT));
}
+2 -4
View File
@@ -45,7 +45,6 @@ static void shakti_c_machine_state_init(MachineState *mstate)
{
ShaktiCMachineState *sms = RISCV_SHAKTI_MACHINE(mstate);
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
/* Allow only Shakti C CPU for this platform */
if (strcmp(mstate->cpu_type, TYPE_RISCV_CPU_SHAKTI_C) != 0) {
@@ -59,11 +58,9 @@ static void shakti_c_machine_state_init(MachineState *mstate)
qdev_realize(DEVICE(&sms->soc), NULL, &error_abort);
/* register RAM */
memory_region_init_ram(main_mem, NULL, "riscv.shakti.c.ram",
mstate->ram_size, &error_fatal);
memory_region_add_subregion(system_memory,
shakti_c_memmap[SHAKTI_C_RAM].base,
main_mem);
mstate->ram);
/* ROM reset vector */
riscv_setup_rom_reset_vec(mstate, &sms->soc.cpus,
@@ -88,6 +85,7 @@ static void shakti_c_machine_class_init(ObjectClass *klass, void *data)
mc->desc = "RISC-V Board compatible with Shakti SDK";
mc->init = shakti_c_machine_state_init;
mc->default_cpu_type = TYPE_RISCV_CPU_SHAKTI_C;
mc->default_ram_id = "riscv.shakti.c.ram";
}
static const TypeInfo shakti_c_machine_type_info = {
+12 -4
View File
@@ -29,6 +29,7 @@
*/
#include "qemu/osdep.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
#include "qapi/error.h"
#include "hw/boards.h"
@@ -71,22 +72,27 @@ static const MemMapEntry sifive_e_memmap[] = {
static void sifive_e_machine_init(MachineState *machine)
{
MachineClass *mc = MACHINE_GET_CLASS(machine);
const MemMapEntry *memmap = sifive_e_memmap;
SiFiveEState *s = RISCV_E_MACHINE(machine);
MemoryRegion *sys_mem = get_system_memory();
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
int i;
if (machine->ram_size != mc->default_ram_size) {
char *sz = size_to_str(mc->default_ram_size);
error_report("Invalid RAM size, should be %s", sz);
g_free(sz);
exit(EXIT_FAILURE);
}
/* Initialize SoC */
object_initialize_child(OBJECT(machine), "soc", &s->soc, TYPE_RISCV_E_SOC);
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
/* Data Tightly Integrated Memory */
memory_region_init_ram(main_mem, NULL, "riscv.sifive.e.ram",
memmap[SIFIVE_E_DEV_DTIM].size, &error_fatal);
memory_region_add_subregion(sys_mem,
memmap[SIFIVE_E_DEV_DTIM].base, main_mem);
memmap[SIFIVE_E_DEV_DTIM].base, machine->ram);
/* Mask ROM reset vector */
uint32_t reset_vec[4];
@@ -142,6 +148,8 @@ static void sifive_e_machine_class_init(ObjectClass *oc, void *data)
mc->init = sifive_e_machine_init;
mc->max_cpus = 1;
mc->default_cpu_type = SIFIVE_E_CPU;
mc->default_ram_id = "riscv.sifive.e.ram";
mc->default_ram_size = sifive_e_memmap[SIFIVE_E_DEV_DTIM].size;
object_class_property_add_bool(oc, "revb", sifive_e_machine_get_revb,
sifive_e_machine_set_revb);
+2 -4
View File
@@ -528,7 +528,6 @@ static void sifive_u_machine_init(MachineState *machine)
const MemMapEntry *memmap = sifive_u_memmap;
SiFiveUState *s = RISCV_U_MACHINE(machine);
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
MemoryRegion *flash0 = g_new(MemoryRegion, 1);
target_ulong start_addr = memmap[SIFIVE_U_DEV_DRAM].base;
target_ulong firmware_end_addr, kernel_start_addr;
@@ -549,10 +548,8 @@ static void sifive_u_machine_init(MachineState *machine)
qdev_realize(DEVICE(&s->soc), NULL, &error_abort);
/* register RAM */
memory_region_init_ram(main_mem, NULL, "riscv.sifive.u.ram",
machine->ram_size, &error_fatal);
memory_region_add_subregion(system_memory, memmap[SIFIVE_U_DEV_DRAM].base,
main_mem);
machine->ram);
/* register QSPI0 Flash */
memory_region_init_ram(flash0, NULL, "riscv.sifive.u.flash0",
@@ -748,6 +745,7 @@ static void sifive_u_machine_class_init(ObjectClass *oc, void *data)
mc->min_cpus = SIFIVE_U_MANAGEMENT_CPU_COUNT + 1;
mc->default_cpu_type = SIFIVE_U_CPU;
mc->default_cpus = mc->min_cpus;
mc->default_ram_id = "riscv.sifive.u.ram";
object_class_property_add_bool(oc, "start-in-flash",
sifive_u_machine_get_start_in_flash,
+2 -4
View File
@@ -180,7 +180,6 @@ static void spike_board_init(MachineState *machine)
const MemMapEntry *memmap = spike_memmap;
SpikeState *s = SPIKE_MACHINE(machine);
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
target_ulong firmware_end_addr, kernel_start_addr;
uint32_t fdt_load_addr;
@@ -239,10 +238,8 @@ static void spike_board_init(MachineState *machine)
}
/* register system main memory (actual RAM) */
memory_region_init_ram(main_mem, NULL, "riscv.spike.ram",
machine->ram_size, &error_fatal);
memory_region_add_subregion(system_memory, memmap[SPIKE_DRAM].base,
main_mem);
machine->ram);
/* create device tree */
create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline,
@@ -326,6 +323,7 @@ static void spike_machine_class_init(ObjectClass *oc, void *data)
mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props;
mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id;
mc->numa_mem_supported = true;
mc->default_ram_id = "riscv.spike.ram";
}
static const TypeInfo spike_machine_typeinfo = {
+2 -4
View File
@@ -771,7 +771,6 @@ static void virt_machine_init(MachineState *machine)
const MemMapEntry *memmap = virt_memmap;
RISCVVirtState *s = RISCV_VIRT_MACHINE(machine);
MemoryRegion *system_memory = get_system_memory();
MemoryRegion *main_mem = g_new(MemoryRegion, 1);
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
char *plic_hart_config, *soc_name;
target_ulong start_addr = memmap[VIRT_DRAM].base;
@@ -890,10 +889,8 @@ static void virt_machine_init(MachineState *machine)
}
/* register system main memory (actual RAM) */
memory_region_init_ram(main_mem, NULL, "riscv_virt_board.ram",
machine->ram_size, &error_fatal);
memory_region_add_subregion(system_memory, memmap[VIRT_DRAM].base,
main_mem);
machine->ram);
/* create device tree */
create_fdt(s, memmap, machine->ram_size, machine->kernel_cmdline,
@@ -1032,6 +1029,7 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props;
mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id;
mc->numa_mem_supported = true;
mc->default_ram_id = "riscv_virt_board.ram";
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
+3 -3
View File
@@ -20,7 +20,7 @@
#define HW_OPENTITAN_H
#include "hw/riscv/riscv_hart.h"
#include "hw/intc/ibex_plic.h"
#include "hw/intc/sifive_plic.h"
#include "hw/char/ibex_uart.h"
#include "hw/timer/ibex_timer.h"
#include "qom/object.h"
@@ -34,7 +34,7 @@ struct LowRISCIbexSoCState {
/*< public >*/
RISCVHartArrayState cpus;
IbexPlicState plic;
SiFivePLICState plic;
IbexUartState uart;
IbexTimerState timer;
@@ -87,7 +87,7 @@ enum {
};
enum {
IBEX_TIMER_TIMEREXPIRED0_0 = 125,
IBEX_TIMER_TIMEREXPIRED0_0 = 126,
IBEX_UART0_RX_PARITY_ERR_IRQ = 8,
IBEX_UART0_RX_TIMEOUT_IRQ = 7,
IBEX_UART0_RX_BREAK_ERR_IRQ = 6,
+1 -1
View File
@@ -1448,7 +1448,7 @@ static uint32_t get_elf_hwcap(void)
uint32_t mask = MISA_BIT('I') | MISA_BIT('M') | MISA_BIT('A')
| MISA_BIT('F') | MISA_BIT('D') | MISA_BIT('C');
return cpu->env.misa & mask;
return cpu->env.misa_ext & mask;
#undef MISA_BIT
}
+1 -1
View File
@@ -133,7 +133,7 @@ void target_cpu_copy_regs(CPUArchState *env, struct target_pt_regs *regs)
env->gpr[xSP] = regs->sp;
env->elf_flags = info->elf_flags;
if ((env->misa & RVE) && !(env->elf_flags & EF_RISCV_RVE)) {
if ((env->misa_ext & RVE) && !(env->elf_flags & EF_RISCV_RVE)) {
error_report("Incompatible ELF: RVE cpu requires RVE ABI binary");
exit(EXIT_FAILURE);
}
+1 -1
View File
@@ -775,7 +775,7 @@ static inline bool is_64bit_semihosting(CPUArchState *env)
#if defined(TARGET_ARM)
return is_a64(env);
#elif defined(TARGET_RISCV)
return !riscv_cpu_is_32bit(env);
return riscv_cpu_mxl(env) != MXL_RV32;
#else
#error un-handled architecture
#endif
+122 -94
View File
@@ -108,18 +108,10 @@ const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
}
}
bool riscv_cpu_is_32bit(CPURISCVState *env)
static void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext)
{
if (env->misa & RV64) {
return false;
}
return true;
}
static void set_misa(CPURISCVState *env, target_ulong misa)
{
env->misa_mask = env->misa = misa;
env->misa_mxl_max = env->misa_mxl = mxl;
env->misa_ext_mask = env->misa_ext = ext;
}
static void set_priv_version(CPURISCVState *env, int priv_ver)
@@ -148,9 +140,9 @@ static void riscv_any_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
#if defined(TARGET_RISCV32)
set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVU);
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
#elif defined(TARGET_RISCV64)
set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVU);
set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
#endif
set_priv_version(env, PRIV_VERSION_1_11_0);
}
@@ -160,20 +152,20 @@ static void rv64_base_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
/* We set this in the realise function */
set_misa(env, RV64);
set_misa(env, MXL_RV64, 0);
}
static void rv64_sifive_u_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
set_misa(env, RV64 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
set_priv_version(env, PRIV_VERSION_1_10_0);
}
static void rv64_sifive_e_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
set_misa(env, RV64 | RVI | RVM | RVA | RVC | RVU);
set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
set_priv_version(env, PRIV_VERSION_1_10_0);
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
}
@@ -182,20 +174,20 @@ static void rv32_base_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
/* We set this in the realise function */
set_misa(env, RV32);
set_misa(env, MXL_RV32, 0);
}
static void rv32_sifive_u_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
set_priv_version(env, PRIV_VERSION_1_10_0);
}
static void rv32_sifive_e_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
set_misa(env, RV32 | RVI | RVM | RVA | RVC | RVU);
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVC | RVU);
set_priv_version(env, PRIV_VERSION_1_10_0);
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
}
@@ -203,7 +195,7 @@ static void rv32_sifive_e_cpu_init(Object *obj)
static void rv32_ibex_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
set_misa(env, RV32 | RVI | RVM | RVC | RVU);
set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU);
set_priv_version(env, PRIV_VERSION_1_10_0);
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
qdev_prop_set_bit(DEVICE(obj), "x-epmp", true);
@@ -212,7 +204,7 @@ static void rv32_ibex_cpu_init(Object *obj)
static void rv32_imafcu_nommu_cpu_init(Object *obj)
{
CPURISCVState *env = &RISCV_CPU(obj)->env;
set_misa(env, RV32 | RVI | RVM | RVA | RVF | RVC | RVU);
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | RVU);
set_priv_version(env, PRIV_VERSION_1_10_0);
set_resetvec(env, DEFAULT_RSTVEC);
qdev_prop_set_bit(DEVICE(obj), "mmu", false);
@@ -250,55 +242,56 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
#endif
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc ", env->pc);
#ifndef CONFIG_USER_ONLY
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mhartid ", env->mhartid);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatus ", (target_ulong)env->mstatus);
if (riscv_cpu_is_32bit(env)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mstatush ",
(target_ulong)(env->mstatus >> 32));
{
static const int dump_csrs[] = {
CSR_MHARTID,
CSR_MSTATUS,
CSR_MSTATUSH,
CSR_HSTATUS,
CSR_VSSTATUS,
CSR_MIP,
CSR_MIE,
CSR_MIDELEG,
CSR_HIDELEG,
CSR_MEDELEG,
CSR_HEDELEG,
CSR_MTVEC,
CSR_STVEC,
CSR_VSTVEC,
CSR_MEPC,
CSR_SEPC,
CSR_VSEPC,
CSR_MCAUSE,
CSR_SCAUSE,
CSR_VSCAUSE,
CSR_MTVAL,
CSR_STVAL,
CSR_HTVAL,
CSR_MTVAL2,
CSR_MSCRATCH,
CSR_SSCRATCH,
CSR_SATP,
};
for (int i = 0; i < ARRAY_SIZE(dump_csrs); ++i) {
int csrno = dump_csrs[i];
target_ulong val = 0;
RISCVException res = riscv_csrrw_debug(env, csrno, &val, 0, 0);
/*
* Rely on the smode, hmode, etc, predicates within csr.c
* to do the filtering of the registers that are present.
*/
if (res == RISCV_EXCP_NONE) {
qemu_fprintf(f, " %-8s " TARGET_FMT_lx "\n",
csr_ops[csrno].name, val);
}
}
}
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hstatus ", env->hstatus);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsstatus ",
(target_ulong)env->vsstatus);
}
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mip ", env->mip);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mie ", env->mie);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mideleg ", env->mideleg);
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hideleg ", env->hideleg);
}
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "medeleg ", env->medeleg);
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "hedeleg ", env->hedeleg);
}
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtvec ", env->mtvec);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stvec ", env->stvec);
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vstvec ", env->vstvec);
}
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mepc ", env->mepc);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sepc ", env->sepc);
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vsepc ", env->vsepc);
}
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mcause ", env->mcause);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "scause ", env->scause);
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "vscause ", env->vscause);
}
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval ", env->mtval);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "stval ", env->stval);
if (riscv_has_ext(env, RVH)) {
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "htval ", env->htval);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mtval2 ", env->mtval2);
}
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "mscratch", env->mscratch);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "sscratch", env->sscratch);
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "satp ", env->satp);
#endif
for (i = 0; i < 32; i++) {
qemu_fprintf(f, " %s " TARGET_FMT_lx,
qemu_fprintf(f, " %-8s " TARGET_FMT_lx,
riscv_int_regnames[i], env->gpr[i]);
if ((i & 3) == 3) {
qemu_fprintf(f, "\n");
@@ -306,7 +299,7 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
}
if (flags & CPU_DUMP_FPU) {
for (i = 0; i < 32; i++) {
qemu_fprintf(f, " %s %016" PRIx64,
qemu_fprintf(f, " %-8s %016" PRIx64,
riscv_fpr_regnames[i], env->fpr[i]);
if ((i & 3) == 3) {
qemu_fprintf(f, "\n");
@@ -360,8 +353,17 @@ static void riscv_cpu_reset(DeviceState *dev)
mcc->parent_reset(dev);
#ifndef CONFIG_USER_ONLY
env->misa_mxl = env->misa_mxl_max;
env->priv = PRV_M;
env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
if (env->misa_mxl > MXL_RV32) {
/*
* The reset status of SXL/UXL is undefined, but mstatus is WARL
* and we must ensure that the value after init is valid for read.
*/
env->mstatus = set_field(env->mstatus, MSTATUS64_SXL, env->misa_mxl);
env->mstatus = set_field(env->mstatus, MSTATUS64_UXL, env->misa_mxl);
}
env->mcause = 0;
env->pc = env->resetvec;
env->two_stage_lookup = false;
@@ -374,10 +376,16 @@ static void riscv_cpu_reset(DeviceState *dev)
static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
{
RISCVCPU *cpu = RISCV_CPU(s);
if (riscv_cpu_is_32bit(&cpu->env)) {
switch (riscv_cpu_mxl(&cpu->env)) {
case MXL_RV32:
info->print_insn = print_insn_riscv32;
} else {
break;
case MXL_RV64:
info->print_insn = print_insn_riscv64;
break;
default:
g_assert_not_reached();
}
}
@@ -388,7 +396,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
CPURISCVState *env = &cpu->env;
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
int priv_version = 0;
target_ulong target_misa = env->misa;
Error *local_err = NULL;
cpu_exec_realizefn(cs, &local_err);
@@ -434,8 +441,23 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
set_resetvec(env, cpu->cfg.resetvec);
/* If only XLEN is set for misa, then set misa from properties */
if (env->misa == RV32 || env->misa == RV64) {
/* Validate that MISA_MXL is set properly. */
switch (env->misa_mxl_max) {
#ifdef TARGET_RISCV64
case MXL_RV64:
break;
#endif
case MXL_RV32:
break;
default:
g_assert_not_reached();
}
assert(env->misa_mxl_max == env->misa_mxl);
/* If only MISA_EXT is unset for misa, then set it from properties */
if (env->misa_ext == 0) {
uint32_t ext = 0;
/* Do some ISA extension error checking */
if (cpu->cfg.ext_i && cpu->cfg.ext_e) {
error_setg(errp,
@@ -462,38 +484,38 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
/* Set the ISA extensions, checks should have happened above */
if (cpu->cfg.ext_i) {
target_misa |= RVI;
ext |= RVI;
}
if (cpu->cfg.ext_e) {
target_misa |= RVE;
ext |= RVE;
}
if (cpu->cfg.ext_m) {
target_misa |= RVM;
ext |= RVM;
}
if (cpu->cfg.ext_a) {
target_misa |= RVA;
ext |= RVA;
}
if (cpu->cfg.ext_f) {
target_misa |= RVF;
ext |= RVF;
}
if (cpu->cfg.ext_d) {
target_misa |= RVD;
ext |= RVD;
}
if (cpu->cfg.ext_c) {
target_misa |= RVC;
ext |= RVC;
}
if (cpu->cfg.ext_s) {
target_misa |= RVS;
ext |= RVS;
}
if (cpu->cfg.ext_u) {
target_misa |= RVU;
ext |= RVU;
}
if (cpu->cfg.ext_h) {
target_misa |= RVH;
ext |= RVH;
}
if (cpu->cfg.ext_v) {
int vext_version = VEXT_VERSION_0_07_1;
target_misa |= RVV;
ext |= RVV;
if (!is_power_of_2(cpu->cfg.vlen)) {
error_setg(errp,
"Vector extension VLEN must be power of 2");
@@ -532,7 +554,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
set_vext_version(env, vext_version);
}
set_misa(env, target_misa);
set_misa(env, env->misa_mxl, ext);
}
riscv_cpu_register_gdb_regs_for_features(cs);
@@ -581,6 +603,7 @@ static void riscv_cpu_init(Object *obj)
}
static Property riscv_cpu_properties[] = {
/* Defaults for standard extensions */
DEFINE_PROP_BOOL("i", RISCVCPU, cfg.ext_i, true),
DEFINE_PROP_BOOL("e", RISCVCPU, cfg.ext_e, false),
DEFINE_PROP_BOOL("g", RISCVCPU, cfg.ext_g, true),
@@ -591,22 +614,24 @@ static Property riscv_cpu_properties[] = {
DEFINE_PROP_BOOL("c", RISCVCPU, cfg.ext_c, true),
DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true),
DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
/* This is experimental so mark with 'x-' */
DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
/* These are experimental so mark with 'x-' */
DEFINE_PROP_BOOL("x-zba", RISCVCPU, cfg.ext_zba, false),
DEFINE_PROP_BOOL("x-zbb", RISCVCPU, cfg.ext_zbb, false),
DEFINE_PROP_BOOL("x-zbc", RISCVCPU, cfg.ext_zbc, false),
DEFINE_PROP_BOOL("x-zbs", RISCVCPU, cfg.ext_zbs, false),
DEFINE_PROP_BOOL("x-h", RISCVCPU, cfg.ext_h, false),
DEFINE_PROP_BOOL("x-v", RISCVCPU, cfg.ext_v, false),
DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),
DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
/* ePMP 0.9.3 */
DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
@@ -619,10 +644,13 @@ static gchar *riscv_gdb_arch_name(CPUState *cs)
RISCVCPU *cpu = RISCV_CPU(cs);
CPURISCVState *env = &cpu->env;
if (riscv_cpu_is_32bit(env)) {
switch (riscv_cpu_mxl(env)) {
case MXL_RV32:
return g_strdup("riscv:rv32");
} else {
case MXL_RV64:
return g_strdup("riscv:rv64");
default:
g_assert_not_reached();
}
}
@@ -705,7 +733,7 @@ char *riscv_isa_string(RISCVCPU *cpu)
char *isa_str = g_new(char, maxlen);
char *p = isa_str + snprintf(isa_str, maxlen, "rv%d", TARGET_LONG_BITS);
for (i = 0; i < sizeof(riscv_exts); i++) {
if (cpu->env.misa & RV(riscv_exts[i])) {
if (cpu->env.misa_ext & RV(riscv_exts[i])) {
*p++ = qemu_tolower(riscv_exts[i]);
}
}
+27 -60
View File
@@ -25,6 +25,7 @@
#include "exec/cpu-defs.h"
#include "fpu/softfloat-types.h"
#include "qom/object.h"
#include "cpu_bits.h"
#define TCG_GUEST_DEFAULT_MO 0
@@ -51,9 +52,6 @@
# define TYPE_RISCV_CPU_BASE TYPE_RISCV_CPU_BASE64
#endif
#define RV32 ((target_ulong)1 << (TARGET_LONG_BITS - 2))
#define RV64 ((target_ulong)2 << (TARGET_LONG_BITS - 2))
#define RV(x) ((target_ulong)1 << (x - 'A'))
#define RVI RV('I')
@@ -133,8 +131,12 @@ struct CPURISCVState {
target_ulong priv_ver;
target_ulong bext_ver;
target_ulong vext_ver;
target_ulong misa;
target_ulong misa_mask;
/* RISCVMXL, but uint32_t for vmstate migration */
uint32_t misa_mxl; /* current mxl */
uint32_t misa_mxl_max; /* max mxl for this cpu */
uint32_t misa_ext; /* current extensions */
uint32_t misa_ext_mask; /* max ext for this cpu */
uint32_t features;
@@ -313,7 +315,7 @@ struct RISCVCPU {
static inline int riscv_has_ext(CPURISCVState *env, target_ulong ext)
{
return (env->misa & ext) != 0;
return (env->misa_ext & ext) != 0;
}
static inline bool riscv_feature(CPURISCVState *env, int feature)
@@ -322,7 +324,6 @@ static inline bool riscv_feature(CPURISCVState *env, int feature)
}
#include "cpu_user.h"
#include "cpu_bits.h"
extern const char * const riscv_int_regnames[];
extern const char * const riscv_fpr_regnames[];
@@ -378,7 +379,6 @@ void QEMU_NORETURN riscv_raise_exception(CPURISCVState *env,
target_ulong riscv_cpu_get_fflags(CPURISCVState *env);
void riscv_cpu_set_fflags(CPURISCVState *env, target_ulong);
#define TB_FLAGS_MMU_MASK 7
#define TB_FLAGS_PRIV_MMU_MASK 3
#define TB_FLAGS_PRIV_HYP_ACCESS_MASK (1 << 2)
#define TB_FLAGS_MSTATUS_FS MSTATUS_FS
@@ -387,15 +387,25 @@ typedef CPURISCVState CPUArchState;
typedef RISCVCPU ArchCPU;
#include "exec/cpu-all.h"
FIELD(TB_FLAGS, VL_EQ_VLMAX, 2, 1)
FIELD(TB_FLAGS, LMUL, 3, 2)
FIELD(TB_FLAGS, SEW, 5, 3)
FIELD(TB_FLAGS, VILL, 8, 1)
FIELD(TB_FLAGS, MEM_IDX, 0, 3)
FIELD(TB_FLAGS, VL_EQ_VLMAX, 3, 1)
FIELD(TB_FLAGS, LMUL, 4, 2)
FIELD(TB_FLAGS, SEW, 6, 3)
FIELD(TB_FLAGS, VILL, 9, 1)
/* Is a Hypervisor instruction load/store allowed? */
FIELD(TB_FLAGS, HLSX, 9, 1)
FIELD(TB_FLAGS, MSTATUS_HS_FS, 10, 2)
FIELD(TB_FLAGS, HLSX, 10, 1)
FIELD(TB_FLAGS, MSTATUS_HS_FS, 11, 2)
/* The combination of MXL/SXL/UXL that applies to the current cpu mode. */
FIELD(TB_FLAGS, XL, 13, 2)
bool riscv_cpu_is_32bit(CPURISCVState *env);
#ifdef TARGET_RISCV32
#define riscv_cpu_mxl(env) ((void)(env), MXL_RV32)
#else
static inline RISCVMXL riscv_cpu_mxl(CPURISCVState *env)
{
return env->misa_mxl;
}
#endif
/*
* A simplification for VLMAX
@@ -413,51 +423,8 @@ static inline uint32_t vext_get_vlmax(RISCVCPU *cpu, target_ulong vtype)
return cpu->cfg.vlen >> (sew + 3 - lmul);
}
static inline void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
target_ulong *cs_base, uint32_t *pflags)
{
uint32_t flags = 0;
*pc = env->pc;
*cs_base = 0;
if (riscv_has_ext(env, RVV)) {
uint32_t vlmax = vext_get_vlmax(env_archcpu(env), env->vtype);
bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl);
flags = FIELD_DP32(flags, TB_FLAGS, VILL,
FIELD_EX64(env->vtype, VTYPE, VILL));
flags = FIELD_DP32(flags, TB_FLAGS, SEW,
FIELD_EX64(env->vtype, VTYPE, VSEW));
flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
FIELD_EX64(env->vtype, VTYPE, VLMUL));
flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
} else {
flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
}
#ifdef CONFIG_USER_ONLY
flags |= TB_FLAGS_MSTATUS_FS;
#else
flags |= cpu_mmu_index(env, 0);
if (riscv_cpu_fp_enabled(env)) {
flags |= env->mstatus & MSTATUS_FS;
}
if (riscv_has_ext(env, RVH)) {
if (env->priv == PRV_M ||
(env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
(env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
get_field(env->hstatus, HSTATUS_HU))) {
flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
}
flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_FS,
get_field(env->mstatus_hs, MSTATUS_FS));
}
#endif
*pflags = flags;
}
void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
target_ulong *cs_base, uint32_t *pflags);
RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
target_ulong *ret_value,
+5 -11
View File
@@ -364,9 +364,11 @@
#define MISA32_MXL 0xC0000000
#define MISA64_MXL 0xC000000000000000ULL
#define MXL_RV32 1
#define MXL_RV64 2
#define MXL_RV128 3
typedef enum {
MXL_RV32 = 1,
MXL_RV64 = 2,
MXL_RV128 = 3,
} RISCVMXL;
/* sstatus CSR bits */
#define SSTATUS_UIE 0x00000001
@@ -427,14 +429,6 @@
#define SATP64_ASID 0x0FFFF00000000000ULL
#define SATP64_PPN 0x00000FFFFFFFFFFFULL
/* VM modes (mstatus.vm) privileged ISA 1.9.1 */
#define VM_1_09_MBARE 0
#define VM_1_09_MBB 1
#define VM_1_09_MBBID 2
#define VM_1_09_SV32 8
#define VM_1_09_SV39 9
#define VM_1_09_SV48 10
/* VM modes (satp.mode) privileged ISA 1.10 */
#define VM_1_10_MBARE 0
#define VM_1_10_SV32 1
+85 -7
View File
@@ -35,6 +35,85 @@ int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
#endif
}
static RISCVMXL cpu_get_xl(CPURISCVState *env)
{
#if defined(TARGET_RISCV32)
return MXL_RV32;
#elif defined(CONFIG_USER_ONLY)
return MXL_RV64;
#else
RISCVMXL xl = riscv_cpu_mxl(env);
/*
* When emulating a 32-bit-only cpu, use RV32.
* When emulating a 64-bit cpu, and MXL has been reduced to RV32,
* MSTATUSH doesn't have UXL/SXL, therefore XLEN cannot be widened
* back to RV64 for lower privs.
*/
if (xl != MXL_RV32) {
switch (env->priv) {
case PRV_M:
break;
case PRV_U:
xl = get_field(env->mstatus, MSTATUS64_UXL);
break;
default: /* PRV_S | PRV_H */
xl = get_field(env->mstatus, MSTATUS64_SXL);
break;
}
}
return xl;
#endif
}
void cpu_get_tb_cpu_state(CPURISCVState *env, target_ulong *pc,
target_ulong *cs_base, uint32_t *pflags)
{
uint32_t flags = 0;
*pc = env->pc;
*cs_base = 0;
if (riscv_has_ext(env, RVV)) {
uint32_t vlmax = vext_get_vlmax(env_archcpu(env), env->vtype);
bool vl_eq_vlmax = (env->vstart == 0) && (vlmax == env->vl);
flags = FIELD_DP32(flags, TB_FLAGS, VILL,
FIELD_EX64(env->vtype, VTYPE, VILL));
flags = FIELD_DP32(flags, TB_FLAGS, SEW,
FIELD_EX64(env->vtype, VTYPE, VSEW));
flags = FIELD_DP32(flags, TB_FLAGS, LMUL,
FIELD_EX64(env->vtype, VTYPE, VLMUL));
flags = FIELD_DP32(flags, TB_FLAGS, VL_EQ_VLMAX, vl_eq_vlmax);
} else {
flags = FIELD_DP32(flags, TB_FLAGS, VILL, 1);
}
#ifdef CONFIG_USER_ONLY
flags |= TB_FLAGS_MSTATUS_FS;
#else
flags |= cpu_mmu_index(env, 0);
if (riscv_cpu_fp_enabled(env)) {
flags |= env->mstatus & MSTATUS_FS;
}
if (riscv_has_ext(env, RVH)) {
if (env->priv == PRV_M ||
(env->priv == PRV_S && !riscv_cpu_virt_enabled(env)) ||
(env->priv == PRV_U && !riscv_cpu_virt_enabled(env) &&
get_field(env->hstatus, HSTATUS_HU))) {
flags = FIELD_DP32(flags, TB_FLAGS, HLSX, 1);
}
flags = FIELD_DP32(flags, TB_FLAGS, MSTATUS_HS_FS,
get_field(env->mstatus_hs, MSTATUS_FS));
}
#endif
flags = FIELD_DP32(flags, TB_FLAGS, XL, cpu_get_xl(env));
*pflags = flags;
}
#ifndef CONFIG_USER_ONLY
static int riscv_cpu_local_irq_pending(CPURISCVState *env)
{
@@ -106,10 +185,9 @@ bool riscv_cpu_fp_enabled(CPURISCVState *env)
void riscv_cpu_swap_hypervisor_regs(CPURISCVState *env)
{
uint64_t sd = riscv_cpu_is_32bit(env) ? MSTATUS32_SD : MSTATUS64_SD;
uint64_t mstatus_mask = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_FS |
MSTATUS_SPP | MSTATUS_SPIE | MSTATUS_SIE |
MSTATUS64_UXL | sd;
MSTATUS64_UXL;
bool current_virt = riscv_cpu_virt_enabled(env);
g_assert(riscv_has_ext(env, RVH));
@@ -401,7 +479,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
if (first_stage == true) {
if (use_background) {
if (riscv_cpu_is_32bit(env)) {
if (riscv_cpu_mxl(env) == MXL_RV32) {
base = (hwaddr)get_field(env->vsatp, SATP32_PPN) << PGSHIFT;
vm = get_field(env->vsatp, SATP32_MODE);
} else {
@@ -409,7 +487,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
vm = get_field(env->vsatp, SATP64_MODE);
}
} else {
if (riscv_cpu_is_32bit(env)) {
if (riscv_cpu_mxl(env) == MXL_RV32) {
base = (hwaddr)get_field(env->satp, SATP32_PPN) << PGSHIFT;
vm = get_field(env->satp, SATP32_MODE);
} else {
@@ -419,7 +497,7 @@ static int get_physical_address(CPURISCVState *env, hwaddr *physical,
}
widened = 0;
} else {
if (riscv_cpu_is_32bit(env)) {
if (riscv_cpu_mxl(env) == MXL_RV32) {
base = (hwaddr)get_field(env->hgatp, SATP32_PPN) << PGSHIFT;
vm = get_field(env->hgatp, SATP32_MODE);
} else {
@@ -512,7 +590,7 @@ restart:
}
target_ulong pte;
if (riscv_cpu_is_32bit(env)) {
if (riscv_cpu_mxl(env) == MXL_RV32) {
pte = address_space_ldl(cs->as, pte_addr, attrs, &res);
} else {
pte = address_space_ldq(cs->as, pte_addr, attrs, &res);
@@ -632,7 +710,7 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
int page_fault_exceptions, vm;
uint64_t stap_mode;
if (riscv_cpu_is_32bit(env)) {
if (riscv_cpu_mxl(env) == MXL_RV32) {
stap_mode = SATP32_MODE;
} else {
stap_mode = SATP64_MODE;
+64 -40
View File
@@ -39,7 +39,7 @@ static RISCVException fs(CPURISCVState *env, int csrno)
{
#if !defined(CONFIG_USER_ONLY)
/* loose check condition for fcsr in vector extension */
if ((csrno == CSR_FCSR) && (env->misa & RVV)) {
if ((csrno == CSR_FCSR) && (env->misa_ext & RVV)) {
return RISCV_EXCP_NONE;
}
if (!env->debugger && !riscv_cpu_fp_enabled(env)) {
@@ -51,7 +51,7 @@ static RISCVException fs(CPURISCVState *env, int csrno)
static RISCVException vs(CPURISCVState *env, int csrno)
{
if (env->misa & RVV) {
if (env->misa_ext & RVV) {
return RISCV_EXCP_NONE;
}
return RISCV_EXCP_ILLEGAL_INST;
@@ -95,7 +95,7 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
}
break;
}
if (riscv_cpu_is_32bit(env)) {
if (riscv_cpu_mxl(env) == MXL_RV32) {
switch (csrno) {
case CSR_CYCLEH:
if (!get_field(env->hcounteren, COUNTEREN_CY) &&
@@ -130,7 +130,7 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
static RISCVException ctr32(CPURISCVState *env, int csrno)
{
if (!riscv_cpu_is_32bit(env)) {
if (riscv_cpu_mxl(env) != MXL_RV32) {
return RISCV_EXCP_ILLEGAL_INST;
}
@@ -145,7 +145,7 @@ static RISCVException any(CPURISCVState *env, int csrno)
static RISCVException any32(CPURISCVState *env, int csrno)
{
if (!riscv_cpu_is_32bit(env)) {
if (riscv_cpu_mxl(env) != MXL_RV32) {
return RISCV_EXCP_ILLEGAL_INST;
}
@@ -180,7 +180,7 @@ static RISCVException hmode(CPURISCVState *env, int csrno)
static RISCVException hmode32(CPURISCVState *env, int csrno)
{
if (!riscv_cpu_is_32bit(env)) {
if (riscv_cpu_mxl(env) != MXL_RV32) {
if (riscv_cpu_virt_enabled(env)) {
return RISCV_EXCP_ILLEGAL_INST;
} else {
@@ -477,16 +477,34 @@ static RISCVException read_mhartid(CPURISCVState *env, int csrno,
}
/* Machine Trap Setup */
/* We do not store SD explicitly, only compute it on demand. */
static uint64_t add_status_sd(RISCVMXL xl, uint64_t status)
{
if ((status & MSTATUS_FS) == MSTATUS_FS ||
(status & MSTATUS_XS) == MSTATUS_XS) {
switch (xl) {
case MXL_RV32:
return status | MSTATUS32_SD;
case MXL_RV64:
return status | MSTATUS64_SD;
default:
g_assert_not_reached();
}
}
return status;
}
static RISCVException read_mstatus(CPURISCVState *env, int csrno,
target_ulong *val)
{
*val = env->mstatus;
*val = add_status_sd(riscv_cpu_mxl(env), env->mstatus);
return RISCV_EXCP_NONE;
}
static int validate_vm(CPURISCVState *env, target_ulong vm)
{
if (riscv_cpu_is_32bit(env)) {
if (riscv_cpu_mxl(env) == MXL_RV32) {
return valid_vm_1_10_32[vm & 0xf];
} else {
return valid_vm_1_10_64[vm & 0xf];
@@ -498,7 +516,6 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
{
uint64_t mstatus = env->mstatus;
uint64_t mask = 0;
int dirty;
/* flush tlb on mstatus fields that affect VM */
if ((val ^ mstatus) & (MSTATUS_MXR | MSTATUS_MPP | MSTATUS_MPV |
@@ -510,7 +527,7 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR |
MSTATUS_TW;
if (!riscv_cpu_is_32bit(env)) {
if (riscv_cpu_mxl(env) != MXL_RV32) {
/*
* RV32: MPV and GVA are not in mstatus. The current plan is to
* add them to mstatush. For now, we just don't support it.
@@ -520,12 +537,10 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno,
mstatus = (mstatus & ~mask) | (val & mask);
dirty = ((mstatus & MSTATUS_FS) == MSTATUS_FS) |
((mstatus & MSTATUS_XS) == MSTATUS_XS);
if (riscv_cpu_is_32bit(env)) {
mstatus = set_field(mstatus, MSTATUS32_SD, dirty);
} else {
mstatus = set_field(mstatus, MSTATUS64_SD, dirty);
if (riscv_cpu_mxl(env) == MXL_RV64) {
/* SXL and UXL fields are for now read only */
mstatus = set_field(mstatus, MSTATUS64_SXL, MXL_RV64);
mstatus = set_field(mstatus, MSTATUS64_UXL, MXL_RV64);
}
env->mstatus = mstatus;
@@ -557,7 +572,22 @@ static RISCVException write_mstatush(CPURISCVState *env, int csrno,
static RISCVException read_misa(CPURISCVState *env, int csrno,
target_ulong *val)
{
*val = env->misa;
target_ulong misa;
switch (env->misa_mxl) {
case MXL_RV32:
misa = (target_ulong)MXL_RV32 << 30;
break;
#ifdef TARGET_RISCV64
case MXL_RV64:
misa = (target_ulong)MXL_RV64 << 62;
break;
#endif
default:
g_assert_not_reached();
}
*val = misa | env->misa_ext;
return RISCV_EXCP_NONE;
}
@@ -583,8 +613,13 @@ static RISCVException write_misa(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
/*
* misa.MXL writes are not supported by QEMU.
* Drop writes to those bits.
*/
/* Mask extensions that are not supported by this hart */
val &= env->misa_mask;
val &= env->misa_ext_mask;
/* Mask extensions that are not supported by QEMU */
val &= (RVI | RVE | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
@@ -601,20 +636,14 @@ static RISCVException write_misa(CPURISCVState *env, int csrno,
val &= ~RVC;
}
/* misa.MXL writes are not supported by QEMU */
if (riscv_cpu_is_32bit(env)) {
val = (env->misa & MISA32_MXL) | (val & ~MISA32_MXL);
} else {
val = (env->misa & MISA64_MXL) | (val & ~MISA64_MXL);
/* If nothing changed, do nothing. */
if (val == env->misa_ext) {
return RISCV_EXCP_NONE;
}
/* flush translation cache */
if (val != env->misa) {
tb_flush(env_cpu(env));
}
env->misa = val;
tb_flush(env_cpu(env));
env->misa_ext = val;
return RISCV_EXCP_NONE;
}
@@ -781,13 +810,8 @@ static RISCVException read_sstatus(CPURISCVState *env, int csrno,
{
target_ulong mask = (sstatus_v1_10_mask);
if (riscv_cpu_is_32bit(env)) {
mask |= SSTATUS32_SD;
} else {
mask |= SSTATUS64_SD;
}
*val = env->mstatus & mask;
/* TODO: Use SXL not MXL. */
*val = add_status_sd(riscv_cpu_mxl(env), env->mstatus & mask);
return RISCV_EXCP_NONE;
}
@@ -992,7 +1016,7 @@ static RISCVException write_satp(CPURISCVState *env, int csrno,
return RISCV_EXCP_NONE;
}
if (riscv_cpu_is_32bit(env)) {
if (riscv_cpu_mxl(env) == MXL_RV32) {
vm = validate_vm(env, get_field(val, SATP32_MODE));
mask = (val ^ env->satp) & (SATP32_MODE | SATP32_ASID | SATP32_PPN);
asid = (val ^ env->satp) & SATP32_ASID;
@@ -1020,7 +1044,7 @@ static RISCVException read_hstatus(CPURISCVState *env, int csrno,
target_ulong *val)
{
*val = env->hstatus;
if (!riscv_cpu_is_32bit(env)) {
if (riscv_cpu_mxl(env) != MXL_RV32) {
/* We only support 64-bit VSXL */
*val = set_field(*val, HSTATUS_VSXL, 2);
}
@@ -1033,7 +1057,7 @@ static RISCVException write_hstatus(CPURISCVState *env, int csrno,
target_ulong val)
{
env->hstatus = val;
if (!riscv_cpu_is_32bit(env) && get_field(val, HSTATUS_VSXL) != 2) {
if (riscv_cpu_mxl(env) != MXL_RV32 && get_field(val, HSTATUS_VSXL) != 2) {
qemu_log_mask(LOG_UNIMP, "QEMU does not support mixed HSXLEN options.");
}
if (get_field(val, HSTATUS_VSBE) != 0) {
@@ -1201,7 +1225,7 @@ static RISCVException write_htimedelta(CPURISCVState *env, int csrno,
return RISCV_EXCP_ILLEGAL_INST;
}
if (riscv_cpu_is_32bit(env)) {
if (riscv_cpu_mxl(env) == MXL_RV32) {
env->htimedelta = deposit64(env->htimedelta, 0, 32, (uint64_t)val);
} else {
env->htimedelta = val;

Some files were not shown because too many files have changed in this diff Show More