aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml5
-rw-r--r--MAINTAINERS1
-rw-r--r--chardev/char-file.c8
-rw-r--r--chardev/char.c3
-rw-r--r--cpu.c2
-rw-r--r--docs/devel/kconfig.rst2
-rw-r--r--docs/system/arm/cubieboard.rst1
-rw-r--r--docs/system/arm/emulation.rst1
-rw-r--r--docs/system/arm/orangepi.rst1
-rw-r--r--docs/system/devices/cxl.rst2
-rw-r--r--docs/system/introduction.rst2
-rw-r--r--gdb-xml/aarch64-pauth.xml2
-rw-r--r--hw/arm/Kconfig4
-rw-r--r--hw/arm/allwinner-a10.c7
-rw-r--r--hw/arm/allwinner-h3.c8
-rw-r--r--hw/arm/exynos4210.c4
-rw-r--r--hw/arm/fsl-imx6ul.c20
-rw-r--r--hw/arm/fsl-imx7.c20
-rw-r--r--hw/arm/mcimx6ul-evk.c2
-rw-r--r--hw/arm/mcimx7d-sabre.c2
-rw-r--r--hw/arm/musicpal.c2
-rw-r--r--hw/arm/omap1.c2
-rw-r--r--hw/arm/omap2.c2
-rw-r--r--hw/arm/virt-acpi-build.c2
-rw-r--r--hw/arm/virt.c13
-rw-r--r--hw/arm/xlnx-versal-virt.c2
-rw-r--r--hw/char/meson.build5
-rw-r--r--hw/core/machine.c3
-rw-r--r--hw/core/meson.build2
-rw-r--r--hw/display/meson.build2
-rw-r--r--hw/display/vga.c31
-rw-r--r--hw/i386/pc.c3
-rw-r--r--hw/i386/pc_piix.c16
-rw-r--r--hw/i386/pc_q35.c14
-rw-r--r--hw/m68k/virt.c9
-rw-r--r--hw/net/imx_fec.c27
-rw-r--r--hw/ppc/spapr.c15
-rw-r--r--hw/ppc/spapr_rtas.c29
-rw-r--r--hw/s390x/s390-virtio-ccw.c14
-rw-r--r--hw/timer/exynos4210_mct.c13
-rw-r--r--hw/timer/imx_epit.c2
-rw-r--r--hw/watchdog/Kconfig4
-rw-r--r--hw/watchdog/allwinner-wdt.c416
-rw-r--r--hw/watchdog/meson.build1
-rw-r--r--hw/watchdog/trace-events7
-rw-r--r--include/exec/cpu-all.h64
-rw-r--r--include/exec/cpu-common.h2
-rw-r--r--include/exec/tswap.h72
-rw-r--r--include/hw/arm/allwinner-a10.h2
-rw-r--r--include/hw/arm/allwinner-h3.h5
-rw-r--r--include/hw/arm/fsl-imx6ul.h1
-rw-r--r--include/hw/arm/fsl-imx7.h1
-rw-r--r--include/hw/boards.h3
-rw-r--r--include/hw/i386/pc.h3
-rw-r--r--include/hw/net/imx_fec.h2
-rw-r--r--include/hw/watchdog/allwinner-wdt.h123
-rw-r--r--include/sysemu/qtest.h4
-rw-r--r--qemu-options.hx10
-rw-r--r--softmmu/dirtylimit.c3
-rw-r--r--softmmu/meson.build4
-rw-r--r--softmmu/qtest.c53
-rw-r--r--softmmu/vl.c2
-rw-r--r--target/arm/cpu.h5
-rw-r--r--target/arm/cpu64.c2
-rw-r--r--target/arm/cpu_tcg.c2
-rw-r--r--target/arm/gdbstub.c9
-rw-r--r--target/arm/kvm-consts.h9
-rw-r--r--target/arm/kvm.c2
-rw-r--r--target/arm/kvm64.c18
-rw-r--r--target/arm/kvm_arm.h8
-rw-r--r--target/arm/ptw.c14
-rw-r--r--target/arm/tcg/tlb_helper.c26
-rw-r--r--target/i386/cpu.c31
-rw-r--r--tests/avocado/boot_linux_console.py15
-rw-r--r--tests/qtest/migration-test.c23
-rw-r--r--tests/unit/test-crypto-secret.c10
-rwxr-xr-xtests/vm/freebsd101
77 files changed, 1075 insertions, 287 deletions
diff --git a/.travis.yml b/.travis.yml
index cf088ba..b958eca 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -237,13 +237,15 @@ jobs:
- libglib2.0-dev
- libgnutls28-dev
- ninja-build
+ - flex
+ - bison
env:
- CONFIG="--disable-containers --disable-system"
- name: "[s390x] Clang (disable-tcg)"
arch: s390x
dist: focal
- compiler: clang
+ compiler: clang-10
addons:
apt_packages:
- libaio-dev
@@ -269,6 +271,7 @@ jobs:
- libvdeplug-dev
- libvte-2.91-dev
- ninja-build
+ - clang-10
env:
- TEST_CMD="make check-unit"
- CONFIG="--disable-containers --disable-tcg --enable-kvm --disable-tools
diff --git a/MAINTAINERS b/MAINTAINERS
index 2c2068e..24154f5 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -70,6 +70,7 @@ R: Daniel P. Berrangé <berrange@redhat.com>
R: Thomas Huth <thuth@redhat.com>
R: Markus Armbruster <armbru@redhat.com>
R: Philippe Mathieu-Daudé <philmd@linaro.org>
+R: Juan Quintela <quintela@redhat.com>
W: https://www.qemu.org/docs/master/devel/index.html
S: Odd Fixes
F: docs/devel/style.rst
diff --git a/chardev/char-file.c b/chardev/char-file.c
index 3a7b9ca..263e6da 100644
--- a/chardev/char-file.c
+++ b/chardev/char-file.c
@@ -100,6 +100,7 @@ static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend,
Error **errp)
{
const char *path = qemu_opt_get(opts, "path");
+ const char *inpath = qemu_opt_get(opts, "input-path");
ChardevFile *file;
backend->type = CHARDEV_BACKEND_KIND_FILE;
@@ -107,9 +108,16 @@ static void qemu_chr_parse_file_out(QemuOpts *opts, ChardevBackend *backend,
error_setg(errp, "chardev: file: no filename given");
return;
}
+#ifdef _WIN32
+ if (inpath) {
+ error_setg(errp, "chardev: file: input-path not supported on Windows");
+ return;
+ }
+#endif
file = backend->u.file.data = g_new0(ChardevFile, 1);
qemu_chr_parse_common(opts, qapi_ChardevFile_base(file));
file->out = g_strdup(path);
+ file->in = g_strdup(inpath);
file->has_append = true;
file->append = qemu_opt_get_bool(opts, "append", false);
diff --git a/chardev/char.c b/chardev/char.c
index e693906..661ad81 100644
--- a/chardev/char.c
+++ b/chardev/char.c
@@ -806,6 +806,9 @@ QemuOptsList qemu_chardev_opts = {
.name = "path",
.type = QEMU_OPT_STRING,
},{
+ .name = "input-path",
+ .type = QEMU_OPT_STRING,
+ },{
.name = "host",
.type = QEMU_OPT_STRING,
},{
diff --git a/cpu.c b/cpu.c
index 849bac0..9105c85 100644
--- a/cpu.c
+++ b/cpu.c
@@ -284,7 +284,7 @@ const char *parse_cpu_option(const char *cpu_option)
return cpu_type;
}
-void list_cpus(const char *optarg)
+void list_cpus(void)
{
/* XXX: implement xxx_cpu_list for targets that still miss it */
#if defined(cpu_list)
diff --git a/docs/devel/kconfig.rst b/docs/devel/kconfig.rst
index cc1a456..ac9453e 100644
--- a/docs/devel/kconfig.rst
+++ b/docs/devel/kconfig.rst
@@ -274,7 +274,7 @@ or commenting out lines in the second group.
It is also possible to run QEMU's configure script with the
``--without-default-devices`` option. When this is done, everything defaults
-to ``n`` unless it is ``select``ed or explicitly switched on in the
+to ``n`` unless it is ``select``\ ed or explicitly switched on in the
``.mak`` files. In other words, ``default`` and ``imply`` directives
are disabled. When QEMU is built with this option, the user will probably
want to change some lines in the first group, for example like this::
diff --git a/docs/system/arm/cubieboard.rst b/docs/system/arm/cubieboard.rst
index 8d485f5..58c4a2d 100644
--- a/docs/system/arm/cubieboard.rst
+++ b/docs/system/arm/cubieboard.rst
@@ -15,3 +15,4 @@ Emulated devices:
- USB controller
- SATA controller
- TWI (I2C) controller
+- Watchdog timer
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index 2062d71..7338987 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -56,6 +56,7 @@ the following architecture extensions:
- FEAT_MTE3 (MTE Asymmetric Fault Handling)
- FEAT_PAN (Privileged access never)
- FEAT_PAN2 (AT S1E1R and AT S1E1W instruction variants affected by PSTATE.PAN)
+- FEAT_PAN3 (Support for SCTLR_ELx.EPAN)
- FEAT_PAuth (Pointer authentication)
- FEAT_PMULL (PMULL, PMULL2 instructions)
- FEAT_PMUv3p1 (PMU Extensions v3.1)
diff --git a/docs/system/arm/orangepi.rst b/docs/system/arm/orangepi.rst
index e597360..9afa542 100644
--- a/docs/system/arm/orangepi.rst
+++ b/docs/system/arm/orangepi.rst
@@ -26,6 +26,7 @@ The Orange Pi PC machine supports the following devices:
* System Control module
* Security Identifier device
* TWI (I2C)
+ * Watchdog timer
Limitations
"""""""""""
diff --git a/docs/system/devices/cxl.rst b/docs/system/devices/cxl.rst
index f25783a..4c38223 100644
--- a/docs/system/devices/cxl.rst
+++ b/docs/system/devices/cxl.rst
@@ -111,7 +111,7 @@ Interfaces provided include:
CXL Root Ports (CXL RP)
~~~~~~~~~~~~~~~~~~~~~~~
-A CXL Root Port servers te same purpose as a PCIe Root Port.
+A CXL Root Port serves the same purpose as a PCIe Root Port.
There are a number of CXL specific Designated Vendor Specific
Extended Capabilities (DVSEC) in PCIe Configuration Space
and associated component register access via PCI bars.
diff --git a/docs/system/introduction.rst b/docs/system/introduction.rst
index c8a9fe6..3e256f8 100644
--- a/docs/system/introduction.rst
+++ b/docs/system/introduction.rst
@@ -27,7 +27,7 @@ Tiny Code Generator (TCG) capable of emulating many CPUs.
* - Hypervisor Framework (hvf)
- MacOS
- x86 (64 bit only), Arm (64 bit only)
- * - Windows Hypervisor Platform (wphx)
+ * - Windows Hypervisor Platform (whpx)
- Windows
- x86
* - NetBSD Virtual Machine Monitor (nvmm)
diff --git a/gdb-xml/aarch64-pauth.xml b/gdb-xml/aarch64-pauth.xml
index 24af5f9..0a5c566 100644
--- a/gdb-xml/aarch64-pauth.xml
+++ b/gdb-xml/aarch64-pauth.xml
@@ -6,7 +6,7 @@
notice and this notice are preserved. -->
<!DOCTYPE feature SYSTEM "gdb-target.dtd">
-<feature name="org.gnu.gdb.aarch64.pauth">
+<feature name="org.gnu.gdb.aarch64.pauth_v2">
<reg name="pauth_dmask" bitsize="64"/>
<reg name="pauth_cmask" bitsize="64"/>
<reg name="pauth_dmask_high" bitsize="64"/>
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 05d6ef1..b53bd7f 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -127,7 +127,7 @@ config OLIMEX_STM32_H405
config NSERIES
bool
select OMAP
- select TMP105 # tempature sensor
+ select TMP105 # temperature sensor
select BLIZZARD # LCD/TV controller
select ONENAND
select TSC210X # touchscreen/sensors/audio
@@ -326,6 +326,7 @@ config ALLWINNER_A10
select ALLWINNER_A10_PIC
select ALLWINNER_A10_CCM
select ALLWINNER_A10_DRAMC
+ select ALLWINNER_WDT
select ALLWINNER_EMAC
select ALLWINNER_I2C
select AXP209_PMU
@@ -337,6 +338,7 @@ config ALLWINNER_H3
select ALLWINNER_A10_PIT
select ALLWINNER_SUN8I_EMAC
select ALLWINNER_I2C
+ select ALLWINNER_WDT
select SERIAL
select ARM_TIMER
select ARM_GIC
diff --git a/hw/arm/allwinner-a10.c b/hw/arm/allwinner-a10.c
index b7ca795..b0ea3f7 100644
--- a/hw/arm/allwinner-a10.c
+++ b/hw/arm/allwinner-a10.c
@@ -38,6 +38,7 @@
#define AW_A10_EHCI_BASE 0x01c14000
#define AW_A10_OHCI_BASE 0x01c14400
#define AW_A10_SATA_BASE 0x01c18000
+#define AW_A10_WDT_BASE 0x01c20c90
#define AW_A10_RTC_BASE 0x01c20d00
#define AW_A10_I2C0_BASE 0x01c2ac00
@@ -92,6 +93,8 @@ static void aw_a10_init(Object *obj)
object_initialize_child(obj, "mmc0", &s->mmc0, TYPE_AW_SDHOST_SUN4I);
object_initialize_child(obj, "rtc", &s->rtc, TYPE_AW_RTC_SUN4I);
+
+ object_initialize_child(obj, "wdt", &s->wdt, TYPE_AW_WDT_SUN4I);
}
static void aw_a10_realize(DeviceState *dev, Error **errp)
@@ -203,6 +206,10 @@ static void aw_a10_realize(DeviceState *dev, Error **errp)
sysbus_realize(SYS_BUS_DEVICE(&s->i2c0), &error_fatal);
sysbus_mmio_map(SYS_BUS_DEVICE(&s->i2c0), 0, AW_A10_I2C0_BASE);
sysbus_connect_irq(SYS_BUS_DEVICE(&s->i2c0), 0, qdev_get_gpio_in(dev, 7));
+
+ /* WDT */
+ sysbus_realize(SYS_BUS_DEVICE(&s->wdt), &error_fatal);
+ sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->wdt), 0, AW_A10_WDT_BASE, 1);
}
static void aw_a10_class_init(ObjectClass *oc, void *data)
diff --git a/hw/arm/allwinner-h3.c b/hw/arm/allwinner-h3.c
index 69d0ad6..f05afdd 100644
--- a/hw/arm/allwinner-h3.c
+++ b/hw/arm/allwinner-h3.c
@@ -49,6 +49,7 @@ const hwaddr allwinner_h3_memmap[] = {
[AW_H3_DEV_OHCI3] = 0x01c1d400,
[AW_H3_DEV_CCU] = 0x01c20000,
[AW_H3_DEV_PIT] = 0x01c20c00,
+ [AW_H3_DEV_WDT] = 0x01c20ca0,
[AW_H3_DEV_UART0] = 0x01c28000,
[AW_H3_DEV_UART1] = 0x01c28400,
[AW_H3_DEV_UART2] = 0x01c28800,
@@ -234,6 +235,8 @@ static void allwinner_h3_init(Object *obj)
object_initialize_child(obj, "twi1", &s->i2c1, TYPE_AW_I2C_SUN6I);
object_initialize_child(obj, "twi2", &s->i2c2, TYPE_AW_I2C_SUN6I);
object_initialize_child(obj, "r_twi", &s->r_twi, TYPE_AW_I2C_SUN6I);
+
+ object_initialize_child(obj, "wdt", &s->wdt, TYPE_AW_WDT_SUN6I);
}
static void allwinner_h3_realize(DeviceState *dev, Error **errp)
@@ -453,6 +456,11 @@ static void allwinner_h3_realize(DeviceState *dev, Error **errp)
sysbus_connect_irq(SYS_BUS_DEVICE(&s->r_twi), 0,
qdev_get_gpio_in(DEVICE(&s->gic), AW_H3_GIC_SPI_R_TWI));
+ /* WDT */
+ sysbus_realize(SYS_BUS_DEVICE(&s->wdt), &error_fatal);
+ sysbus_mmio_map_overlap(SYS_BUS_DEVICE(&s->wdt), 0,
+ s->memmap[AW_H3_DEV_WDT], 1);
+
/* Unimplemented devices */
for (i = 0; i < ARRAY_SIZE(unimplemented); i++) {
create_unimplemented_device(unimplemented[i].device_name,
diff --git a/hw/arm/exynos4210.c b/hw/arm/exynos4210.c
index 6f2dda1..de39fb0 100644
--- a/hw/arm/exynos4210.c
+++ b/hw/arm/exynos4210.c
@@ -326,7 +326,7 @@ static int mapline_size(const int *mapline)
/*
* Initialize board IRQs.
- * These IRQs contain splitted Int/External Combiner and External Gic IRQs.
+ * These IRQs contain split Int/External Combiner and External Gic IRQs.
*/
static void exynos4210_init_board_irqs(Exynos4210State *s)
{
@@ -744,7 +744,7 @@ static void exynos4210_realize(DeviceState *socdev, Error **errp)
* - SDMA
* - ADMA2
*
- * As this part of the Exynos4210 is not publically available,
+ * As this part of the Exynos4210 is not publicly available,
* we used the "HS-MMC Controller S3C2416X RISC Microprocessor"
* public datasheet which is very similar (implementing
* MMC Specification Version 4.0 being the only difference noted)
diff --git a/hw/arm/fsl-imx6ul.c b/hw/arm/fsl-imx6ul.c
index d88d6cc..2189dcb 100644
--- a/hw/arm/fsl-imx6ul.c
+++ b/hw/arm/fsl-imx6ul.c
@@ -407,8 +407,24 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
/*
* Ethernet
+ *
+ * We must use two loops since phy_connected affects the other interface
+ * and we have to set all properties before calling sysbus_realize().
*/
for (i = 0; i < FSL_IMX6UL_NUM_ETHS; i++) {
+ object_property_set_bool(OBJECT(&s->eth[i]), "phy-connected",
+ s->phy_connected[i], &error_abort);
+ /*
+ * If the MDIO bus on this controller is not connected, assume the
+ * other controller provides support for it.
+ */
+ if (!s->phy_connected[i]) {
+ object_property_set_link(OBJECT(&s->eth[1 - i]), "phy-consumer",
+ OBJECT(&s->eth[i]), &error_abort);
+ }
+ }
+
+ for (i = 0; i < FSL_IMX6UL_NUM_ETHS; i++) {
static const hwaddr FSL_IMX6UL_ENETn_ADDR[FSL_IMX6UL_NUM_ETHS] = {
FSL_IMX6UL_ENET1_ADDR,
FSL_IMX6UL_ENET2_ADDR,
@@ -620,6 +636,10 @@ static void fsl_imx6ul_realize(DeviceState *dev, Error **errp)
static Property fsl_imx6ul_properties[] = {
DEFINE_PROP_UINT32("fec1-phy-num", FslIMX6ULState, phy_num[0], 0),
DEFINE_PROP_UINT32("fec2-phy-num", FslIMX6ULState, phy_num[1], 1),
+ DEFINE_PROP_BOOL("fec1-phy-connected", FslIMX6ULState, phy_connected[0],
+ true),
+ DEFINE_PROP_BOOL("fec2-phy-connected", FslIMX6ULState, phy_connected[1],
+ true),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/arm/fsl-imx7.c b/hw/arm/fsl-imx7.c
index afc7480..9e41d4b 100644
--- a/hw/arm/fsl-imx7.c
+++ b/hw/arm/fsl-imx7.c
@@ -395,8 +395,24 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
/*
* Ethernet
+ *
+ * We must use two loops since phy_connected affects the other interface
+ * and we have to set all properties before calling sysbus_realize().
*/
for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) {
+ object_property_set_bool(OBJECT(&s->eth[i]), "phy-connected",
+ s->phy_connected[i], &error_abort);
+ /*
+ * If the MDIO bus on this controller is not connected, assume the
+ * other controller provides support for it.
+ */
+ if (!s->phy_connected[i]) {
+ object_property_set_link(OBJECT(&s->eth[1 - i]), "phy-consumer",
+ OBJECT(&s->eth[i]), &error_abort);
+ }
+ }
+
+ for (i = 0; i < FSL_IMX7_NUM_ETHS; i++) {
static const hwaddr FSL_IMX7_ENETn_ADDR[FSL_IMX7_NUM_ETHS] = {
FSL_IMX7_ENET1_ADDR,
FSL_IMX7_ENET2_ADDR,
@@ -601,6 +617,10 @@ static void fsl_imx7_realize(DeviceState *dev, Error **errp)
static Property fsl_imx7_properties[] = {
DEFINE_PROP_UINT32("fec1-phy-num", FslIMX7State, phy_num[0], 0),
DEFINE_PROP_UINT32("fec2-phy-num", FslIMX7State, phy_num[1], 1),
+ DEFINE_PROP_BOOL("fec1-phy-connected", FslIMX7State, phy_connected[0],
+ true),
+ DEFINE_PROP_BOOL("fec2-phy-connected", FslIMX7State, phy_connected[1],
+ true),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/arm/mcimx6ul-evk.c b/hw/arm/mcimx6ul-evk.c
index d83c3c3..3ac1e2e 100644
--- a/hw/arm/mcimx6ul-evk.c
+++ b/hw/arm/mcimx6ul-evk.c
@@ -41,6 +41,8 @@ static void mcimx6ul_evk_init(MachineState *machine)
object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
object_property_set_uint(OBJECT(s), "fec1-phy-num", 2, &error_fatal);
object_property_set_uint(OBJECT(s), "fec2-phy-num", 1, &error_fatal);
+ object_property_set_bool(OBJECT(s), "fec1-phy-connected", false,
+ &error_fatal);
qdev_realize(DEVICE(s), NULL, &error_fatal);
memory_region_add_subregion(get_system_memory(), FSL_IMX6UL_MMDC_ADDR,
diff --git a/hw/arm/mcimx7d-sabre.c b/hw/arm/mcimx7d-sabre.c
index 6182b15..d177812 100644
--- a/hw/arm/mcimx7d-sabre.c
+++ b/hw/arm/mcimx7d-sabre.c
@@ -41,6 +41,8 @@ static void mcimx7d_sabre_init(MachineState *machine)
s = FSL_IMX7(object_new(TYPE_FSL_IMX7));
object_property_add_child(OBJECT(machine), "soc", OBJECT(s));
+ object_property_set_bool(OBJECT(s), "fec2-phy-connected", false,
+ &error_fatal);
qdev_realize(DEVICE(s), NULL, &error_fatal);
memory_region_add_subregion(get_system_memory(), FSL_IMX7_MMDC_ADDR,
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index c9010b2..58f3d30 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -100,7 +100,7 @@
#define MP_LCD_SPI_CMD 0x00104011
#define MP_LCD_SPI_INVALID 0x00000000
-/* Commmands */
+/* Commands */
#define MP_LCD_INST_SETPAGE0 0xB0
/* ... */
#define MP_LCD_INST_SETPAGE7 0xB7
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
index 559c066..d543815 100644
--- a/hw/arm/omap1.c
+++ b/hw/arm/omap1.c
@@ -4057,7 +4057,7 @@ struct omap_mpu_state_s *omap310_mpu_init(MemoryRegion *dram,
s->led[1] = omap_lpg_init(system_memory,
0xfffbd800, omap_findclk(s, "clk32-kHz"));
- /* Register mappings not currenlty implemented:
+ /* Register mappings not currently implemented:
* MCSI2 Comm fffb2000 - fffb27ff (not mapped on OMAP310)
* MCSI1 Bluetooth fffb2800 - fffb2fff (not mapped on OMAP310)
* USB W2FC fffb4000 - fffb47ff
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
index 366d6af..d5a2ae7 100644
--- a/hw/arm/omap2.c
+++ b/hw/arm/omap2.c
@@ -2523,7 +2523,7 @@ struct omap_mpu_state_s *omap2420_mpu_init(MemoryRegion *sdram,
omap_findclk(s, "func_96m_clk"),
omap_findclk(s, "core_l4_iclk"));
- /* All register mappings (includin those not currenlty implemented):
+ /* All register mappings (including those not currently implemented):
* SystemControlMod 48000000 - 48000fff
* SystemControlL4 48001000 - 48001fff
* 32kHz Timer Mod 48004000 - 48004fff
diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index 4156111..4af0de8 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -694,7 +694,7 @@ static void build_append_gicr(GArray *table_data, uint64_t base, uint32_t size)
build_append_int_noprefix(table_data, 0xE, 1); /* Type */
build_append_int_noprefix(table_data, 16, 1); /* Length */
build_append_int_noprefix(table_data, 0, 2); /* Reserved */
- /* Discovery Range Base Addres */
+ /* Discovery Range Base Address */
build_append_int_noprefix(table_data, base, 8);
build_append_int_noprefix(table_data, size, 4); /* Discovery Range Length */
}
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index ac626b3..a89d699 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -204,7 +204,9 @@ static const int a15irqmap[] = {
};
static const char *valid_cpus[] = {
+#ifdef CONFIG_TCG
ARM_CPU_TYPE_NAME("cortex-a7"),
+#endif
ARM_CPU_TYPE_NAME("cortex-a15"),
ARM_CPU_TYPE_NAME("cortex-a35"),
ARM_CPU_TYPE_NAME("cortex-a53"),
@@ -2052,7 +2054,7 @@ static void machvirt_init(MachineState *machine)
int pa_bits;
/*
- * Instanciate a temporary CPU object to find out about what
+ * Instantiate a temporary CPU object to find out about what
* we are about to deal with. Once this is done, get rid of
* the object.
*/
@@ -3232,10 +3234,17 @@ static void machvirt_machine_init(void)
}
type_init(machvirt_machine_init);
+static void virt_machine_8_1_options(MachineClass *mc)
+{
+}
+DEFINE_VIRT_MACHINE_AS_LATEST(8, 1)
+
static void virt_machine_8_0_options(MachineClass *mc)
{
+ virt_machine_8_1_options(mc);
+ compat_props_add(mc->compat_props, hw_compat_8_0, hw_compat_8_0_len);
}
-DEFINE_VIRT_MACHINE_AS_LATEST(8, 0)
+DEFINE_VIRT_MACHINE(8, 0)
static void virt_machine_7_2_options(MachineClass *mc)
{
diff --git a/hw/arm/xlnx-versal-virt.c b/hw/arm/xlnx-versal-virt.c
index 37fc9b9..668a9d6 100644
--- a/hw/arm/xlnx-versal-virt.c
+++ b/hw/arm/xlnx-versal-virt.c
@@ -659,7 +659,7 @@ static void versal_virt_init(MachineState *machine)
fdt_add_clk_node(s, "/clk25", 25000000, s->phandle.clk_25Mhz);
/* Make the APU cpu address space visible to virtio and other
- * modules unaware of muliple address-spaces. */
+ * modules unaware of multiple address-spaces. */
memory_region_add_subregion_overlap(get_system_memory(),
0, &s->soc.fpd.apu.mr, 0);
diff --git a/hw/char/meson.build b/hw/char/meson.build
index e02c60d..0807e00 100644
--- a/hw/char/meson.build
+++ b/hw/char/meson.build
@@ -32,10 +32,9 @@ softmmu_ss.add(when: 'CONFIG_SIFIVE_UART', if_true: files('sifive_uart.c'))
softmmu_ss.add(when: 'CONFIG_SH_SCI', if_true: files('sh_serial.c'))
softmmu_ss.add(when: 'CONFIG_STM32F2XX_USART', if_true: files('stm32f2xx_usart.c'))
softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_MMUART', if_true: files('mchp_pfsoc_mmuart.c'))
+softmmu_ss.add(when: 'CONFIG_HTIF', if_true: files('riscv_htif.c'))
+softmmu_ss.add(when: 'CONFIG_GOLDFISH_TTY', if_true: files('goldfish_tty.c'))
-specific_ss.add(when: 'CONFIG_HTIF', if_true: files('riscv_htif.c'))
specific_ss.add(when: 'CONFIG_TERMINAL3270', if_true: files('terminal3270.c'))
specific_ss.add(when: 'CONFIG_VIRTIO', if_true: files('virtio-serial-bus.c'))
specific_ss.add(when: 'CONFIG_PSERIES', if_true: files('spapr_vty.c'))
-
-specific_ss.add(when: 'CONFIG_GOLDFISH_TTY', if_true: files('goldfish_tty.c'))
diff --git a/hw/core/machine.c b/hw/core/machine.c
index cd13b8b..2ce97a5 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -39,6 +39,9 @@
#include "hw/virtio/virtio.h"
#include "hw/virtio/virtio-pci.h"
+GlobalProperty hw_compat_8_0[] = {};
+const size_t hw_compat_8_0_len = G_N_ELEMENTS(hw_compat_8_0);
+
GlobalProperty hw_compat_7_2[] = {
{ "e1000e", "migrate-timadj", "off" },
{ "virtio-mem", "x-early-migration", "false" },
diff --git a/hw/core/meson.build b/hw/core/meson.build
index 7a4d02b..ae977c9 100644
--- a/hw/core/meson.build
+++ b/hw/core/meson.build
@@ -44,6 +44,7 @@ softmmu_ss.add(files(
'machine.c',
'nmi.c',
'null-machine.c',
+ 'numa.c',
'qdev-fw.c',
'qdev-properties-system.c',
'sysbus.c',
@@ -53,5 +54,4 @@ softmmu_ss.add(files(
specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: files(
'machine-qmp-cmds.c',
- 'numa.c',
))
diff --git a/hw/display/meson.build b/hw/display/meson.build
index 4191694..17165bd 100644
--- a/hw/display/meson.build
+++ b/hw/display/meson.build
@@ -36,7 +36,7 @@ softmmu_ss.add(when: 'CONFIG_CG3', if_true: files('cg3.c'))
softmmu_ss.add(when: 'CONFIG_MACFB', if_true: files('macfb.c'))
softmmu_ss.add(when: 'CONFIG_NEXTCUBE', if_true: files('next-fb.c'))
-specific_ss.add(when: 'CONFIG_VGA', if_true: files('vga.c'))
+softmmu_ss.add(when: 'CONFIG_VGA', if_true: files('vga.c'))
if (config_all_devices.has_key('CONFIG_VGA_CIRRUS') or
config_all_devices.has_key('CONFIG_VGA_PCI') or
diff --git a/hw/display/vga.c b/hw/display/vga.c
index 7a5fdff..37557c3 100644
--- a/hw/display/vga.c
+++ b/hw/display/vga.c
@@ -26,7 +26,9 @@
#include "qemu/units.h"
#include "sysemu/reset.h"
#include "qapi/error.h"
+#include "hw/core/cpu.h"
#include "hw/display/vga.h"
+#include "hw/i386/x86.h"
#include "hw/pci/pci.h"
#include "vga_int.h"
#include "vga_regs.h"
@@ -2244,11 +2246,8 @@ bool vga_common_init(VGACommonState *s, Object *obj, Error **errp)
* into a device attribute set by the machine/platform to remove
* all target endian dependencies from this file.
*/
-#if TARGET_BIG_ENDIAN
- s->default_endian_fb = true;
-#else
- s->default_endian_fb = false;
-#endif
+ s->default_endian_fb = target_words_bigendian();
+
vga_dirty_log_start(s);
return true;
@@ -2263,11 +2262,15 @@ static const MemoryRegionPortio vga_portio_list[] = {
PORTIO_END_OF_LIST(),
};
-static const MemoryRegionPortio vbe_portio_list[] = {
+static const MemoryRegionPortio vbe_portio_list_x86[] = {
{ 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
-# ifdef TARGET_I386
{ 1, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
-# endif
+ { 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
+ PORTIO_END_OF_LIST(),
+};
+
+static const MemoryRegionPortio vbe_portio_list_no_x86[] = {
+ { 0, 1, 2, .read = vbe_ioport_read_index, .write = vbe_ioport_write_index },
{ 2, 1, 2, .read = vbe_ioport_read_data, .write = vbe_ioport_write_data },
PORTIO_END_OF_LIST(),
};
@@ -2278,9 +2281,19 @@ MemoryRegion *vga_init_io(VGACommonState *s, Object *obj,
const MemoryRegionPortio **vbe_ports)
{
MemoryRegion *vga_mem;
+ MachineState *ms = MACHINE(qdev_get_machine());
+
+ /*
+ * We unfortunately need two VBE lists since non-x86 machines might
+ * not be able to do 16-bit accesses at unaligned addresses (0x1cf)
+ */
+ if (object_dynamic_cast(OBJECT(ms), TYPE_X86_MACHINE)) {
+ *vbe_ports = vbe_portio_list_x86;
+ } else {
+ *vbe_ports = vbe_portio_list_no_x86;
+ }
*vga_ports = vga_portio_list;
- *vbe_ports = vbe_portio_list;
vga_mem = g_malloc(sizeof(*vga_mem));
memory_region_init_io(vga_mem, obj, &vga_mem_ops, s,
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 1489abf..615e1d3 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -116,6 +116,9 @@
{ "qemu64-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },\
{ "athlon-" TYPE_X86_CPU, "model-id", "QEMU Virtual CPU version " v, },
+GlobalProperty pc_compat_8_0[] = {};
+const size_t pc_compat_8_0_len = G_N_ELEMENTS(pc_compat_8_0);
+
GlobalProperty pc_compat_7_2[] = {
{ "ICH9-LPC", "noreboot", "true" },
};
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 30eedd6..21591da 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -454,21 +454,31 @@ static void pc_i440fx_machine_options(MachineClass *m)
machine_class_allow_dynamic_sysbus_dev(m, TYPE_VMBUS_BRIDGE);
}
-static void pc_i440fx_8_0_machine_options(MachineClass *m)
+static void pc_i440fx_8_1_machine_options(MachineClass *m)
{
pc_i440fx_machine_options(m);
m->alias = "pc";
m->is_default = true;
}
+DEFINE_I440FX_MACHINE(v8_1, "pc-i440fx-8.1", NULL,
+ pc_i440fx_8_1_machine_options);
+
+static void pc_i440fx_8_0_machine_options(MachineClass *m)
+{
+ pc_i440fx_8_1_machine_options(m);
+ m->alias = NULL;
+ m->is_default = false;
+ compat_props_add(m->compat_props, hw_compat_8_0, hw_compat_8_0_len);
+ compat_props_add(m->compat_props, pc_compat_8_0, pc_compat_8_0_len);
+}
+
DEFINE_I440FX_MACHINE(v8_0, "pc-i440fx-8.0", NULL,
pc_i440fx_8_0_machine_options);
static void pc_i440fx_7_2_machine_options(MachineClass *m)
{
pc_i440fx_8_0_machine_options(m);
- m->alias = NULL;
- m->is_default = false;
compat_props_add(m->compat_props, hw_compat_7_2, hw_compat_7_2_len);
compat_props_add(m->compat_props, pc_compat_7_2, pc_compat_7_2_len);
}
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 797ba34..f02919d 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -373,19 +373,29 @@ static void pc_q35_machine_options(MachineClass *m)
m->max_cpus = 288;
}
-static void pc_q35_8_0_machine_options(MachineClass *m)
+static void pc_q35_8_1_machine_options(MachineClass *m)
{
pc_q35_machine_options(m);
m->alias = "q35";
}
+DEFINE_Q35_MACHINE(v8_1, "pc-q35-8.1", NULL,
+ pc_q35_8_1_machine_options);
+
+static void pc_q35_8_0_machine_options(MachineClass *m)
+{
+ pc_q35_8_1_machine_options(m);
+ m->alias = NULL;
+ compat_props_add(m->compat_props, hw_compat_8_0, hw_compat_8_0_len);
+ compat_props_add(m->compat_props, pc_compat_8_0, pc_compat_8_0_len);
+}
+
DEFINE_Q35_MACHINE(v8_0, "pc-q35-8.0", NULL,
pc_q35_8_0_machine_options);
static void pc_q35_7_2_machine_options(MachineClass *m)
{
pc_q35_8_0_machine_options(m);
- m->alias = NULL;
compat_props_add(m->compat_props, hw_compat_7_2, hw_compat_7_2_len);
compat_props_add(m->compat_props, pc_compat_7_2, pc_compat_7_2_len);
}
diff --git a/hw/m68k/virt.c b/hw/m68k/virt.c
index 754b9bd..731205b 100644
--- a/hw/m68k/virt.c
+++ b/hw/m68k/virt.c
@@ -347,10 +347,17 @@ type_init(virt_machine_register_types)
} \
type_init(machvirt_machine_##major##_##minor##_init);
+static void virt_machine_8_1_options(MachineClass *mc)
+{
+}
+DEFINE_VIRT_MACHINE(8, 1, true)
+
static void virt_machine_8_0_options(MachineClass *mc)
{
+ virt_machine_8_1_options(mc);
+ compat_props_add(mc->compat_props, hw_compat_8_0, hw_compat_8_0_len);
}
-DEFINE_VIRT_MACHINE(8, 0, true)
+DEFINE_VIRT_MACHINE(8, 0, false)
static void virt_machine_7_2_options(MachineClass *mc)
{
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index c862d96..5d1f1f1 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -282,11 +282,19 @@ static uint32_t imx_phy_read(IMXFECState *s, int reg)
uint32_t val;
uint32_t phy = reg / 32;
- if (phy != s->phy_num) {
- trace_imx_phy_read_num(phy, s->phy_num);
+ if (!s->phy_connected) {
return 0xffff;
}
+ if (phy != s->phy_num) {
+ if (s->phy_consumer && phy == s->phy_consumer->phy_num) {
+ s = s->phy_consumer;
+ } else {
+ trace_imx_phy_read_num(phy, s->phy_num);
+ return 0xffff;
+ }
+ }
+
reg %= 32;
switch (reg) {
@@ -343,11 +351,19 @@ static void imx_phy_write(IMXFECState *s, int reg, uint32_t val)
{
uint32_t phy = reg / 32;
- if (phy != s->phy_num) {
- trace_imx_phy_write_num(phy, s->phy_num);
+ if (!s->phy_connected) {
return;
}
+ if (phy != s->phy_num) {
+ if (s->phy_consumer && phy == s->phy_consumer->phy_num) {
+ s = s->phy_consumer;
+ } else {
+ trace_imx_phy_write_num(phy, s->phy_num);
+ return;
+ }
+ }
+
reg %= 32;
trace_imx_phy_write(val, phy, reg);
@@ -1327,6 +1343,9 @@ static Property imx_eth_properties[] = {
DEFINE_NIC_PROPERTIES(IMXFECState, conf),
DEFINE_PROP_UINT32("tx-ring-num", IMXFECState, tx_ring_num, 1),
DEFINE_PROP_UINT32("phy-num", IMXFECState, phy_num, 0),
+ DEFINE_PROP_BOOL("phy-connected", IMXFECState, phy_connected, true),
+ DEFINE_PROP_LINK("phy-consumer", IMXFECState, phy_consumer, TYPE_IMX_FEC,
+ IMXFECState *),
DEFINE_PROP_END_OF_LIST(),
};
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index 4921198..ddc9c7b 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -4735,14 +4735,25 @@ static void spapr_machine_latest_class_options(MachineClass *mc)
type_init(spapr_machine_register_##suffix)
/*
+ * pseries-8.1
+ */
+static void spapr_machine_8_1_class_options(MachineClass *mc)
+{
+ /* Defaults for the latest behaviour inherited from the base class */
+}
+
+DEFINE_SPAPR_MACHINE(8_1, "8.1", true);
+
+/*
* pseries-8.0
*/
static void spapr_machine_8_0_class_options(MachineClass *mc)
{
- /* Defaults for the latest behaviour inherited from the base class */
+ spapr_machine_8_1_class_options(mc);
+ compat_props_add(mc->compat_props, hw_compat_8_0, hw_compat_8_0_len);
}
-DEFINE_SPAPR_MACHINE(8_0, "8.0", true);
+DEFINE_SPAPR_MACHINE(8_0, "8.0", false);
/*
* pseries-7.2
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 3f664ea..7df2158 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -33,6 +33,7 @@
#include "sysemu/cpus.h"
#include "sysemu/hw_accel.h"
#include "sysemu/runstate.h"
+#include "sysemu/qtest.h"
#include "kvm_ppc.h"
#include "hw/ppc/spapr.h"
@@ -548,6 +549,32 @@ uint64_t qtest_rtas_call(char *cmd, uint32_t nargs, uint64_t args,
return H_PARAMETER;
}
+static bool spapr_qtest_callback(CharBackend *chr, gchar **words)
+{
+ if (strcmp(words[0], "rtas") == 0) {
+ uint64_t res, args, ret;
+ unsigned long nargs, nret;
+ int rc;
+
+ rc = qemu_strtoul(words[2], NULL, 0, &nargs);
+ g_assert(rc == 0);
+ rc = qemu_strtou64(words[3], NULL, 0, &args);
+ g_assert(rc == 0);
+ rc = qemu_strtoul(words[4], NULL, 0, &nret);
+ g_assert(rc == 0);
+ rc = qemu_strtou64(words[5], NULL, 0, &ret);
+ g_assert(rc == 0);
+ res = qtest_rtas_call(words[1], nargs, args, nret, ret);
+
+ qtest_send_prefix(chr);
+ qtest_sendf(chr, "OK %"PRIu64"\n", res);
+
+ return true;
+ }
+
+ return false;
+}
+
void spapr_rtas_register(int token, const char *name, spapr_rtas_fn fn)
{
assert((token >= RTAS_TOKEN_BASE) && (token < RTAS_TOKEN_MAX));
@@ -630,6 +657,8 @@ static void core_rtas_register_types(void)
rtas_ibm_nmi_register);
spapr_rtas_register(RTAS_IBM_NMI_INTERLOCK, "ibm,nmi-interlock",
rtas_ibm_nmi_interlock);
+
+ qtest_set_command_cb(spapr_qtest_callback);
}
type_init(core_rtas_register_types)
diff --git a/hw/s390x/s390-virtio-ccw.c b/hw/s390x/s390-virtio-ccw.c
index 503f212..e6f2c62 100644
--- a/hw/s390x/s390-virtio-ccw.c
+++ b/hw/s390x/s390-virtio-ccw.c
@@ -826,14 +826,26 @@ bool css_migration_enabled(void)
} \
type_init(ccw_machine_register_##suffix)
+static void ccw_machine_8_1_instance_options(MachineState *machine)
+{
+}
+
+static void ccw_machine_8_1_class_options(MachineClass *mc)
+{
+}
+DEFINE_CCW_MACHINE(8_1, "8.1", true);
+
static void ccw_machine_8_0_instance_options(MachineState *machine)
{
+ ccw_machine_8_1_instance_options(machine);
}
static void ccw_machine_8_0_class_options(MachineClass *mc)
{
+ ccw_machine_8_1_class_options(mc);
+ compat_props_add(mc->compat_props, hw_compat_8_0, hw_compat_8_0_len);
}
-DEFINE_CCW_MACHINE(8_0, "8.0", true);
+DEFINE_CCW_MACHINE(8_0, "8.0", false);
static void ccw_machine_7_2_instance_options(MachineState *machine)
{
diff --git a/hw/timer/exynos4210_mct.c b/hw/timer/exynos4210_mct.c
index c17b247..446bbd2 100644
--- a/hw/timer/exynos4210_mct.c
+++ b/hw/timer/exynos4210_mct.c
@@ -480,11 +480,14 @@ static int32_t exynos4210_gcomp_find(Exynos4210MCTState *s)
res = min_comp_i;
}
- DPRINTF("found comparator %d: comp 0x%llx distance 0x%llx, gfrc 0x%llx\n",
- res,
- s->g_timer.reg.comp[res],
- distance_min,
- gfrc);
+ if (res >= 0) {
+ DPRINTF("found comparator %d: "
+ "comp 0x%llx distance 0x%llx, gfrc 0x%llx\n",
+ res,
+ s->g_timer.reg.comp[res],
+ distance_min,
+ gfrc);
+ }
return res;
}
diff --git a/hw/timer/imx_epit.c b/hw/timer/imx_epit.c
index 3a86978..640e439 100644
--- a/hw/timer/imx_epit.c
+++ b/hw/timer/imx_epit.c
@@ -179,7 +179,7 @@ static void imx_epit_update_compare_timer(IMXEPITState *s)
* the compare value. Otherwise it may fire at most once in the
* current round.
*/
- bool is_oneshot = (limit >= s->cmp);
+ is_oneshot = (limit < s->cmp);
if (counter >= s->cmp) {
/* The compare timer fires in the current round. */
counter -= s->cmp;
diff --git a/hw/watchdog/Kconfig b/hw/watchdog/Kconfig
index 66e1d02..861fd00 100644
--- a/hw/watchdog/Kconfig
+++ b/hw/watchdog/Kconfig
@@ -20,3 +20,7 @@ config WDT_IMX2
config WDT_SBSA
bool
+
+config ALLWINNER_WDT
+ bool
+ select PTIMER
diff --git a/hw/watchdog/allwinner-wdt.c b/hw/watchdog/allwinner-wdt.c
new file mode 100644
index 0000000..6205765
--- /dev/null
+++ b/hw/watchdog/allwinner-wdt.c
@@ -0,0 +1,416 @@
+/*
+ * Allwinner Watchdog emulation
+ *
+ * Copyright (C) 2023 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
+ *
+ * This file is derived from Allwinner RTC,
+ * by Niek Linnenbank.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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 "qemu/units.h"
+#include "qemu/module.h"
+#include "trace.h"
+#include "hw/sysbus.h"
+#include "hw/registerfields.h"
+#include "hw/watchdog/allwinner-wdt.h"
+#include "sysemu/watchdog.h"
+#include "migration/vmstate.h"
+
+/* WDT registers */
+enum {
+ REG_IRQ_EN = 0, /* Watchdog interrupt enable */
+ REG_IRQ_STA, /* Watchdog interrupt status */
+ REG_CTRL, /* Watchdog control register */
+ REG_CFG, /* Watchdog configuration register */
+ REG_MODE, /* Watchdog mode register */
+};
+
+/* Universal WDT register flags */
+#define WDT_RESTART_MASK (1 << 0)
+#define WDT_EN_MASK (1 << 0)
+
+/* sun4i specific WDT register flags */
+#define RST_EN_SUN4I_MASK (1 << 1)
+#define INTV_VALUE_SUN4I_SHIFT (3)
+#define INTV_VALUE_SUN4I_MASK (0xfu << INTV_VALUE_SUN4I_SHIFT)
+
+/* sun6i specific WDT register flags */
+#define RST_EN_SUN6I_MASK (1 << 0)
+#define KEY_FIELD_SUN6I_SHIFT (1)
+#define KEY_FIELD_SUN6I_MASK (0xfffu << KEY_FIELD_SUN6I_SHIFT)
+#define KEY_FIELD_SUN6I (0xA57u)
+#define INTV_VALUE_SUN6I_SHIFT (4)
+#define INTV_VALUE_SUN6I_MASK (0xfu << INTV_VALUE_SUN6I_SHIFT)
+
+/* Map of INTV_VALUE to 0.5s units. */
+static const uint8_t allwinner_wdt_count_map[] = {
+ 1,
+ 2,
+ 4,
+ 6,
+ 8,
+ 10,
+ 12,
+ 16,
+ 20,
+ 24,
+ 28,
+ 32
+};
+
+/* WDT sun4i register map (offset to name) */
+const uint8_t allwinner_wdt_sun4i_regmap[] = {
+ [0x0000] = REG_CTRL,
+ [0x0004] = REG_MODE,
+};
+
+/* WDT sun6i register map (offset to name) */
+const uint8_t allwinner_wdt_sun6i_regmap[] = {
+ [0x0000] = REG_IRQ_EN,
+ [0x0004] = REG_IRQ_STA,
+ [0x0010] = REG_CTRL,
+ [0x0014] = REG_CFG,
+ [0x0018] = REG_MODE,
+};
+
+static bool allwinner_wdt_sun4i_read(AwWdtState *s, uint32_t offset)
+{
+ /* no sun4i specific registers currently implemented */
+ return false;
+}
+
+static bool allwinner_wdt_sun4i_write(AwWdtState *s, uint32_t offset,
+ uint32_t data)
+{
+ /* no sun4i specific registers currently implemented */
+ return false;
+}
+
+static bool allwinner_wdt_sun4i_can_reset_system(AwWdtState *s)
+{
+ if (s->regs[REG_MODE] & RST_EN_SUN4I_MASK) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static bool allwinner_wdt_sun4i_is_key_valid(AwWdtState *s, uint32_t val)
+{
+ /* sun4i has no key */
+ return true;
+}
+
+static uint8_t allwinner_wdt_sun4i_get_intv_value(AwWdtState *s)
+{
+ return ((s->regs[REG_MODE] & INTV_VALUE_SUN4I_MASK) >>
+ INTV_VALUE_SUN4I_SHIFT);
+}
+
+static bool allwinner_wdt_sun6i_read(AwWdtState *s, uint32_t offset)
+{
+ const AwWdtClass *c = AW_WDT_GET_CLASS(s);
+
+ switch (c->regmap[offset]) {
+ case REG_IRQ_EN:
+ case REG_IRQ_STA:
+ case REG_CFG:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+static bool allwinner_wdt_sun6i_write(AwWdtState *s, uint32_t offset,
+ uint32_t data)
+{
+ const AwWdtClass *c = AW_WDT_GET_CLASS(s);
+
+ switch (c->regmap[offset]) {
+ case REG_IRQ_EN:
+ case REG_IRQ_STA:
+ case REG_CFG:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+static bool allwinner_wdt_sun6i_can_reset_system(AwWdtState *s)
+{
+ if (s->regs[REG_CFG] & RST_EN_SUN6I_MASK) {
+ return true;
+ } else {
+ return false;
+ }
+}
+
+static bool allwinner_wdt_sun6i_is_key_valid(AwWdtState *s, uint32_t val)
+{
+ uint16_t key = (val & KEY_FIELD_SUN6I_MASK) >> KEY_FIELD_SUN6I_SHIFT;
+ return (key == KEY_FIELD_SUN6I);
+}
+
+static uint8_t allwinner_wdt_sun6i_get_intv_value(AwWdtState *s)
+{
+ return ((s->regs[REG_MODE] & INTV_VALUE_SUN6I_MASK) >>
+ INTV_VALUE_SUN6I_SHIFT);
+}
+
+static void allwinner_wdt_update_timer(AwWdtState *s)
+{
+ const AwWdtClass *c = AW_WDT_GET_CLASS(s);
+ uint8_t count = c->get_intv_value(s);
+
+ ptimer_transaction_begin(s->timer);
+ ptimer_stop(s->timer);
+
+ /* Use map to convert. */
+ if (count < sizeof(allwinner_wdt_count_map)) {
+ ptimer_set_count(s->timer, allwinner_wdt_count_map[count]);
+ } else {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: incorrect INTV_VALUE 0x%02x\n",
+ __func__, count);
+ }
+
+ ptimer_run(s->timer, 1);
+ ptimer_transaction_commit(s->timer);
+
+ trace_allwinner_wdt_update_timer(count);
+}
+
+static uint64_t allwinner_wdt_read(void *opaque, hwaddr offset,
+ unsigned size)
+{
+ AwWdtState *s = AW_WDT(opaque);
+ const AwWdtClass *c = AW_WDT_GET_CLASS(s);
+ uint64_t r;
+
+ if (offset >= c->regmap_size) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
+ __func__, (uint32_t)offset);
+ return 0;
+ }
+
+ switch (c->regmap[offset]) {
+ case REG_CTRL:
+ case REG_MODE:
+ r = s->regs[c->regmap[offset]];
+ break;
+ default:
+ if (!c->read(s, offset)) {
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented register 0x%04x\n",
+ __func__, (uint32_t)offset);
+ return 0;
+ }
+ r = s->regs[c->regmap[offset]];
+ break;
+ }
+
+ trace_allwinner_wdt_read(offset, r, size);
+
+ return r;
+}
+
+static void allwinner_wdt_write(void *opaque, hwaddr offset,
+ uint64_t val, unsigned size)
+{
+ AwWdtState *s = AW_WDT(opaque);
+ const AwWdtClass *c = AW_WDT_GET_CLASS(s);
+ uint32_t old_val;
+
+ if (offset >= c->regmap_size) {
+ qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset 0x%04x\n",
+ __func__, (uint32_t)offset);
+ return;
+ }
+
+ trace_allwinner_wdt_write(offset, val, size);
+
+ switch (c->regmap[offset]) {
+ case REG_CTRL:
+ if (c->is_key_valid(s, val)) {
+ if (val & WDT_RESTART_MASK) {
+ /* Kick timer */
+ allwinner_wdt_update_timer(s);
+ }
+ }
+ break;
+ case REG_MODE:
+ old_val = s->regs[REG_MODE];
+ s->regs[REG_MODE] = (uint32_t)val;
+
+ /* Check for rising edge on WDOG_MODE_EN */
+ if ((s->regs[REG_MODE] & ~old_val) & WDT_EN_MASK) {
+ allwinner_wdt_update_timer(s);
+ }
+ break;
+ default:
+ if (!c->write(s, offset, val)) {
+ qemu_log_mask(LOG_UNIMP, "%s: unimplemented register 0x%04x\n",
+ __func__, (uint32_t)offset);
+ }
+ s->regs[c->regmap[offset]] = (uint32_t)val;
+ break;
+ }
+}
+
+static const MemoryRegionOps allwinner_wdt_ops = {
+ .read = allwinner_wdt_read,
+ .write = allwinner_wdt_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ .min_access_size = 4,
+ .max_access_size = 4,
+ },
+ .impl.min_access_size = 4,
+};
+
+static void allwinner_wdt_expired(void *opaque)
+{
+ AwWdtState *s = AW_WDT(opaque);
+ const AwWdtClass *c = AW_WDT_GET_CLASS(s);
+
+ bool enabled = s->regs[REG_MODE] & WDT_EN_MASK;
+ bool reset_enabled = c->can_reset_system(s);
+
+ trace_allwinner_wdt_expired(enabled, reset_enabled);
+
+ /* Perform watchdog action if watchdog is enabled and can trigger reset */
+ if (enabled && reset_enabled) {
+ watchdog_perform_action();
+ }
+}
+
+static void allwinner_wdt_reset_enter(Object *obj, ResetType type)
+{
+ AwWdtState *s = AW_WDT(obj);
+
+ trace_allwinner_wdt_reset_enter();
+
+ /* Clear registers */
+ memset(s->regs, 0, sizeof(s->regs));
+}
+
+static const VMStateDescription allwinner_wdt_vmstate = {
+ .name = "allwinner-wdt",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (VMStateField[]) {
+ VMSTATE_PTIMER(timer, AwWdtState),
+ VMSTATE_UINT32_ARRAY(regs, AwWdtState, AW_WDT_REGS_NUM),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+static void allwinner_wdt_init(Object *obj)
+{
+ SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
+ AwWdtState *s = AW_WDT(obj);
+ const AwWdtClass *c = AW_WDT_GET_CLASS(s);
+
+ /* Memory mapping */
+ memory_region_init_io(&s->iomem, OBJECT(s), &allwinner_wdt_ops, s,
+ TYPE_AW_WDT, c->regmap_size * 4);
+ sysbus_init_mmio(sbd, &s->iomem);
+}
+
+static void allwinner_wdt_realize(DeviceState *dev, Error **errp)
+{
+ AwWdtState *s = AW_WDT(dev);
+
+ s->timer = ptimer_init(allwinner_wdt_expired, s,
+ PTIMER_POLICY_NO_IMMEDIATE_TRIGGER |
+ PTIMER_POLICY_NO_IMMEDIATE_RELOAD |
+ PTIMER_POLICY_NO_COUNTER_ROUND_DOWN);
+
+ ptimer_transaction_begin(s->timer);
+ /* Set to 2Hz (0.5s period); other periods are multiples of 0.5s. */
+ ptimer_set_freq(s->timer, 2);
+ ptimer_set_limit(s->timer, 0xff, 1);
+ ptimer_transaction_commit(s->timer);
+}
+
+static void allwinner_wdt_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+ rc->phases.enter = allwinner_wdt_reset_enter;
+ dc->realize = allwinner_wdt_realize;
+ dc->vmsd = &allwinner_wdt_vmstate;
+}
+
+static void allwinner_wdt_sun4i_class_init(ObjectClass *klass, void *data)
+{
+ AwWdtClass *awc = AW_WDT_CLASS(klass);
+
+ awc->regmap = allwinner_wdt_sun4i_regmap;
+ awc->regmap_size = sizeof(allwinner_wdt_sun4i_regmap);
+ awc->read = allwinner_wdt_sun4i_read;
+ awc->write = allwinner_wdt_sun4i_write;
+ awc->can_reset_system = allwinner_wdt_sun4i_can_reset_system;
+ awc->is_key_valid = allwinner_wdt_sun4i_is_key_valid;
+ awc->get_intv_value = allwinner_wdt_sun4i_get_intv_value;
+}
+
+static void allwinner_wdt_sun6i_class_init(ObjectClass *klass, void *data)
+{
+ AwWdtClass *awc = AW_WDT_CLASS(klass);
+
+ awc->regmap = allwinner_wdt_sun6i_regmap;
+ awc->regmap_size = sizeof(allwinner_wdt_sun6i_regmap);
+ awc->read = allwinner_wdt_sun6i_read;
+ awc->write = allwinner_wdt_sun6i_write;
+ awc->can_reset_system = allwinner_wdt_sun6i_can_reset_system;
+ awc->is_key_valid = allwinner_wdt_sun6i_is_key_valid;
+ awc->get_intv_value = allwinner_wdt_sun6i_get_intv_value;
+}
+
+static const TypeInfo allwinner_wdt_info = {
+ .name = TYPE_AW_WDT,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_init = allwinner_wdt_init,
+ .instance_size = sizeof(AwWdtState),
+ .class_init = allwinner_wdt_class_init,
+ .class_size = sizeof(AwWdtClass),
+ .abstract = true,
+};
+
+static const TypeInfo allwinner_wdt_sun4i_info = {
+ .name = TYPE_AW_WDT_SUN4I,
+ .parent = TYPE_AW_WDT,
+ .class_init = allwinner_wdt_sun4i_class_init,
+};
+
+static const TypeInfo allwinner_wdt_sun6i_info = {
+ .name = TYPE_AW_WDT_SUN6I,
+ .parent = TYPE_AW_WDT,
+ .class_init = allwinner_wdt_sun6i_class_init,
+};
+
+static void allwinner_wdt_register(void)
+{
+ type_register_static(&allwinner_wdt_info);
+ type_register_static(&allwinner_wdt_sun4i_info);
+ type_register_static(&allwinner_wdt_sun6i_info);
+}
+
+type_init(allwinner_wdt_register)
diff --git a/hw/watchdog/meson.build b/hw/watchdog/meson.build
index 8974b5c..5dcd4fb 100644
--- a/hw/watchdog/meson.build
+++ b/hw/watchdog/meson.build
@@ -1,4 +1,5 @@
softmmu_ss.add(files('watchdog.c'))
+softmmu_ss.add(when: 'CONFIG_ALLWINNER_WDT', if_true: files('allwinner-wdt.c'))
softmmu_ss.add(when: 'CONFIG_CMSDK_APB_WATCHDOG', if_true: files('cmsdk-apb-watchdog.c'))
softmmu_ss.add(when: 'CONFIG_WDT_IB6300ESB', if_true: files('wdt_i6300esb.c'))
softmmu_ss.add(when: 'CONFIG_WDT_IB700', if_true: files('wdt_ib700.c'))
diff --git a/hw/watchdog/trace-events b/hw/watchdog/trace-events
index 54371ae..2739570 100644
--- a/hw/watchdog/trace-events
+++ b/hw/watchdog/trace-events
@@ -1,5 +1,12 @@
# See docs/devel/tracing.rst for syntax documentation.
+# allwinner-wdt.c
+allwinner_wdt_read(uint64_t offset, uint64_t data, unsigned size) "Allwinner watchdog read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+allwinner_wdt_write(uint64_t offset, uint64_t data, unsigned size) "Allwinner watchdog write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
+allwinner_wdt_reset_enter(void) "Allwinner watchdog: reset"
+allwinner_wdt_update_timer(uint8_t count) "Allwinner watchdog: count %" PRIu8
+allwinner_wdt_expired(bool enabled, bool reset_enabled) "Allwinner watchdog: enabled %u reset_enabled %u"
+
# cmsdk-apb-watchdog.c
cmsdk_apb_watchdog_read(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
cmsdk_apb_watchdog_write(uint64_t offset, uint64_t data, unsigned size) "CMSDK APB watchdog write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u"
diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h
index 090922e..ad824fe 100644
--- a/include/exec/cpu-all.h
+++ b/include/exec/cpu-all.h
@@ -21,6 +21,7 @@
#include "exec/cpu-common.h"
#include "exec/memory.h"
+#include "exec/tswap.h"
#include "qemu/thread.h"
#include "hw/core/cpu.h"
#include "qemu/rcu.h"
@@ -44,69 +45,6 @@
#define BSWAP_NEEDED
#endif
-#ifdef BSWAP_NEEDED
-
-static inline uint16_t tswap16(uint16_t s)
-{
- return bswap16(s);
-}
-
-static inline uint32_t tswap32(uint32_t s)
-{
- return bswap32(s);
-}
-
-static inline uint64_t tswap64(uint64_t s)
-{
- return bswap64(s);
-}
-
-static inline void tswap16s(uint16_t *s)
-{
- *s = bswap16(*s);
-}
-
-static inline void tswap32s(uint32_t *s)
-{
- *s = bswap32(*s);
-}
-
-static inline void tswap64s(uint64_t *s)
-{
- *s = bswap64(*s);
-}
-
-#else
-
-static inline uint16_t tswap16(uint16_t s)
-{
- return s;
-}
-
-static inline uint32_t tswap32(uint32_t s)
-{
- return s;
-}
-
-static inline uint64_t tswap64(uint64_t s)
-{
- return s;
-}
-
-static inline void tswap16s(uint16_t *s)
-{
-}
-
-static inline void tswap32s(uint32_t *s)
-{
-}
-
-static inline void tswap64s(uint64_t *s)
-{
-}
-
-#endif
-
#if TARGET_LONG_SIZE == 4
#define tswapl(s) tswap32(s)
#define tswapls(s) tswap32s((uint32_t *)(s))
diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h
index 6feaa40..565c203 100644
--- a/include/exec/cpu-common.h
+++ b/include/exec/cpu-common.h
@@ -165,6 +165,6 @@ int cpu_memory_rw_debug(CPUState *cpu, vaddr addr,
/* vl.c */
extern int singlestep;
-void list_cpus(const char *optarg);
+void list_cpus(void);
#endif /* CPU_COMMON_H */
diff --git a/include/exec/tswap.h b/include/exec/tswap.h
new file mode 100644
index 0000000..68944a8
--- /dev/null
+++ b/include/exec/tswap.h
@@ -0,0 +1,72 @@
+/*
+ * Macros for swapping a value if the endianness is different
+ * between the target and the host.
+ *
+ * SPDX-License-Identifier: LGPL-2.1-or-later
+ */
+
+#ifndef TSWAP_H
+#define TSWAP_H
+
+#include "hw/core/cpu.h"
+#include "qemu/bswap.h"
+
+/*
+ * If we're in target-specific code, we can hard-code the swapping
+ * condition, otherwise we have to do (slower) run-time checks.
+ */
+#ifdef NEED_CPU_H
+#define target_needs_bswap() (HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN)
+#else
+#define target_needs_bswap() (target_words_bigendian() != HOST_BIG_ENDIAN)
+#endif
+
+static inline uint16_t tswap16(uint16_t s)
+{
+ if (target_needs_bswap()) {
+ return bswap16(s);
+ } else {
+ return s;
+ }
+}
+
+static inline uint32_t tswap32(uint32_t s)
+{
+ if (target_needs_bswap()) {
+ return bswap32(s);
+ } else {
+ return s;
+ }
+}
+
+static inline uint64_t tswap64(uint64_t s)
+{
+ if (target_needs_bswap()) {
+ return bswap64(s);
+ } else {
+ return s;
+ }
+}
+
+static inline void tswap16s(uint16_t *s)
+{
+ if (target_needs_bswap()) {
+ *s = bswap16(*s);
+ }
+}
+
+static inline void tswap32s(uint32_t *s)
+{
+ if (target_needs_bswap()) {
+ *s = bswap32(*s);
+ }
+}
+
+static inline void tswap64s(uint64_t *s)
+{
+ if (target_needs_bswap()) {
+ *s = bswap64(*s);
+ }
+}
+
+#endif /* TSWAP_H */
diff --git a/include/hw/arm/allwinner-a10.h b/include/hw/arm/allwinner-a10.h
index 095afb2..cd1465c 100644
--- a/include/hw/arm/allwinner-a10.h
+++ b/include/hw/arm/allwinner-a10.h
@@ -13,6 +13,7 @@
#include "hw/misc/allwinner-a10-ccm.h"
#include "hw/misc/allwinner-a10-dramc.h"
#include "hw/i2c/allwinner-i2c.h"
+#include "hw/watchdog/allwinner-wdt.h"
#include "sysemu/block-backend.h"
#include "target/arm/cpu.h"
@@ -41,6 +42,7 @@ struct AwA10State {
AwSdHostState mmc0;
AWI2CState i2c0;
AwRtcState rtc;
+ AwWdtState wdt;
MemoryRegion sram_a;
EHCISysBusState ehci[AW_A10_NUM_USB];
OHCISysBusState ohci[AW_A10_NUM_USB];
diff --git a/include/hw/arm/allwinner-h3.h b/include/hw/arm/allwinner-h3.h
index 59e0f82..f15d6d7 100644
--- a/include/hw/arm/allwinner-h3.h
+++ b/include/hw/arm/allwinner-h3.h
@@ -48,6 +48,7 @@
#include "hw/net/allwinner-sun8i-emac.h"
#include "hw/rtc/allwinner-rtc.h"
#include "hw/i2c/allwinner-i2c.h"
+#include "hw/watchdog/allwinner-wdt.h"
#include "target/arm/cpu.h"
#include "sysemu/block-backend.h"
@@ -96,7 +97,8 @@ enum {
AW_H3_DEV_RTC,
AW_H3_DEV_CPUCFG,
AW_H3_DEV_R_TWI,
- AW_H3_DEV_SDRAM
+ AW_H3_DEV_SDRAM,
+ AW_H3_DEV_WDT
};
/** Total number of CPU cores in the H3 SoC */
@@ -141,6 +143,7 @@ struct AwH3State {
AWI2CState r_twi;
AwSun8iEmacState emac;
AwRtcState rtc;
+ AwWdtState wdt;
GICState gic;
MemoryRegion sram_a1;
MemoryRegion sram_a2;
diff --git a/include/hw/arm/fsl-imx6ul.h b/include/hw/arm/fsl-imx6ul.h
index 1952cb9..9ee15ae 100644
--- a/include/hw/arm/fsl-imx6ul.h
+++ b/include/hw/arm/fsl-imx6ul.h
@@ -89,6 +89,7 @@ struct FslIMX6ULState {
MemoryRegion ocram_alias;
uint32_t phy_num[FSL_IMX6UL_NUM_ETHS];
+ bool phy_connected[FSL_IMX6UL_NUM_ETHS];
};
enum FslIMX6ULMemoryMap {
diff --git a/include/hw/arm/fsl-imx7.h b/include/hw/arm/fsl-imx7.h
index 355bd8e..54ea2f0 100644
--- a/include/hw/arm/fsl-imx7.h
+++ b/include/hw/arm/fsl-imx7.h
@@ -82,6 +82,7 @@ struct FslIMX7State {
ChipideaState usb[FSL_IMX7_NUM_USBS];
DesignwarePCIEHost pcie;
uint32_t phy_num[FSL_IMX7_NUM_ETHS];
+ bool phy_connected[FSL_IMX7_NUM_ETHS];
};
enum FslIMX7MemoryMap {
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 6fbbfd5..bf5fc9e 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -381,6 +381,9 @@ struct MachineState {
} \
type_init(machine_initfn##_register_types)
+extern GlobalProperty hw_compat_8_0[];
+extern const size_t hw_compat_8_0_len;
+
extern GlobalProperty hw_compat_7_2[];
extern const size_t hw_compat_7_2_len;
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 8206d54..eb668e9 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -195,6 +195,9 @@ void pc_madt_cpu_entry(int uid, const CPUArchIdList *apic_ids,
/* sgx.c */
void pc_machine_init_sgx_epc(PCMachineState *pcms);
+extern GlobalProperty pc_compat_8_0[];
+extern const size_t pc_compat_8_0_len;
+
extern GlobalProperty pc_compat_7_2[];
extern const size_t pc_compat_7_2_len;
diff --git a/include/hw/net/imx_fec.h b/include/hw/net/imx_fec.h
index e3a8755..2d13290 100644
--- a/include/hw/net/imx_fec.h
+++ b/include/hw/net/imx_fec.h
@@ -270,6 +270,8 @@ struct IMXFECState {
uint32_t phy_int;
uint32_t phy_int_mask;
uint32_t phy_num;
+ bool phy_connected;
+ struct IMXFECState *phy_consumer;
bool is_fec;
diff --git a/include/hw/watchdog/allwinner-wdt.h b/include/hw/watchdog/allwinner-wdt.h
new file mode 100644
index 0000000..7fe41e2
--- /dev/null
+++ b/include/hw/watchdog/allwinner-wdt.h
@@ -0,0 +1,123 @@
+/*
+ * Allwinner Watchdog emulation
+ *
+ * Copyright (C) 2023 Strahinja Jankovic <strahinja.p.jankovic@gmail.com>
+ *
+ * This file is derived from Allwinner RTC,
+ * by Niek Linnenbank.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that 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/>.
+ */
+
+#ifndef HW_WATCHDOG_ALLWINNER_WDT_H
+#define HW_WATCHDOG_ALLWINNER_WDT_H
+
+#include "qom/object.h"
+#include "hw/ptimer.h"
+#include "hw/sysbus.h"
+
+/*
+ * This is a model of the Allwinner watchdog.
+ * Since watchdog registers belong to the timer module (and are shared with the
+ * RTC module), the interrupt line from watchdog is not handled right now.
+ * In QEMU, we just wire up the watchdog reset to watchdog_perform_action(),
+ * at least for the moment.
+ */
+
+#define TYPE_AW_WDT "allwinner-wdt"
+
+/** Allwinner WDT sun4i family (A10, A12), also sun7i (A20) */
+#define TYPE_AW_WDT_SUN4I TYPE_AW_WDT "-sun4i"
+
+/** Allwinner WDT sun6i family and newer (A31, H2+, H3, etc) */
+#define TYPE_AW_WDT_SUN6I TYPE_AW_WDT "-sun6i"
+
+/** Number of WDT registers */
+#define AW_WDT_REGS_NUM (5)
+
+OBJECT_DECLARE_TYPE(AwWdtState, AwWdtClass, AW_WDT)
+
+/**
+ * Allwinner WDT object instance state.
+ */
+struct AwWdtState {
+ /*< private >*/
+ SysBusDevice parent_obj;
+
+ /*< public >*/
+ MemoryRegion iomem;
+ struct ptimer_state *timer;
+
+ uint32_t regs[AW_WDT_REGS_NUM];
+};
+
+/**
+ * Allwinner WDT class-level struct.
+ *
+ * This struct is filled by each sunxi device specific code
+ * such that the generic code can use this struct to support
+ * all devices.
+ */
+struct AwWdtClass {
+ /*< private >*/
+ SysBusDeviceClass parent_class;
+ /*< public >*/
+
+ /** Defines device specific register map */
+ const uint8_t *regmap;
+
+ /** Size of the regmap in bytes */
+ size_t regmap_size;
+
+ /**
+ * Read device specific register
+ *
+ * @offset: register offset to read
+ * @return true if register read successful, false otherwise
+ */
+ bool (*read)(AwWdtState *s, uint32_t offset);
+
+ /**
+ * Write device specific register
+ *
+ * @offset: register offset to write
+ * @data: value to set in register
+ * @return true if register write successful, false otherwise
+ */
+ bool (*write)(AwWdtState *s, uint32_t offset, uint32_t data);
+
+ /**
+ * Check if watchdog can generate system reset
+ *
+ * @return true if watchdog can generate system reset
+ */
+ bool (*can_reset_system)(AwWdtState *s);
+
+ /**
+ * Check if provided key is valid
+ *
+ * @value: value written to register
+ * @return true if key is valid, false otherwise
+ */
+ bool (*is_key_valid)(AwWdtState *s, uint32_t val);
+
+ /**
+ * Get current INTV_VALUE setting
+ *
+ * @return current INTV_VALUE (0-15)
+ */
+ uint8_t (*get_intv_value)(AwWdtState *s);
+};
+
+#endif /* HW_WATCHDOG_ALLWINNER_WDT_H */
diff --git a/include/sysemu/qtest.h b/include/sysemu/qtest.h
index 4c53537..85f05b0 100644
--- a/include/sysemu/qtest.h
+++ b/include/sysemu/qtest.h
@@ -14,6 +14,7 @@
#ifndef QTEST_H
#define QTEST_H
+#include "chardev/char.h"
extern bool qtest_allowed;
@@ -22,6 +23,9 @@ static inline bool qtest_enabled(void)
return qtest_allowed;
}
+void qtest_send_prefix(CharBackend *chr);
+void G_GNUC_PRINTF(2, 3) qtest_sendf(CharBackend *chr, const char *fmt, ...);
+void qtest_set_command_cb(bool (*pc_cb)(CharBackend *chr, gchar **words));
bool qtest_driver(void);
void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **errp);
diff --git a/qemu-options.hx b/qemu-options.hx
index 59bdf67..04c2591 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -3360,7 +3360,7 @@ DEF("chardev", HAS_ARG, QEMU_OPTION_chardev,
"-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]\n"
" [,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
"-chardev ringbuf,id=id[,size=size][,logfile=PATH][,logappend=on|off]\n"
- "-chardev file,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
+ "-chardev file,id=id,path=path[,input-path=input-file][,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
"-chardev pipe,id=id,path=path[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
#ifdef _WIN32
"-chardev console,id=id[,mux=on|off][,logfile=PATH][,logappend=on|off]\n"
@@ -3563,13 +3563,19 @@ The available backends are:
Create a ring buffer with fixed size ``size``. size must be a power
of two and defaults to ``64K``.
-``-chardev file,id=id,path=path``
+``-chardev file,id=id,path=path[,input-path=input-path]``
Log all traffic received from the guest to a file.
``path`` specifies the path of the file to be opened. This file will
be created if it does not already exist, and overwritten if it does.
``path`` is required.
+ If ``input-path`` is specified, this is the path of a second file
+ which will be used for input. If ``input-path`` is not specified,
+ no input will be available from the chardev.
+
+ Note that ``input-path`` is not supported on Windows hosts.
+
``-chardev pipe,id=id,path=path``
Create a two-way connection to the guest. The behaviour differs
slightly between Windows hosts and other hosts:
diff --git a/softmmu/dirtylimit.c b/softmmu/dirtylimit.c
index c56f0f5..82986c1 100644
--- a/softmmu/dirtylimit.c
+++ b/softmmu/dirtylimit.c
@@ -20,6 +20,7 @@
#include "monitor/hmp.h"
#include "monitor/monitor.h"
#include "exec/memory.h"
+#include "exec/target_page.h"
#include "hw/boards.h"
#include "sysemu/kvm.h"
#include "trace.h"
@@ -236,7 +237,7 @@ static inline int64_t dirtylimit_dirty_ring_full_time(uint64_t dirtyrate)
static uint64_t max_dirtyrate;
uint32_t dirty_ring_size = kvm_dirty_ring_size();
uint64_t dirty_ring_size_meory_MB =
- dirty_ring_size * TARGET_PAGE_SIZE >> 20;
+ dirty_ring_size * qemu_target_page_size() >> 20;
if (max_dirtyrate < dirtyrate) {
max_dirtyrate = dirtyrate;
diff --git a/softmmu/meson.build b/softmmu/meson.build
index 1a7c7ac..974732b 100644
--- a/softmmu/meson.build
+++ b/softmmu/meson.build
@@ -3,8 +3,6 @@ specific_ss.add(when: 'CONFIG_SOFTMMU', if_true: [files(
'ioport.c',
'memory.c',
'physmem.c',
- 'qtest.c',
- 'dirtylimit.c',
'watchpoint.c',
)])
@@ -19,10 +17,12 @@ softmmu_ss.add(files(
'cpu-throttle.c',
'cpu-timers.c',
'datadir.c',
+ 'dirtylimit.c',
'dma-helpers.c',
'globals.c',
'memory_mapping.c',
'qdev-monitor.c',
+ 'qtest.c',
'rtc.c',
'runstate-action.c',
'runstate-hmp-cmds.c',
diff --git a/softmmu/qtest.c b/softmmu/qtest.c
index 34bd2a3..f8d764b 100644
--- a/softmmu/qtest.c
+++ b/softmmu/qtest.c
@@ -13,12 +13,12 @@
#include "qemu/osdep.h"
#include "qapi/error.h"
-#include "cpu.h"
#include "sysemu/qtest.h"
#include "sysemu/runstate.h"
#include "chardev/char-fe.h"
#include "exec/ioport.h"
#include "exec/memory.h"
+#include "exec/tswap.h"
#include "hw/qdev-core.h"
#include "hw/irq.h"
#include "qemu/accel.h"
@@ -29,10 +29,6 @@
#include "qemu/module.h"
#include "qemu/cutils.h"
#include "qom/object_interfaces.h"
-#include CONFIG_DEVICES
-#ifdef CONFIG_PSERIES
-#include "hw/ppc/spapr_rtas.h"
-#endif
#define MAX_IRQ 256
@@ -263,7 +259,7 @@ static int hex2nib(char ch)
}
}
-static void qtest_send_prefix(CharBackend *chr)
+void qtest_send_prefix(CharBackend *chr)
{
if (!qtest_log_fp || !qtest_opened) {
return;
@@ -302,8 +298,7 @@ static void qtest_send(CharBackend *chr, const char *str)
qtest_server_send(qtest_server_send_opaque, str);
}
-static void G_GNUC_PRINTF(2, 3) qtest_sendf(CharBackend *chr,
- const char *fmt, ...)
+void qtest_sendf(CharBackend *chr, const char *fmt, ...)
{
va_list ap;
gchar *buffer;
@@ -361,6 +356,15 @@ static void qtest_clock_warp(int64_t dest)
qemu_clock_notify(QEMU_CLOCK_VIRTUAL);
}
+static bool (*process_command_cb)(CharBackend *chr, gchar **words);
+
+void qtest_set_command_cb(bool (*pc_cb)(CharBackend *chr, gchar **words))
+{
+ assert(!process_command_cb); /* Switch to a list if we need more than one */
+
+ process_command_cb = pc_cb;
+}
+
static void qtest_process_command(CharBackend *chr, gchar **words)
{
const gchar *command;
@@ -713,30 +717,11 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
qtest_send(chr, "OK\n");
} else if (strcmp(words[0], "endianness") == 0) {
qtest_send_prefix(chr);
-#if TARGET_BIG_ENDIAN
- qtest_sendf(chr, "OK big\n");
-#else
- qtest_sendf(chr, "OK little\n");
-#endif
-#ifdef CONFIG_PSERIES
- } else if (strcmp(words[0], "rtas") == 0) {
- uint64_t res, args, ret;
- unsigned long nargs, nret;
- int rc;
-
- rc = qemu_strtoul(words[2], NULL, 0, &nargs);
- g_assert(rc == 0);
- rc = qemu_strtou64(words[3], NULL, 0, &args);
- g_assert(rc == 0);
- rc = qemu_strtoul(words[4], NULL, 0, &nret);
- g_assert(rc == 0);
- rc = qemu_strtou64(words[5], NULL, 0, &ret);
- g_assert(rc == 0);
- res = qtest_rtas_call(words[1], nargs, args, nret, ret);
-
- qtest_send_prefix(chr);
- qtest_sendf(chr, "OK %"PRIu64"\n", res);
-#endif
+ if (target_words_bigendian()) {
+ qtest_sendf(chr, "OK big\n");
+ } else {
+ qtest_sendf(chr, "OK little\n");
+ }
} else if (qtest_enabled() && strcmp(words[0], "clock_step") == 0) {
int64_t ns;
@@ -777,6 +762,8 @@ static void qtest_process_command(CharBackend *chr, gchar **words)
qtest_send_prefix(chr);
qtest_sendf(chr, "OK %"PRIi64"\n",
(int64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
+ } else if (process_command_cb && process_command_cb(chr, words)) {
+ /* Command got consumed by the callback handler */
} else {
qtest_send_prefix(chr);
qtest_sendf(chr, "FAIL Unknown command '%s'\n", words[0]);
@@ -867,7 +854,7 @@ void qtest_server_init(const char *qtest_chrdev, const char *qtest_log, Error **
}
qtest = object_new(TYPE_QTEST);
- object_property_set_str(qtest, "chardev", "qtest", &error_abort);
+ object_property_set_str(qtest, "chardev", chr->label, &error_abort);
if (qtest_log) {
object_property_set_str(qtest, "log", qtest_log, &error_abort);
}
diff --git a/softmmu/vl.c b/softmmu/vl.c
index ea20b23..5cb72a5 100644
--- a/softmmu/vl.c
+++ b/softmmu/vl.c
@@ -2432,7 +2432,7 @@ static void qemu_process_help_options(void)
* to say '-cpu help -machine something'.
*/
if (cpu_option && is_help_option(cpu_option)) {
- list_cpus(cpu_option);
+ list_cpus();
exit(0);
}
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index c097cae..d469a26 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -3823,6 +3823,11 @@ static inline bool isar_feature_aa64_ats1e1(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 2;
}
+static inline bool isar_feature_aa64_pan3(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, PAN) >= 3;
+}
+
static inline bool isar_feature_aa64_hcx(const ARMISARegisters *id)
{
return FIELD_EX64(id->id_aa64mmfr1, ID_AA64MMFR1, HCX) != 0;
diff --git a/target/arm/cpu64.c b/target/arm/cpu64.c
index 0fb07cc..735ca54 100644
--- a/target/arm/cpu64.c
+++ b/target/arm/cpu64.c
@@ -1302,7 +1302,7 @@ static void aarch64_max_initfn(Object *obj)
t = FIELD_DP64(t, ID_AA64MMFR1, VH, 1); /* FEAT_VHE */
t = FIELD_DP64(t, ID_AA64MMFR1, HPDS, 1); /* FEAT_HPDS */
t = FIELD_DP64(t, ID_AA64MMFR1, LO, 1); /* FEAT_LOR */
- t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 2); /* FEAT_PAN2 */
+ t = FIELD_DP64(t, ID_AA64MMFR1, PAN, 3); /* FEAT_PAN3 */
t = FIELD_DP64(t, ID_AA64MMFR1, XNX, 1); /* FEAT_XNX */
t = FIELD_DP64(t, ID_AA64MMFR1, ETS, 1); /* FEAT_ETS */
t = FIELD_DP64(t, ID_AA64MMFR1, HCX, 1); /* FEAT_HCX */
diff --git a/target/arm/cpu_tcg.c b/target/arm/cpu_tcg.c
index df0c45e..1911d7e 100644
--- a/target/arm/cpu_tcg.c
+++ b/target/arm/cpu_tcg.c
@@ -546,7 +546,6 @@ static void cortex_a7_initfn(Object *obj)
set_feature(&cpu->env, ARM_FEATURE_EL2);
set_feature(&cpu->env, ARM_FEATURE_EL3);
set_feature(&cpu->env, ARM_FEATURE_PMU);
- cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A7;
cpu->midr = 0x410fc075;
cpu->reset_fpsid = 0x41023075;
cpu->isar.mvfr0 = 0x10110222;
@@ -595,7 +594,6 @@ static void cortex_a15_initfn(Object *obj)
set_feature(&cpu->env, ARM_FEATURE_EL2);
set_feature(&cpu->env, ARM_FEATURE_EL3);
set_feature(&cpu->env, ARM_FEATURE_PMU);
- cpu->kvm_target = QEMU_KVM_ARM_TARGET_CORTEX_A15;
/* r4p0 cpu, not requiring expensive tlb flush errata */
cpu->midr = 0x414fc0f0;
cpu->revidr = 0x0;
diff --git a/target/arm/gdbstub.c b/target/arm/gdbstub.c
index 13fbe9b..03b17c8 100644
--- a/target/arm/gdbstub.c
+++ b/target/arm/gdbstub.c
@@ -521,11 +521,11 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
aarch64_gdb_set_fpu_reg,
34, "aarch64-fpu.xml", 0);
}
-#if 0
/*
- * GDB versions 9 through 12 have a bug which means they will
- * crash if they see this XML from QEMU; disable it for the 8.0
- * release, pending a better solution.
+ * Note that we report pauth information via the feature name
+ * org.gnu.gdb.aarch64.pauth_v2, not org.gnu.gdb.aarch64.pauth.
+ * GDB versions 9 through 12 have a bug where they will crash
+ * if they see the latter XML from QEMU.
*/
if (isar_feature_aa64_pauth(&cpu->isar)) {
gdb_register_coprocessor(cs, aarch64_gdb_get_pauth_reg,
@@ -533,7 +533,6 @@ void arm_cpu_register_gdb_regs_for_features(ARMCPU *cpu)
4, "aarch64-pauth.xml", 0);
}
#endif
-#endif
} else {
if (arm_feature(env, ARM_FEATURE_NEON)) {
gdb_register_coprocessor(cs, vfp_gdb_get_reg, vfp_gdb_set_reg,
diff --git a/target/arm/kvm-consts.h b/target/arm/kvm-consts.h
index 09967ec..7c6adc1 100644
--- a/target/arm/kvm-consts.h
+++ b/target/arm/kvm-consts.h
@@ -124,13 +124,10 @@ MISMATCH_CHECK(QEMU_PSCI_RET_INTERNAL_FAILURE, PSCI_RET_INTERNAL_FAILURE);
MISMATCH_CHECK(QEMU_PSCI_RET_NOT_PRESENT, PSCI_RET_NOT_PRESENT);
MISMATCH_CHECK(QEMU_PSCI_RET_DISABLED, PSCI_RET_DISABLED);
-/* Note that KVM uses overlapping values for AArch32 and AArch64
- * target CPU numbers. AArch32 targets:
+/*
+ * Note that KVM uses overlapping values for AArch32 and AArch64
+ * target CPU numbers. AArch64 targets:
*/
-#define QEMU_KVM_ARM_TARGET_CORTEX_A15 0
-#define QEMU_KVM_ARM_TARGET_CORTEX_A7 1
-
-/* AArch64 targets: */
#define QEMU_KVM_ARM_TARGET_AEM_V8 0
#define QEMU_KVM_ARM_TARGET_FOUNDATION_V8 1
#define QEMU_KVM_ARM_TARGET_CORTEX_A57 2
diff --git a/target/arm/kvm.c b/target/arm/kvm.c
index f022c64..84da493 100644
--- a/target/arm/kvm.c
+++ b/target/arm/kvm.c
@@ -280,6 +280,8 @@ int kvm_arch_init(MachineState *ms, KVMState *s)
}
}
+ kvm_arm_init_debug(s);
+
return ret;
}
diff --git a/target/arm/kvm64.c b/target/arm/kvm64.c
index 1197253..810db33 100644
--- a/target/arm/kvm64.c
+++ b/target/arm/kvm64.c
@@ -74,24 +74,16 @@ GArray *hw_breakpoints, *hw_watchpoints;
#define get_hw_bp(i) (&g_array_index(hw_breakpoints, HWBreakpoint, i))
#define get_hw_wp(i) (&g_array_index(hw_watchpoints, HWWatchpoint, i))
-/**
- * kvm_arm_init_debug() - check for guest debug capabilities
- * @cs: CPUState
- *
- * kvm_check_extension returns the number of debug registers we have
- * or 0 if we have none.
- *
- */
-static void kvm_arm_init_debug(CPUState *cs)
+void kvm_arm_init_debug(KVMState *s)
{
- have_guest_debug = kvm_check_extension(cs->kvm_state,
+ have_guest_debug = kvm_check_extension(s,
KVM_CAP_SET_GUEST_DEBUG);
- max_hw_wps = kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBUG_HW_WPS);
+ max_hw_wps = kvm_check_extension(s, KVM_CAP_GUEST_DEBUG_HW_WPS);
hw_watchpoints = g_array_sized_new(true, true,
sizeof(HWWatchpoint), max_hw_wps);
- max_hw_bps = kvm_check_extension(cs->kvm_state, KVM_CAP_GUEST_DEBUG_HW_BPS);
+ max_hw_bps = kvm_check_extension(s, KVM_CAP_GUEST_DEBUG_HW_BPS);
hw_breakpoints = g_array_sized_new(true, true,
sizeof(HWBreakpoint), max_hw_bps);
return;
@@ -920,8 +912,6 @@ int kvm_arch_init_vcpu(CPUState *cs)
}
cpu->mp_affinity = mpidr & ARM64_AFFINITY_MASK;
- kvm_arm_init_debug(cs);
-
/* Check whether user space can specify guest syndrome value */
kvm_arm_init_serror_injection(cs);
diff --git a/target/arm/kvm_arm.h b/target/arm/kvm_arm.h
index 99017b6..330fbe5 100644
--- a/target/arm/kvm_arm.h
+++ b/target/arm/kvm_arm.h
@@ -19,6 +19,14 @@
#define KVM_ARM_VGIC_V3 (1 << 1)
/**
+ * kvm_arm_init_debug() - initialize guest debug capabilities
+ * @s: KVMState
+ *
+ * Should be called only once before using guest debug capabilities.
+ */
+void kvm_arm_init_debug(KVMState *s);
+
+/**
* kvm_arm_vcpu_init:
* @cs: CPUState
*
diff --git a/target/arm/ptw.c b/target/arm/ptw.c
index 6d72950..bd75da8 100644
--- a/target/arm/ptw.c
+++ b/target/arm/ptw.c
@@ -947,6 +947,7 @@ static int get_S2prot(CPUARMState *env, int s2ap, int xn, bool s1_is_el0)
static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
int ap, int ns, int xn, int pxn)
{
+ ARMCPU *cpu = env_archcpu(env);
bool is_user = regime_is_user(env, mmu_idx);
int prot_rw, user_rw;
bool have_wxn;
@@ -958,8 +959,19 @@ static int get_S1prot(CPUARMState *env, ARMMMUIdx mmu_idx, bool is_aa64,
if (is_user) {
prot_rw = user_rw;
} else {
+ /*
+ * PAN controls can forbid data accesses but don't affect insn fetch.
+ * Plain PAN forbids data accesses if EL0 has data permissions;
+ * PAN3 forbids data accesses if EL0 has either data or exec perms.
+ * Note that for AArch64 the 'user can exec' case is exactly !xn.
+ * We make the IMPDEF choices that SCR_EL3.SIF and Realm EL2&0
+ * do not affect EPAN.
+ */
if (user_rw && regime_is_pan(env, mmu_idx)) {
- /* PAN forbids data accesses but doesn't affect insn fetch */
+ prot_rw = 0;
+ } else if (cpu_isar_feature(aa64_pan3, cpu) && is_aa64 &&
+ regime_is_pan(env, mmu_idx) &&
+ (regime_sctlr(env, mmu_idx) & SCTLR_EPAN) && !xn) {
prot_rw = 0;
} else {
prot_rw = simple_ap_to_rw_prot_is_user(ap, false);
diff --git a/target/arm/tcg/tlb_helper.c b/target/arm/tcg/tlb_helper.c
index 31eb77f..d5a89bc 100644
--- a/target/arm/tcg/tlb_helper.c
+++ b/target/arm/tcg/tlb_helper.c
@@ -24,16 +24,17 @@ bool arm_s1_regime_using_lpae_format(CPUARMState *env, ARMMMUIdx mmu_idx)
}
static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
+ ARMMMUFaultInfo *fi,
unsigned int target_el,
- bool same_el, bool ea,
- bool s1ptw, bool is_write,
+ bool same_el, bool is_write,
int fsc)
{
uint32_t syn;
/*
- * ISV is only set for data aborts routed to EL2 and
- * never for stage-1 page table walks faulting on stage 2.
+ * ISV is only set for stage-2 data aborts routed to EL2 and
+ * never for stage-1 page table walks faulting on stage 2
+ * or for stage-1 faults.
*
* Furthermore, ISV is only set for certain kinds of load/stores.
* If the template syndrome does not have ISV set, we should leave
@@ -42,10 +43,16 @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
* See ARMv8 specs, D7-1974:
* ISS encoding for an exception from a Data Abort, the
* ISV field.
+ *
+ * TODO: FEAT_LS64/FEAT_LS64_V/FEAT_SL64_ACCDATA: Translation,
+ * Access Flag, and Permission faults caused by LD64B, ST64B,
+ * ST64BV, or ST64BV0 insns report syndrome info even for stage-1
+ * faults and regardless of the target EL.
*/
- if (!(template_syn & ARM_EL_ISV) || target_el != 2 || s1ptw) {
+ if (!(template_syn & ARM_EL_ISV) || target_el != 2
+ || fi->s1ptw || !fi->stage2) {
syn = syn_data_abort_no_iss(same_el, 0,
- ea, 0, s1ptw, is_write, fsc);
+ fi->ea, 0, fi->s1ptw, is_write, fsc);
} else {
/*
* Fields: IL, ISV, SAS, SSE, SRT, SF and AR come from the template
@@ -54,7 +61,7 @@ static inline uint32_t merge_syn_data_abort(uint32_t template_syn,
*/
syn = syn_data_abort_with_iss(same_el,
0, 0, 0, 0, 0,
- ea, 0, s1ptw, is_write, fsc,
+ fi->ea, 0, fi->s1ptw, is_write, fsc,
true);
/* Merge the runtime syndrome with the template syndrome. */
syn |= template_syn;
@@ -117,9 +124,8 @@ void arm_deliver_fault(ARMCPU *cpu, vaddr addr,
syn = syn_insn_abort(same_el, fi->ea, fi->s1ptw, fsc);
exc = EXCP_PREFETCH_ABORT;
} else {
- syn = merge_syn_data_abort(env->exception.syndrome, target_el,
- same_el, fi->ea, fi->s1ptw,
- access_type == MMU_DATA_STORE,
+ syn = merge_syn_data_abort(env->exception.syndrome, fi, target_el,
+ same_el, access_type == MMU_DATA_STORE,
fsc);
if (access_type == MMU_DATA_STORE
&& arm_feature(env, ARM_FEATURE_V6)) {
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index 6576287..95c0dcd 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -45,6 +45,8 @@
#include "disas/capstone.h"
#include "cpu-internal.h"
+static void x86_cpu_realizefn(DeviceState *dev, Error **errp);
+
/* Helpers for building CPUID[2] descriptors: */
struct CPUID2CacheDescriptorInfo {
@@ -4316,6 +4318,25 @@ static Property max_x86_cpu_properties[] = {
DEFINE_PROP_END_OF_LIST()
};
+static void max_x86_cpu_realize(DeviceState *dev, Error **errp)
+{
+ Object *obj = OBJECT(dev);
+
+ if (!object_property_get_int(obj, "family", &error_abort)) {
+ if (X86_CPU(obj)->env.features[FEAT_8000_0001_EDX] & CPUID_EXT2_LM) {
+ object_property_set_int(obj, "family", 15, &error_abort);
+ object_property_set_int(obj, "model", 107, &error_abort);
+ object_property_set_int(obj, "stepping", 1, &error_abort);
+ } else {
+ object_property_set_int(obj, "family", 6, &error_abort);
+ object_property_set_int(obj, "model", 6, &error_abort);
+ object_property_set_int(obj, "stepping", 3, &error_abort);
+ }
+ }
+
+ x86_cpu_realizefn(dev, errp);
+}
+
static void max_x86_cpu_class_init(ObjectClass *oc, void *data)
{
DeviceClass *dc = DEVICE_CLASS(oc);
@@ -4327,6 +4348,7 @@ static void max_x86_cpu_class_init(ObjectClass *oc, void *data)
"Enables all features supported by the accelerator in the current host";
device_class_set_props(dc, max_x86_cpu_properties);
+ dc->realize = max_x86_cpu_realize;
}
static void max_x86_cpu_initfn(Object *obj)
@@ -4345,15 +4367,6 @@ static void max_x86_cpu_initfn(Object *obj)
*/
object_property_set_str(OBJECT(cpu), "vendor", CPUID_VENDOR_AMD,
&error_abort);
-#ifdef TARGET_X86_64
- object_property_set_int(OBJECT(cpu), "family", 15, &error_abort);
- object_property_set_int(OBJECT(cpu), "model", 107, &error_abort);
- object_property_set_int(OBJECT(cpu), "stepping", 1, &error_abort);
-#else
- object_property_set_int(OBJECT(cpu), "family", 6, &error_abort);
- object_property_set_int(OBJECT(cpu), "model", 6, &error_abort);
- object_property_set_int(OBJECT(cpu), "stepping", 3, &error_abort);
-#endif
object_property_set_str(OBJECT(cpu), "model-id",
"QEMU TCG CPU version " QEMU_HW_VERSION,
&error_abort);
diff --git a/tests/avocado/boot_linux_console.py b/tests/avocado/boot_linux_console.py
index 574609b..c067580 100644
--- a/tests/avocado/boot_linux_console.py
+++ b/tests/avocado/boot_linux_console.py
@@ -581,7 +581,10 @@ class BootLinuxConsole(LinuxKernelTest):
'Allwinner sun4i/sun5i')
exec_command_and_wait_for_pattern(self, 'cat /proc/iomem',
'system-control@1c00000')
- # cubieboard's reboot is not functioning; omit reboot test.
+ exec_command_and_wait_for_pattern(self, 'reboot',
+ 'reboot: Restarting system')
+ # Wait for VM to shut down gracefully
+ self.vm.wait()
def test_arm_cubieboard_sata(self):
"""
@@ -625,7 +628,10 @@ class BootLinuxConsole(LinuxKernelTest):
'Allwinner sun4i/sun5i')
exec_command_and_wait_for_pattern(self, 'cat /proc/partitions',
'sda')
- # cubieboard's reboot is not functioning; omit reboot test.
+ exec_command_and_wait_for_pattern(self, 'reboot',
+ 'reboot: Restarting system')
+ # Wait for VM to shut down gracefully
+ self.vm.wait()
@skipUnless(os.getenv('AVOCADO_ALLOW_LARGE_STORAGE'), 'storage limited')
def test_arm_cubieboard_openwrt_22_03_2(self):
@@ -672,7 +678,10 @@ class BootLinuxConsole(LinuxKernelTest):
exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo',
'Allwinner sun4i/sun5i')
- # cubieboard's reboot is not functioning; omit reboot test.
+ exec_command_and_wait_for_pattern(self, 'reboot',
+ 'reboot: Restarting system')
+ # Wait for VM to shut down gracefully
+ self.vm.wait()
@skipUnless(os.getenv('AVOCADO_TIMEOUT_EXPECTED'), 'Test might timeout')
def test_arm_quanta_gsj(self):
diff --git a/tests/qtest/migration-test.c b/tests/qtest/migration-test.c
index 3b615b0..60dd53d 100644
--- a/tests/qtest/migration-test.c
+++ b/tests/qtest/migration-test.c
@@ -1796,6 +1796,21 @@ static void test_validate_uuid_dst_not_set(void)
do_test_validate_uuid(&args, false);
}
+/*
+ * The way auto_converge works, we need to do too many passes to
+ * run this test. Auto_converge logic is only run once every
+ * three iterations, so:
+ *
+ * - 3 iterations without auto_converge enabled
+ * - 3 iterations with pct = 5
+ * - 3 iterations with pct = 30
+ * - 3 iterations with pct = 55
+ * - 3 iterations with pct = 80
+ * - 3 iterations with pct = 95 (max(95, 80 + 25))
+ *
+ * To make things even worse, we need to run the initial stage at
+ * 3MB/s so we enter autoconverge even when host is (over)loaded.
+ */
static void test_migrate_auto_converge(void)
{
g_autofree char *uri = g_strdup_printf("unix:%s/migsocket", tmpfs);
@@ -2575,8 +2590,12 @@ int main(int argc, char **argv)
test_validate_uuid_src_not_set);
qtest_add_func("/migration/validate_uuid_dst_not_set",
test_validate_uuid_dst_not_set);
-
- qtest_add_func("/migration/auto_converge", test_migrate_auto_converge);
+ /*
+ * See explanation why this test is slow on function definition
+ */
+ if (g_test_slow()) {
+ qtest_add_func("/migration/auto_converge", test_migrate_auto_converge);
+ }
qtest_add_func("/migration/multifd/tcp/plain/none",
test_multifd_tcp_none);
/*
diff --git a/tests/unit/test-crypto-secret.c b/tests/unit/test-crypto-secret.c
index 34a4aec..147b4af 100644
--- a/tests/unit/test-crypto-secret.c
+++ b/tests/unit/test-crypto-secret.c
@@ -24,7 +24,7 @@
#include "crypto/secret.h"
#include "qapi/error.h"
#include "qemu/module.h"
-#ifdef CONFIG_KEYUTILS
+#if defined(CONFIG_KEYUTILS) && defined(CONFIG_SECRET_KEYRING)
#include "crypto/secret_keyring.h"
#include <keyutils.h>
#endif
@@ -128,7 +128,7 @@ static void test_secret_indirect_emptyfile(void)
g_free(fname);
}
-#ifdef CONFIG_KEYUTILS
+#if defined(CONFIG_KEYUTILS) && defined(CONFIG_SECRET_KEYRING)
#define DESCRIPTION "qemu_test_secret"
#define PAYLOAD "Test Payload"
@@ -268,7 +268,7 @@ static void test_secret_keyring_bad_key_access_right(void)
keyctl_unlink(key, KEY_SPEC_PROCESS_KEYRING);
}
-#endif /* CONFIG_KEYUTILS */
+#endif /* CONFIG_KEYUTILS && CONFIG_SECRET_KEYRING */
static void test_secret_noconv_base64_good(void)
{
@@ -571,7 +571,7 @@ int main(int argc, char **argv)
g_test_add_func("/crypto/secret/indirect/emptyfile",
test_secret_indirect_emptyfile);
-#ifdef CONFIG_KEYUTILS
+#if defined(CONFIG_KEYUTILS) && defined(CONFIG_SECRET_KEYRING)
g_test_add_func("/crypto/secret/keyring/good",
test_secret_keyring_good);
g_test_add_func("/crypto/secret/keyring/revoked_key",
@@ -582,7 +582,7 @@ int main(int argc, char **argv)
test_secret_keyring_bad_serial_key);
g_test_add_func("/crypto/secret/keyring/bad_key_access_right",
test_secret_keyring_bad_key_access_right);
-#endif /* CONFIG_KEYUTILS */
+#endif /* CONFIG_KEYUTILS && CONFIG_SECRET_KEYRING */
g_test_add_func("/crypto/secret/noconv/base64/good",
test_secret_noconv_base64_good);
diff --git a/tests/vm/freebsd b/tests/vm/freebsd
index ba2ba23..11de647 100755
--- a/tests/vm/freebsd
+++ b/tests/vm/freebsd
@@ -28,15 +28,15 @@ class FreeBSDVM(basevm.BaseVM):
name = "freebsd"
arch = "x86_64"
- link = "https://download.freebsd.org/ftp/releases/ISO-IMAGES/12.4/FreeBSD-12.4-RELEASE-amd64-disc1.iso.xz"
- csum = "1dcf6446e31bf3f81b582e9aba3319a258c29a937a2af6138ee4b181ed719a87"
+ link = "https://download.freebsd.org/releases/CI-IMAGES/13.2-RELEASE/amd64/Latest/FreeBSD-13.2-RELEASE-amd64-BASIC-CI.raw.xz"
+ csum = "a4fb3b6c7b75dd4d58fb0d75e4caf72844bffe0ca00e66459c028b198ffb3c0e"
size = "20G"
pkgs = [
# build tools
"git",
"pkgconf",
"bzip2",
- "python37",
+ "python39",
"ninja",
# gnu tools
@@ -78,72 +78,42 @@ class FreeBSDVM(basevm.BaseVM):
mkdir src build; cd src;
tar -xf /dev/vtbd1;
cd ../build
- ../src/configure --python=python3.7 {configure_opts};
+ ../src/configure --python=python3.9 {configure_opts};
gmake --output-sync -j{jobs} {target} {verbose};
"""
- def console_boot_serial(self):
- self.console_wait_send("Autoboot", "3")
- self.console_wait_send("OK", "set console=comconsole\n")
- self.console_wait_send("OK", "boot\n")
-
def build_image(self, img):
- self.print_step("Downloading install iso")
+ self.print_step("Downloading disk image")
cimg = self._download_with_cache(self.link, sha256sum=self.csum)
- img_tmp = img + ".tmp"
- iso = img + ".install.iso"
- iso_xz = iso + ".xz"
-
- self.print_step("Preparing iso and disk image")
- subprocess.check_call(["cp", "-f", cimg, iso_xz])
- subprocess.check_call(["xz", "-dvf", iso_xz])
- self.exec_qemu_img("create", "-f", "qcow2", img_tmp, self.size)
-
- self.print_step("Booting installer")
+ tmp_raw = img + ".tmp.raw"
+ tmp_raw_xz = tmp_raw + ".xz"
+ img_tmp = img + ".tmp.qcow2"
+
+ self.print_step("Preparing disk image")
+ subprocess.check_call(["cp", "-f", cimg, tmp_raw_xz])
+ subprocess.check_call(["xz", "-dvf", tmp_raw_xz])
+ self.exec_qemu_img("convert", "-O", "qcow2", tmp_raw, img_tmp)
+ self.exec_qemu_img("resize", img_tmp, self.size)
+ os.remove(tmp_raw)
+
+ self.print_step("Preparing disk image")
self.boot(img_tmp, extra_args = [
"-machine", "graphics=off",
- "-device", "VGA",
- "-cdrom", iso
+ "-vga", "none"
])
self.console_init()
- self.console_boot_serial()
- self.console_wait_send("Console type", "xterm\n")
-
- # pre-install configuration
- self.console_wait_send("Welcome", "\n")
- self.console_wait_send("Keymap Selection", "\n")
- self.console_wait_send("Set Hostname", "freebsd\n")
- self.console_wait_send("Distribution Select", "\n")
- self.console_wait_send("Partitioning", "\n")
- self.console_wait_send("Partition", "\n")
- self.console_wait_send("Scheme", "\n")
- self.console_wait_send("Editor", "f")
- self.console_wait_send("Confirmation", "c")
-
- self.print_step("Installation started now, this will take a while")
-
- # post-install configuration
+ self.console_wait_send("login:", "root\n")
+ self.console_wait_send("~ #", "service growfs onestart\n")
+
+ # root user
+ self.console_wait_send("~ #", "passwd\n")
self.console_wait("New Password:")
self.console_send("%s\n" % self._config["root_pass"])
self.console_wait("Retype New Password:")
self.console_send("%s\n" % self._config["root_pass"])
- self.console_wait_send("Network Configuration", "\n")
- self.console_wait_send("IPv4", "y")
- self.console_wait_send("DHCP", "y")
- self.console_wait_send("IPv6", "n")
- self.console_wait_send("Resolver", "\n")
-
- self.console_wait_send("Time Zone Selector", "0\n")
- self.console_wait_send("Confirmation", "y")
- self.console_wait_send("Time & Date", "\n")
- self.console_wait_send("Time & Date", "\n")
-
- self.console_wait_send("System Configuration", "\n")
- self.console_wait_send("System Hardening", "\n")
-
# qemu user
- self.console_wait_send("Add User Accounts", "y")
+ self.console_wait_send("~ #", "adduser\n")
self.console_wait("Username")
self.console_send("%s\n" % self._config["guest_user"])
self.console_wait("Full name")
@@ -165,13 +135,7 @@ class FreeBSDVM(basevm.BaseVM):
self.console_wait_send("Lock out", "\n")
self.console_wait_send("OK", "yes\n")
self.console_wait_send("Add another user", "no\n")
-
- self.console_wait_send("Final Configuration", "\n")
- self.console_wait_send("Manual Configuration", "\n")
- self.console_wait_send("Complete", "\n")
-
- self.print_step("Installation finished, rebooting")
- self.console_boot_serial()
+ self.console_wait_send("~ #", "exit\n")
# setup qemu user
prompt = "$"
@@ -183,35 +147,20 @@ class FreeBSDVM(basevm.BaseVM):
self.console_ssh_init(prompt, "root", self._config["root_pass"])
self.console_sshd_config(prompt)
- # setup serial console
- self.console_wait(prompt)
- self.console_send("echo 'console=comconsole' >> /boot/loader.conf\n")
-
- # setup boot delay
- self.console_wait(prompt)
- self.console_send("echo 'autoboot_delay=1' >> /boot/loader.conf\n")
-
# setup virtio-blk #1 (tarfile)
self.console_wait(prompt)
self.console_send("echo 'chmod 666 /dev/vtbd1' >> /etc/rc.local\n")
- self.print_step("Configuration finished, rebooting")
- self.console_wait_send(prompt, "reboot\n")
- self.console_wait("login:")
- self.wait_ssh()
-
self.print_step("Installing packages")
self.ssh_root_check("pkg install -y %s\n" % " ".join(self.pkgs))
# shutdown
self.ssh_root(self.poweroff)
- self.console_wait("Uptime:")
self.wait()
if os.path.exists(img):
os.remove(img)
os.rename(img_tmp, img)
- os.remove(iso)
self.print_step("All done")
if __name__ == "__main__":