aboutsummaryrefslogtreecommitdiff
path: root/hw
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2023-07-10 21:42:50 +0100
committerRichard Henderson <richard.henderson@linaro.org>2023-07-10 21:42:50 +0100
commit94d68c11362240a26ce425f56e2451d88f6814e1 (patch)
tree2e345a15e1c0deecfd431d8a84f7c712272ad54c /hw
parent8d309a3a97e2d3734b74b07f355f860a9f2e880e (diff)
parenta47842d16653b4f73b5d56ff0c252dd8a329481b (diff)
Merge tag 'pull-riscv-to-apply-20230710-1' of https://github.com/alistair23/qemu into staging
Third RISC-V PR for 8.1 * Use xl instead of mxl for disassemble * Factor out extension tests to cpu_cfg.h * disas/riscv: Add vendor extension support * disas/riscv: Add support for XVentanaCondOps * disas/riscv: Add support for XThead* instructions * Fix mstatus related problems * Fix veyron-v1 CPU properties * Fix the xlen for data address when MPRV=1 * opensbi: Upgrade from v1.2 to v1.3 * Enable 32-bit Spike OpenSBI boot testing * Support the watchdog timer of HiFive 1 rev b * Only build qemu-system-riscv$$ on rv$$ host * Add RVV registers to log * Restrict ACLINT to TCG * Add syscall riscv_hwprobe * Add support for BF16 extensions * KVM_RISCV_SET_TIMER macro is not configured correctly * Generate devicetree only after machine initialization is complete * virt: Convert fdt_load_addr to uint64_t * KVM: fixes and enhancements * Add support for the Zfa extension # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEaukCtqfKh31tZZKWr3yVEwxTgBMFAmSr+ekACgkQr3yVEwxT # gBMMGg//ZCcyH3KXB49c2KUIFO6FKYUxN9uC3giZCtuGyEH8T2yDgZVVXnxwU+Ij # +3Ej6T/ZdWMpePC9qf+xKzHWZk7Qc8Tcg+JgQbga573894yZInRwYl8HsSlEKA+Z # vlqSBPxTlp9rlDwGP/LjGljyIFqL4konk9zi3FL4ZXTF1iHUGrh/953Y3wIreEfl # KX5UznnWcgy2BqQT1vihMbM8qCVK6iryH+QZ6LiAsPMSX1rIzk8ectQryILzoIYh # bMiwCLVMyr4ZrUXjmGTF+7/WcOWwhhyfpdstf2iotKALelZtVHit0wHcty2GYQde # nvN83jJWu04DGXkPBUsqCUQXczGo1QHjJUH3RIRJzfOby/lGt4pSzHAfKA+iNUht # ikM3SdBsXMO+ogjTtTcCMb7/m2vsMoQP60VRts9Mh3YVD0cgr7RqpqRoEMugVYnr # ca8Vijf71mB+y+pq477eV1Q8BoKpr8xa1OlFkNKPC17uMD7HoDMI44QgFOgtYp10 # TMsqqyB75q6PZhSEwm63xbmH0Zpo8kSqT/E3MTtGTyPeuL8TNNNSkCmFaGYmRrbI # XEp7vG2RaDJOvDomS3nUhA5ruc8SaXd0q25q2gLYQfCsehfFqZAwuNB5xf1zS0M0 # ov1/gwaqU93t6nLbo2cCbb0plkIFKwwJ9KKjD06wJ4KPe0TGFzk= # =3XFD # -----END PGP SIGNATURE----- # gpg: Signature made Mon 10 Jul 2023 01:30:33 PM BST # gpg: using RSA key 6AE902B6A7CA877D6D659296AF7C95130C538013 # gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 6AE9 02B6 A7CA 877D 6D65 9296 AF7C 9513 0C53 8013 * tag 'pull-riscv-to-apply-20230710-1' of https://github.com/alistair23/qemu: (54 commits) riscv: Add support for the Zfa extension target/riscv/kvm.c: read/write (cbom|cboz)_blocksize in KVM target/riscv/kvm.c: add kvmconfig_get_cfg_addr() helper target/riscv: update multi-letter extension KVM properties target/riscv/cpu.c: create KVM mock properties target/riscv/cpu.c: remove priv_ver check from riscv_isa_string_ext() target/riscv/cpu.c: add satp_mode properties earlier target/riscv/kvm.c: add multi-letter extension KVM properties target/riscv/kvm.c: update KVM MISA bits target/riscv: add KVM specific MISA properties target/riscv/cpu: add misa_ext_info_arr[] target/riscv/kvm.c: init 'misa_ext_mask' with scratch CPU target/riscv: handle mvendorid/marchid/mimpid for KVM CPUs target/riscv: read marchid/mimpid in kvm_riscv_init_machine_ids() target/riscv: use KVM scratch CPUs to init KVM properties target/riscv/cpu.c: restrict 'marchid' value target/riscv/cpu.c: restrict 'mimpid' value target/riscv/cpu.c: restrict 'mvendorid' value hw/riscv/virt.c: skip 'mmu-type' FDT if satp mode not set target/riscv: skip features setup for KVM CPUs ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'hw')
-rw-r--r--hw/misc/Kconfig3
-rw-r--r--hw/misc/meson.build1
-rw-r--r--hw/misc/sifive_e_aon.c319
-rw-r--r--hw/riscv/Kconfig1
-rw-r--r--hw/riscv/sifive_e.c17
-rw-r--r--hw/riscv/virt.c56
6 files changed, 368 insertions, 29 deletions
diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
index e4c2149175..6996d265e4 100644
--- a/hw/misc/Kconfig
+++ b/hw/misc/Kconfig
@@ -158,6 +158,9 @@ config SIFIVE_TEST
config SIFIVE_E_PRCI
bool
+config SIFIVE_E_AON
+ bool
+
config SIFIVE_U_OTP
bool
diff --git a/hw/misc/meson.build b/hw/misc/meson.build
index 05877f61cc..892f8b91c5 100644
--- a/hw/misc/meson.build
+++ b/hw/misc/meson.build
@@ -30,6 +30,7 @@ system_ss.add(when: 'CONFIG_MCHP_PFSOC_IOSCB', if_true: files('mchp_pfsoc_ioscb.
system_ss.add(when: 'CONFIG_MCHP_PFSOC_SYSREG', if_true: files('mchp_pfsoc_sysreg.c'))
system_ss.add(when: 'CONFIG_SIFIVE_TEST', if_true: files('sifive_test.c'))
system_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: files('sifive_e_prci.c'))
+system_ss.add(when: 'CONFIG_SIFIVE_E_AON', if_true: files('sifive_e_aon.c'))
system_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c'))
system_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: files('sifive_u_prci.c'))
diff --git a/hw/misc/sifive_e_aon.c b/hw/misc/sifive_e_aon.c
new file mode 100644
index 0000000000..4656457d0b
--- /dev/null
+++ b/hw/misc/sifive_e_aon.c
@@ -0,0 +1,319 @@
+/*
+ * SiFive HiFive1 AON (Always On Domain) for QEMU.
+ *
+ * Copyright (c) 2022 SiFive, Inc. All rights reserved.
+ *
+ * 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/timer.h"
+#include "qemu/log.h"
+#include "hw/irq.h"
+#include "hw/registerfields.h"
+#include "hw/misc/sifive_e_aon.h"
+#include "qapi/visitor.h"
+#include "qapi/error.h"
+#include "sysemu/watchdog.h"
+#include "hw/qdev-properties.h"
+
+REG32(AON_WDT_WDOGCFG, 0x0)
+ FIELD(AON_WDT_WDOGCFG, SCALE, 0, 4)
+ FIELD(AON_WDT_WDOGCFG, RSVD0, 4, 4)
+ FIELD(AON_WDT_WDOGCFG, RSTEN, 8, 1)
+ FIELD(AON_WDT_WDOGCFG, ZEROCMP, 9, 1)
+ FIELD(AON_WDT_WDOGCFG, RSVD1, 10, 2)
+ FIELD(AON_WDT_WDOGCFG, EN_ALWAYS, 12, 1)
+ FIELD(AON_WDT_WDOGCFG, EN_CORE_AWAKE, 13, 1)
+ FIELD(AON_WDT_WDOGCFG, RSVD2, 14, 14)
+ FIELD(AON_WDT_WDOGCFG, IP0, 28, 1)
+ FIELD(AON_WDT_WDOGCFG, RSVD3, 29, 3)
+REG32(AON_WDT_WDOGCOUNT, 0x8)
+ FIELD(AON_WDT_WDOGCOUNT, VALUE, 0, 31)
+REG32(AON_WDT_WDOGS, 0x10)
+REG32(AON_WDT_WDOGFEED, 0x18)
+REG32(AON_WDT_WDOGKEY, 0x1c)
+REG32(AON_WDT_WDOGCMP0, 0x20)
+
+static void sifive_e_aon_wdt_update_wdogcount(SiFiveEAONState *r)
+{
+ int64_t now;
+ if (FIELD_EX32(r->wdogcfg, AON_WDT_WDOGCFG, EN_ALWAYS) == 0 &&
+ FIELD_EX32(r->wdogcfg, AON_WDT_WDOGCFG, EN_CORE_AWAKE) == 0) {
+ return;
+ }
+
+ now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ r->wdogcount += muldiv64(now - r->wdog_restart_time,
+ r->wdogclk_freq, NANOSECONDS_PER_SECOND);
+
+ /* Clean the most significant bit. */
+ r->wdogcount &= R_AON_WDT_WDOGCOUNT_VALUE_MASK;
+ r->wdog_restart_time = now;
+}
+
+static void sifive_e_aon_wdt_update_state(SiFiveEAONState *r)
+{
+ uint16_t wdogs;
+ bool cmp_signal = false;
+ sifive_e_aon_wdt_update_wdogcount(r);
+ wdogs = (uint16_t)(r->wdogcount >>
+ FIELD_EX32(r->wdogcfg, AON_WDT_WDOGCFG, SCALE));
+
+ if (wdogs >= r->wdogcmp0) {
+ cmp_signal = true;
+ if (FIELD_EX32(r->wdogcfg, AON_WDT_WDOGCFG, ZEROCMP) == 1) {
+ r->wdogcount = 0;
+ wdogs = 0;
+ }
+ }
+
+ if (cmp_signal) {
+ if (FIELD_EX32(r->wdogcfg, AON_WDT_WDOGCFG, RSTEN) == 1) {
+ watchdog_perform_action();
+ }
+ r->wdogcfg = FIELD_DP32(r->wdogcfg, AON_WDT_WDOGCFG, IP0, 1);
+ }
+
+ qemu_set_irq(r->wdog_irq, FIELD_EX32(r->wdogcfg, AON_WDT_WDOGCFG, IP0));
+
+ if (wdogs < r->wdogcmp0 &&
+ (FIELD_EX32(r->wdogcfg, AON_WDT_WDOGCFG, EN_ALWAYS) == 1 ||
+ FIELD_EX32(r->wdogcfg, AON_WDT_WDOGCFG, EN_CORE_AWAKE) == 1)) {
+ int64_t next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ next += muldiv64((r->wdogcmp0 - wdogs) <<
+ FIELD_EX32(r->wdogcfg, AON_WDT_WDOGCFG, SCALE),
+ NANOSECONDS_PER_SECOND, r->wdogclk_freq);
+ timer_mod(r->wdog_timer, next);
+ } else {
+ timer_mod(r->wdog_timer, INT64_MAX);
+ }
+}
+
+/*
+ * Callback used when the timer set using timer_mod expires.
+ */
+static void sifive_e_aon_wdt_expired_cb(void *opaque)
+{
+ SiFiveEAONState *r = SIFIVE_E_AON(opaque);
+ sifive_e_aon_wdt_update_state(r);
+}
+
+static uint64_t
+sifive_e_aon_wdt_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ SiFiveEAONState *r = SIFIVE_E_AON(opaque);
+
+ switch (addr) {
+ case A_AON_WDT_WDOGCFG:
+ return r->wdogcfg;
+ case A_AON_WDT_WDOGCOUNT:
+ sifive_e_aon_wdt_update_wdogcount(r);
+ return r->wdogcount;
+ case A_AON_WDT_WDOGS:
+ sifive_e_aon_wdt_update_wdogcount(r);
+ return r->wdogcount >>
+ FIELD_EX32(r->wdogcfg,
+ AON_WDT_WDOGCFG,
+ SCALE);
+ case A_AON_WDT_WDOGFEED:
+ return 0;
+ case A_AON_WDT_WDOGKEY:
+ return r->wdogunlock;
+ case A_AON_WDT_WDOGCMP0:
+ return r->wdogcmp0;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad read: addr=0x%x\n",
+ __func__, (int)addr);
+ }
+
+ return 0;
+}
+
+static void
+sifive_e_aon_wdt_write(void *opaque, hwaddr addr,
+ uint64_t val64, unsigned int size)
+{
+ SiFiveEAONState *r = SIFIVE_E_AON(opaque);
+ uint32_t value = val64;
+
+ switch (addr) {
+ case A_AON_WDT_WDOGCFG: {
+ uint8_t new_en_always;
+ uint8_t new_en_core_awake;
+ uint8_t old_en_always;
+ uint8_t old_en_core_awake;
+ if (r->wdogunlock == 0) {
+ return;
+ }
+
+ new_en_always = FIELD_EX32(value, AON_WDT_WDOGCFG, EN_ALWAYS);
+ new_en_core_awake = FIELD_EX32(value, AON_WDT_WDOGCFG, EN_CORE_AWAKE);
+ old_en_always = FIELD_EX32(r->wdogcfg, AON_WDT_WDOGCFG, EN_ALWAYS);
+ old_en_core_awake = FIELD_EX32(r->wdogcfg, AON_WDT_WDOGCFG,
+ EN_CORE_AWAKE);
+
+ if ((old_en_always ||
+ old_en_core_awake) == 1 &&
+ (new_en_always ||
+ new_en_core_awake) == 0) {
+ sifive_e_aon_wdt_update_wdogcount(r);
+ } else if ((old_en_always ||
+ old_en_core_awake) == 0 &&
+ (new_en_always ||
+ new_en_core_awake) == 1) {
+ r->wdog_restart_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ }
+ r->wdogcfg = value;
+ r->wdogunlock = 0;
+ break;
+ }
+ case A_AON_WDT_WDOGCOUNT:
+ if (r->wdogunlock == 0) {
+ return;
+ }
+ r->wdogcount = value & R_AON_WDT_WDOGCOUNT_VALUE_MASK;
+ r->wdog_restart_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ r->wdogunlock = 0;
+ break;
+ case A_AON_WDT_WDOGS:
+ return;
+ case A_AON_WDT_WDOGFEED:
+ if (r->wdogunlock == 0) {
+ return;
+ }
+ if (value == SIFIVE_E_AON_WDOGFEED) {
+ r->wdogcount = 0;
+ r->wdog_restart_time = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ }
+ r->wdogunlock = 0;
+ break;
+ case A_AON_WDT_WDOGKEY:
+ if (value == SIFIVE_E_AON_WDOGKEY) {
+ r->wdogunlock = 1;
+ }
+ break;
+ case A_AON_WDT_WDOGCMP0:
+ if (r->wdogunlock == 0) {
+ return;
+ }
+ r->wdogcmp0 = (uint16_t) value;
+ r->wdogunlock = 0;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%x v=0x%x\n",
+ __func__, (int)addr, (int)value);
+ }
+ sifive_e_aon_wdt_update_state(r);
+}
+
+static uint64_t
+sifive_e_aon_read(void *opaque, hwaddr addr, unsigned int size)
+{
+ if (addr < SIFIVE_E_AON_RTC) {
+ return sifive_e_aon_wdt_read(opaque, addr, size);
+ } else if (addr < SIFIVE_E_AON_MAX) {
+ qemu_log_mask(LOG_UNIMP, "%s: Unimplemented read: addr=0x%x\n",
+ __func__, (int)addr);
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad read: addr=0x%x\n",
+ __func__, (int)addr);
+ }
+ return 0;
+}
+
+static void
+sifive_e_aon_write(void *opaque, hwaddr addr,
+ uint64_t val64, unsigned int size)
+{
+ if (addr < SIFIVE_E_AON_RTC) {
+ sifive_e_aon_wdt_write(opaque, addr, val64, size);
+ } else if (addr < SIFIVE_E_AON_MAX) {
+ qemu_log_mask(LOG_UNIMP, "%s: Unimplemented write: addr=0x%x\n",
+ __func__, (int)addr);
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: bad write: addr=0x%x\n",
+ __func__, (int)addr);
+ }
+}
+
+static const MemoryRegionOps sifive_e_aon_ops = {
+ .read = sifive_e_aon_read,
+ .write = sifive_e_aon_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .impl = {
+ .min_access_size = 4,
+ .max_access_size = 4
+ },
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4
+ }
+};
+
+static void sifive_e_aon_reset(DeviceState *dev)
+{
+ SiFiveEAONState *r = SIFIVE_E_AON(dev);
+
+ r->wdogcfg = FIELD_DP32(r->wdogcfg, AON_WDT_WDOGCFG, RSTEN, 0);
+ r->wdogcfg = FIELD_DP32(r->wdogcfg, AON_WDT_WDOGCFG, EN_ALWAYS, 0);
+ r->wdogcfg = FIELD_DP32(r->wdogcfg, AON_WDT_WDOGCFG, EN_CORE_AWAKE, 0);
+ r->wdogcmp0 = 0xbeef;
+
+ sifive_e_aon_wdt_update_state(r);
+}
+
+static void sifive_e_aon_init(Object *obj)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ SiFiveEAONState *r = SIFIVE_E_AON(obj);
+
+ memory_region_init_io(&r->mmio, OBJECT(r), &sifive_e_aon_ops, r,
+ TYPE_SIFIVE_E_AON, SIFIVE_E_AON_MAX);
+ sysbus_init_mmio(sbd, &r->mmio);
+
+ /* watchdog timer */
+ r->wdog_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
+ sifive_e_aon_wdt_expired_cb, r);
+ r->wdogclk_freq = SIFIVE_E_LFCLK_DEFAULT_FREQ;
+ sysbus_init_irq(sbd, &r->wdog_irq);
+}
+
+static Property sifive_e_aon_properties[] = {
+ DEFINE_PROP_UINT64("wdogclk-frequency", SiFiveEAONState, wdogclk_freq,
+ SIFIVE_E_LFCLK_DEFAULT_FREQ),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void sifive_e_aon_class_init(ObjectClass *oc, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(oc);
+
+ dc->reset = sifive_e_aon_reset;
+ device_class_set_props(dc, sifive_e_aon_properties);
+}
+
+static const TypeInfo sifive_e_aon_info = {
+ .name = TYPE_SIFIVE_E_AON,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(SiFiveEAONState),
+ .instance_init = sifive_e_aon_init,
+ .class_init = sifive_e_aon_class_init,
+};
+
+static void sifive_e_aon_register_types(void)
+{
+ type_register_static(&sifive_e_aon_info);
+}
+
+type_init(sifive_e_aon_register_types)
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index 6528ebfa3a..b6a5eb4452 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -60,6 +60,7 @@ config SIFIVE_E
select SIFIVE_PLIC
select SIFIVE_UART
select SIFIVE_E_PRCI
+ select SIFIVE_E_AON
select UNIMP
config SIFIVE_U
diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
index 04939b60c3..0d37adc542 100644
--- a/hw/riscv/sifive_e.c
+++ b/hw/riscv/sifive_e.c
@@ -45,6 +45,7 @@
#include "hw/intc/riscv_aclint.h"
#include "hw/intc/sifive_plic.h"
#include "hw/misc/sifive_e_prci.h"
+#include "hw/misc/sifive_e_aon.h"
#include "chardev/char.h"
#include "sysemu/sysemu.h"
@@ -185,6 +186,8 @@ static void sifive_e_soc_init(Object *obj)
object_property_set_int(OBJECT(&s->cpus), "resetvec", 0x1004, &error_abort);
object_initialize_child(obj, "riscv.sifive.e.gpio0", &s->gpio,
TYPE_SIFIVE_GPIO);
+ object_initialize_child(obj, "riscv.sifive.e.aon", &s->aon,
+ TYPE_SIFIVE_E_AON);
}
static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
@@ -223,10 +226,17 @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus,
RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, false);
- create_unimplemented_device("riscv.sifive.e.aon",
- memmap[SIFIVE_E_DEV_AON].base, memmap[SIFIVE_E_DEV_AON].size);
sifive_e_prci_create(memmap[SIFIVE_E_DEV_PRCI].base);
+ /* AON */
+
+ if (!sysbus_realize(SYS_BUS_DEVICE(&s->aon), errp)) {
+ return;
+ }
+
+ /* Map AON registers */
+ sysbus_mmio_map(SYS_BUS_DEVICE(&s->aon), 0, memmap[SIFIVE_E_DEV_AON].base);
+
/* GPIO */
if (!sysbus_realize(SYS_BUS_DEVICE(&s->gpio), errp)) {
@@ -245,6 +255,9 @@ static void sifive_e_soc_realize(DeviceState *dev, Error **errp)
qdev_get_gpio_in(DEVICE(s->plic),
SIFIVE_E_GPIO0_IRQ0 + i));
}
+ sysbus_connect_irq(SYS_BUS_DEVICE(&s->aon), 0,
+ qdev_get_gpio_in(DEVICE(s->plic),
+ SIFIVE_E_AON_WDT_IRQ));
sifive_uart_create(sys_mem, memmap[SIFIVE_E_DEV_UART0].base,
serial_hd(0), qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_E_UART0_IRQ));
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index 68ccd0bde1..d90286dc46 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -44,6 +44,7 @@
#include "chardev/char.h"
#include "sysemu/device_tree.h"
#include "sysemu/sysemu.h"
+#include "sysemu/tcg.h"
#include "sysemu/kvm.h"
#include "sysemu/tpm.h"
#include "hw/pci/pci.h"
@@ -243,13 +244,13 @@ static void create_fdt_socket_cpus(RISCVVirtState *s, int socket,
s->soc[socket].hartid_base + cpu);
qemu_fdt_add_subnode(ms->fdt, cpu_name);
- satp_mode_max = satp_mode_max_from_map(
- s->soc[socket].harts[cpu].cfg.satp_mode.map);
- sv_name = g_strdup_printf("riscv,%s",
- satp_mode_str(satp_mode_max, is_32_bit));
- qemu_fdt_setprop_string(ms->fdt, cpu_name, "mmu-type", sv_name);
- g_free(sv_name);
-
+ if (cpu_ptr->cfg.satp_mode.supported != 0) {
+ satp_mode_max = satp_mode_max_from_map(cpu_ptr->cfg.satp_mode.map);
+ sv_name = g_strdup_printf("riscv,%s",
+ satp_mode_str(satp_mode_max, is_32_bit));
+ qemu_fdt_setprop_string(ms->fdt, cpu_name, "mmu-type", sv_name);
+ g_free(sv_name);
+ }
name = riscv_isa_string(cpu_ptr);
qemu_fdt_setprop_string(ms->fdt, cpu_name, "riscv,isa", name);
@@ -776,7 +777,7 @@ static void create_fdt_sockets(RISCVVirtState *s, const MemMapEntry *memmap,
g_free(clust_name);
- if (!kvm_enabled()) {
+ if (tcg_enabled()) {
if (s->have_aclint) {
create_fdt_socket_aclint(s, memmap, socket,
&intc_phandles[phandle_pos]);
@@ -1244,10 +1245,21 @@ static void virt_machine_done(Notifier *notifier, void *data)
target_ulong start_addr = memmap[VIRT_DRAM].base;
target_ulong firmware_end_addr, kernel_start_addr;
const char *firmware_name = riscv_default_firmware_name(&s->soc[0]);
- uint32_t fdt_load_addr;
+ uint64_t fdt_load_addr;
uint64_t kernel_entry = 0;
BlockBackend *pflash_blk0;
+ /* load/create device tree */
+ if (machine->dtb) {
+ machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);
+ if (!machine->fdt) {
+ error_report("load_device_tree() failed");
+ exit(1);
+ }
+ } else {
+ create_fdt(s, memmap);
+ }
+
/*
* Only direct boot kernel is currently supported for KVM VM,
* so the "-bios" parameter is not supported when KVM is enabled.
@@ -1370,7 +1382,7 @@ static void virt_machine_init(MachineState *machine)
hart_count, &error_abort);
sysbus_realize(SYS_BUS_DEVICE(&s->soc[i]), &error_fatal);
- if (!kvm_enabled()) {
+ if (tcg_enabled()) {
if (s->have_aclint) {
if (s->aia_type == VIRT_AIA_TYPE_APLIC_IMSIC) {
/* Per-socket ACLINT MTIMER */
@@ -1508,17 +1520,6 @@ static void virt_machine_init(MachineState *machine)
}
virt_flash_map(s, system_memory);
- /* load/create device tree */
- if (machine->dtb) {
- machine->fdt = load_device_tree(machine->dtb, &s->fdt_size);
- if (!machine->fdt) {
- error_report("load_device_tree() failed");
- exit(1);
- }
- } else {
- create_fdt(s, memmap);
- }
-
s->machine_done.notify = virt_machine_done;
qemu_add_machine_init_done_notifier(&s->machine_done);
}
@@ -1682,12 +1683,13 @@ static void virt_machine_class_init(ObjectClass *oc, void *data)
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
#endif
- object_class_property_add_bool(oc, "aclint", virt_get_aclint,
- virt_set_aclint);
- object_class_property_set_description(oc, "aclint",
- "Set on/off to enable/disable "
- "emulating ACLINT devices");
-
+ if (tcg_enabled()) {
+ object_class_property_add_bool(oc, "aclint", virt_get_aclint,
+ virt_set_aclint);
+ object_class_property_set_description(oc, "aclint",
+ "Set on/off to enable/disable "
+ "emulating ACLINT devices");
+ }
object_class_property_add_str(oc, "aia", virt_get_aia,
virt_set_aia);
object_class_property_set_description(oc, "aia",