Merge tag 'pull-nbd-2024-04-25' of https://repo.or.cz/qemu/ericb into staging
NBD patches for 2024-04-25
- Avoid calling poll() within coroutine
# -----BEGIN PGP SIGNATURE-----
#
# iQEzBAABCAAdFiEEccLMIrHEYCkn0vOqp6FrSiUnQ2oFAmYqzkMACgkQp6FrSiUn
# Q2ol3wf9HbwiYkyHhqybb4ykEs75N8B2JPbOj6gYRSBn7rz90k1vElDCM2yQhlDN
# Ltuh8lTOaJb+Z4n2dKIF2m5hL2GTm/xtErIIpP7o6A+11mHW9ag/VLaAMdWJxmUr
# WEUIH6mVtuRcxTTCp01l/JAYpUxOoQs1fyQljONH5kg1MAZpTTD61/cuhrXlvPLU
# cVlrLfob90oYhydCq5o6ucW3GhaEYkaZzHIWFy7LphFySebMmnbnPhYf/JD6RZPL
# s5K7njMK1DOyguCLlOzSuRM4gIbYunnr0Ofr/orTlAUZvbhRGKUlH0RTMWVMzgek
# xArnEZYlsqF2wIvrz0GwMDL7BMmG7A==
# =vXJj
# -----END PGP SIGNATURE-----
# gpg: Signature made Thu 25 Apr 2024 02:42:27 PM PDT
# gpg: using RSA key 71C2CC22B1C4602927D2F3AAA7A16B4A2527436A
# gpg: Good signature from "Eric Blake <eblake@redhat.com>" [full]
# gpg: aka "Eric Blake (Free Software Programmer) <ebb9@byu.net>" [full]
# gpg: aka "[jpeg image of size 6874]" [full]
* tag 'pull-nbd-2024-04-25' of https://repo.or.cz/qemu/ericb:
nbd/server: Mark negotiation functions as coroutine_fn
nbd/server: do not poll within a coroutine context
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
diff --git a/.gitlab-ci.d/buildtest.yml b/.gitlab-ci.d/buildtest.yml
index 5848c73..6394b8f 100644
--- a/.gitlab-ci.d/buildtest.yml
+++ b/.gitlab-ci.d/buildtest.yml
@@ -158,9 +158,9 @@
- .native_build_job_template
- .native_build_artifact_template
needs:
- job: amd64-centos8-container
+ job: amd64-centos9-container
variables:
- IMAGE: centos8
+ IMAGE: centos9
CONFIGURE_ARGS: --disable-nettle --enable-gcrypt --enable-vfio-user-server
--enable-modules --enable-trace-backends=dtrace --enable-docs
TARGETS: ppc64-softmmu or1k-softmmu s390x-softmmu
@@ -242,7 +242,7 @@
- job: build-system-centos
artifacts: true
variables:
- IMAGE: centos8
+ IMAGE: centos9
MAKE_CHECK_ARGS: check
avocado-system-centos:
@@ -251,7 +251,7 @@
- job: build-system-centos
artifacts: true
variables:
- IMAGE: centos8
+ IMAGE: centos9
MAKE_CHECK_ARGS: check-avocado
AVOCADO_TAGS: arch:ppc64 arch:or1k arch:s390x arch:x86_64 arch:rx
arch:sh4
@@ -327,9 +327,9 @@
build-tcg-disabled:
extends: .native_build_job_template
needs:
- job: amd64-centos8-container
+ job: amd64-centos9-container
variables:
- IMAGE: centos8
+ IMAGE: centos9
script:
- mkdir build
- cd build
@@ -651,9 +651,9 @@
build-without-defaults:
extends: .native_build_job_template
needs:
- job: amd64-centos8-container
+ job: amd64-centos9-container
variables:
- IMAGE: centos8
+ IMAGE: centos9
CONFIGURE_ARGS:
--without-default-devices
--without-default-features
diff --git a/.gitlab-ci.d/container-core.yml b/.gitlab-ci.d/container-core.yml
index 08f8450..5459447 100644
--- a/.gitlab-ci.d/container-core.yml
+++ b/.gitlab-ci.d/container-core.yml
@@ -1,10 +1,10 @@
include:
- local: '/.gitlab-ci.d/container-template.yml'
-amd64-centos8-container:
+amd64-centos9-container:
extends: .container_job_template
variables:
- NAME: centos8
+ NAME: centos9
amd64-fedora-container:
extends: .container_job_template
diff --git a/.travis.yml b/.travis.yml
index 8a3ae76..cef0308 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,5 @@
os: linux
-dist: focal
+dist: jammy
language: c
compiler:
- gcc
@@ -7,13 +7,11 @@
# There is one cache per branch and compiler version.
# characteristics of each job are used to identify the cache:
# - OS name (currently only linux)
- # - OS distribution (for Linux, bionic or focal)
+ # - OS distribution (e.g. "jammy" for Linux)
# - Names and values of visible environment variables set in .travis.yml or Settings panel
timeout: 1200
ccache: true
pip: true
- directories:
- - $HOME/avocado/data/cache
# The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu
@@ -83,7 +81,6 @@
- name: "[aarch64] GCC check-tcg"
arch: arm64
- dist: focal
addons:
apt_packages:
- libaio-dev
@@ -115,11 +112,10 @@
- TEST_CMD="make check check-tcg V=1"
- CONFIG="--disable-containers --enable-fdt=system
--target-list=${MAIN_SYSTEM_TARGETS} --cxx=/bin/false"
- - UNRELIABLE=true
- - name: "[ppc64] GCC check-tcg"
+ - name: "[ppc64] Clang check-tcg"
arch: ppc64le
- dist: focal
+ compiler: clang
addons:
apt_packages:
- libaio-dev
@@ -154,7 +150,6 @@
- name: "[s390x] GCC check-tcg"
arch: s390x
- dist: focal
addons:
apt_packages:
- libaio-dev
@@ -186,7 +181,6 @@
- TEST_CMD="make check check-tcg V=1"
- CONFIG="--disable-containers
--target-list=hppa-softmmu,mips64-softmmu,ppc64-softmmu,riscv64-softmmu,s390x-softmmu,x86_64-softmmu"
- - UNRELIABLE=true
script:
- BUILD_RC=0 && make -j${JOBS} || BUILD_RC=$?
- |
@@ -197,9 +191,9 @@
$(exit $BUILD_RC);
fi
- - name: "[s390x] GCC (other-system)"
+ - name: "[s390x] Clang (other-system)"
arch: s390x
- dist: focal
+ compiler: clang
addons:
apt_packages:
- libaio-dev
@@ -229,7 +223,6 @@
- name: "[s390x] GCC (user)"
arch: s390x
- dist: focal
addons:
apt_packages:
- libgcrypt20-dev
@@ -244,8 +237,7 @@
- name: "[s390x] Clang (disable-tcg)"
arch: s390x
- dist: focal
- compiler: clang-10
+ compiler: clang
addons:
apt_packages:
- libaio-dev
@@ -271,9 +263,7 @@
- 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
--enable-fdt=system --host-cc=clang --cxx=clang++"
- - UNRELIABLE=true
diff --git a/MAINTAINERS b/MAINTAINERS
index 8bb32f4..96411e6 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1115,6 +1115,7 @@
L: qemu-arm@nongnu.org
S: Maintained
F: hw/arm/stm32l4x5_soc.c
+F: hw/char/stm32l4x5_usart.c
F: hw/misc/stm32l4x5_exti.c
F: hw/misc/stm32l4x5_syscfg.c
F: hw/misc/stm32l4x5_rcc.c
@@ -3805,7 +3806,7 @@
RBD
M: Ilya Dryomov <idryomov@gmail.com>
-R: Peter Lieven <pl@kamp.de>
+R: Peter Lieven <pl@dlhnet.de>
L: qemu-block@nongnu.org
S: Supported
F: block/rbd.c
@@ -3831,7 +3832,7 @@
iSCSI
M: Ronnie Sahlberg <ronniesahlberg@gmail.com>
M: Paolo Bonzini <pbonzini@redhat.com>
-M: Peter Lieven <pl@kamp.de>
+M: Peter Lieven <pl@dlhnet.de>
L: qemu-block@nongnu.org
S: Odd Fixes
F: block/iscsi.c
@@ -3854,7 +3855,7 @@
T: git https://gitlab.com/vsementsov/qemu.git block
NFS
-M: Peter Lieven <pl@kamp.de>
+M: Peter Lieven <pl@dlhnet.de>
L: qemu-block@nongnu.org
S: Maintained
F: block/nfs.c
@@ -4229,3 +4230,8 @@
M: Alex Bennée <alex.bennee@linaro.org>
S: Odd Fixes
F: scripts/coverage/
+
+Machine development tool
+M: Maksim Davydov <davydov-max@yandex-team.ru>
+S: Supported
+F: scripts/compare-machine-types.py
diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index baf2f63..833fa3b 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -383,7 +383,7 @@
return "";
}
-/* FIXME: This should use elf_ops.h */
+/* FIXME: This should use elf_ops.h.inc */
static int symcmp(const void *s0, const void *s1)
{
struct elf_sym *sym0 = (struct elf_sym *)s0;
diff --git a/docs/devel/reset.rst b/docs/devel/reset.rst
index 2ea85e7..9746a4e 100644
--- a/docs/devel/reset.rst
+++ b/docs/devel/reset.rst
@@ -27,9 +27,7 @@
``resettable_reset()``. These functions take two parameters: a pointer to the
object to reset and a reset type.
-Several types of reset will be supported. For now only cold reset is defined;
-others may be added later. The Resettable interface handles reset types with an
-enum:
+The Resettable interface handles reset types with an enum ``ResetType``:
``RESET_TYPE_COLD``
Cold reset is supported by every resettable object. In QEMU, it means we reset
@@ -37,6 +35,19 @@
from what is a real hardware cold reset. It differs from other resets (like
warm or bus resets) which may keep certain parts untouched.
+``RESET_TYPE_SNAPSHOT_LOAD``
+ This is called for a reset which is being done to put the system into a
+ clean state prior to loading a snapshot. (This corresponds to a reset
+ with ``SHUTDOWN_CAUSE_SNAPSHOT_LOAD``.) Almost all devices should treat
+ this the same as ``RESET_TYPE_COLD``. The main exception is devices which
+ have some non-deterministic state they want to reinitialize to a different
+ value on each cold reset, such as RNG seed information, and which they
+ must not reinitialize on a snapshot-load reset.
+
+Devices which implement reset methods must treat any unknown ``ResetType``
+as equivalent to ``RESET_TYPE_COLD``; this will reduce the amount of
+existing code we need to change if we add more types in future.
+
Calling ``resettable_reset()`` is equivalent to calling
``resettable_assert_reset()`` then ``resettable_release_reset()``. It is
possible to interleave multiple calls to these three functions. There may
@@ -150,25 +161,25 @@
mydev->var = 0;
}
- static void mydev_reset_hold(Object *obj)
+ static void mydev_reset_hold(Object *obj, ResetType type)
{
MyDevClass *myclass = MYDEV_GET_CLASS(obj);
MyDevState *mydev = MYDEV(obj);
/* call parent class hold phase */
if (myclass->parent_phases.hold) {
- myclass->parent_phases.hold(obj);
+ myclass->parent_phases.hold(obj, type);
}
/* set an IO */
qemu_set_irq(mydev->irq, 1);
}
- static void mydev_reset_exit(Object *obj)
+ static void mydev_reset_exit(Object *obj, ResetType type)
{
MyDevClass *myclass = MYDEV_GET_CLASS(obj);
MyDevState *mydev = MYDEV(obj);
/* call parent class exit phase */
if (myclass->parent_phases.exit) {
- myclass->parent_phases.exit(obj);
+ myclass->parent_phases.exit(obj, type);
}
/* clear an IO */
qemu_set_irq(mydev->irq, 0);
diff --git a/docs/devel/submitting-a-patch.rst b/docs/devel/submitting-a-patch.rst
index c641d94..83e9092 100644
--- a/docs/devel/submitting-a-patch.rst
+++ b/docs/devel/submitting-a-patch.rst
@@ -177,7 +177,7 @@
If your patch fixes a bug in the gitlab bug tracker, please add a line
with "Resolves: <URL-of-the-bug>" to the commit message, too. Gitlab can
-close bugs automatically once commits with the "Resolved:" keyword get
+close bugs automatically once commits with the "Resolves:" keyword get
merged into the master branch of the project. And if your patch addresses
a bug in another public bug tracker, you can also use a line with
"Buglink: <URL-of-the-bug>" for reference here, too.
diff --git a/docs/system/arm/b-l475e-iot01a.rst b/docs/system/arm/b-l475e-iot01a.rst
index 0afef8e..a76c997 100644
--- a/docs/system/arm/b-l475e-iot01a.rst
+++ b/docs/system/arm/b-l475e-iot01a.rst
@@ -19,13 +19,13 @@
- STM32L4x5 SYSCFG (System configuration controller)
- STM32L4x5 RCC (Reset and clock control)
- STM32L4x5 GPIOs (General-purpose I/Os)
+- STM32L4x5 USARTs, UARTs and LPUART (Serial ports)
Missing devices
"""""""""""""""
The B-L475E-IOT01A does *not* support the following devices:
-- Serial ports (UART)
- Analog to Digital Converter (ADC)
- SPI controller
- Timer controller (TIMER)
diff --git a/docs/system/arm/emulation.rst b/docs/system/arm/emulation.rst
index 2a7bbb8..a9ae7ed 100644
--- a/docs/system/arm/emulation.rst
+++ b/docs/system/arm/emulation.rst
@@ -64,6 +64,7 @@
- FEAT_MTE (Memory Tagging Extension)
- FEAT_MTE2 (Memory Tagging Extension)
- FEAT_MTE3 (MTE Asymmetric Fault Handling)
+- FEAT_NMI (Non-maskable Interrupt)
- FEAT_NV (Nested Virtualization)
- FEAT_NV2 (Enhanced nested virtualization support)
- FEAT_PACIMP (Pointer authentication - IMPLEMENTATION DEFINED algorithm)
diff --git a/docs/system/target-i386-desc.rst.inc b/docs/system/target-i386-desc.rst.inc
index 5ebbcda..319e540 100644
--- a/docs/system/target-i386-desc.rst.inc
+++ b/docs/system/target-i386-desc.rst.inc
@@ -36,7 +36,7 @@
- PCI UHCI, OHCI, EHCI or XHCI USB controller and a virtual USB-1.1
hub.
-SMP is supported with up to 255 CPUs.
+SMP is supported with up to 255 CPUs (and 4096 CPUs for PC Q35 machine).
QEMU uses the PC BIOS from the Seabios project and the Plex86/Bochs LGPL
VGA BIOS.
diff --git a/hw/Kconfig b/hw/Kconfig
index b1cc40d..f7866e7 100644
--- a/hw/Kconfig
+++ b/hw/Kconfig
@@ -47,6 +47,7 @@
# arch Kconfig
source arm/Kconfig
+source cpu/Kconfig
source alpha/Kconfig
source avr/Kconfig
source cris/Kconfig
diff --git a/hw/adc/npcm7xx_adc.c b/hw/adc/npcm7xx_adc.c
index c6647ee..de8469d 100644
--- a/hw/adc/npcm7xx_adc.c
+++ b/hw/adc/npcm7xx_adc.c
@@ -218,7 +218,7 @@
npcm7xx_adc_reset(s);
}
-static void npcm7xx_adc_hold_reset(Object *obj)
+static void npcm7xx_adc_hold_reset(Object *obj, ResetType type)
{
NPCM7xxADCState *s = NPCM7XX_ADC(obj);
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 893a7bf..e8b6e5e 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -477,6 +477,7 @@
select STM32L4X5_SYSCFG
select STM32L4X5_RCC
select STM32L4X5_GPIO
+ select STM32L4X5_USART
config XLNX_ZYNQMP_ARM
bool
@@ -485,6 +486,7 @@
select AHCI
select ARM_GIC
select CADENCE
+ select CPU_CLUSTER
select DDC
select DPCD
select SDHCI
@@ -503,6 +505,7 @@
default y
depends on TCG && AARCH64
select ARM_GIC
+ select CPU_CLUSTER
select PL011
select CADENCE
select VIRTIO_MMIO
@@ -678,21 +681,6 @@
select NAND
select ECC
-config A9MPCORE
- bool
- select A9_GTIMER
- select A9SCU # snoop control unit
- select ARM_GIC
- select ARM_MPTIMER
-
-config A15MPCORE
- bool
- select ARM_GIC
-
-config ARM11MPCORE
- bool
- select ARM11SCU
-
config ARMSSE
bool
select ARM_V7M
@@ -703,6 +691,7 @@
select CMSDK_APB_DUALTIMER
select CMSDK_APB_UART
select CMSDK_APB_WATCHDOG
+ select CPU_CLUSTER
select IOTKIT_SECCTL
select IOTKIT_SYSCTL
select IOTKIT_SYSINFO
diff --git a/hw/arm/pxa2xx_pic.c b/hw/arm/pxa2xx_pic.c
index f54546c..34c5555 100644
--- a/hw/arm/pxa2xx_pic.c
+++ b/hw/arm/pxa2xx_pic.c
@@ -272,7 +272,7 @@
return 0;
}
-static void pxa2xx_pic_reset_hold(Object *obj)
+static void pxa2xx_pic_reset_hold(Object *obj, ResetType type)
{
PXA2xxPICState *s = PXA2XX_PIC(obj);
diff --git a/hw/arm/smmu-common.c b/hw/arm/smmu-common.c
index c4b5406..1ce706b 100644
--- a/hw/arm/smmu-common.c
+++ b/hw/arm/smmu-common.c
@@ -682,7 +682,7 @@
}
}
-static void smmu_base_reset_hold(Object *obj)
+static void smmu_base_reset_hold(Object *obj, ResetType type)
{
SMMUState *s = ARM_SMMU(obj);
diff --git a/hw/arm/smmuv3.c b/hw/arm/smmuv3.c
index 9eb56a7..2d1e0d5 100644
--- a/hw/arm/smmuv3.c
+++ b/hw/arm/smmuv3.c
@@ -1727,13 +1727,13 @@
}
}
-static void smmu_reset_hold(Object *obj)
+static void smmu_reset_hold(Object *obj, ResetType type)
{
SMMUv3State *s = ARM_SMMUV3(obj);
SMMUv3Class *c = ARM_SMMUV3_GET_CLASS(s);
if (c->parent_phases.hold) {
- c->parent_phases.hold(obj);
+ c->parent_phases.hold(obj, type);
}
smmuv3_init_regs(s);
diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
index a2f998b..3767462 100644
--- a/hw/arm/stellaris.c
+++ b/hw/arm/stellaris.c
@@ -394,7 +394,7 @@
s->dcgc[0] = 1;
}
-static void stellaris_sys_reset_hold(Object *obj)
+static void stellaris_sys_reset_hold(Object *obj, ResetType type)
{
ssys_state *s = STELLARIS_SYS(obj);
@@ -402,7 +402,7 @@
ssys_calculate_system_clock(s, true);
}
-static void stellaris_sys_reset_exit(Object *obj)
+static void stellaris_sys_reset_exit(Object *obj, ResetType type)
{
}
@@ -618,7 +618,7 @@
i2c_end_transfer(s->bus);
}
-static void stellaris_i2c_reset_hold(Object *obj)
+static void stellaris_i2c_reset_hold(Object *obj, ResetType type)
{
stellaris_i2c_state *s = STELLARIS_I2C(obj);
@@ -631,7 +631,7 @@
s->mcr = 0;
}
-static void stellaris_i2c_reset_exit(Object *obj)
+static void stellaris_i2c_reset_exit(Object *obj, ResetType type)
{
stellaris_i2c_state *s = STELLARIS_I2C(obj);
@@ -787,7 +787,7 @@
}
}
-static void stellaris_adc_reset_hold(Object *obj)
+static void stellaris_adc_reset_hold(Object *obj, ResetType type)
{
StellarisADCState *s = STELLARIS_ADC(obj);
int n;
diff --git a/hw/arm/stm32l4x5_soc.c b/hw/arm/stm32l4x5_soc.c
index 40e294f..3992482 100644
--- a/hw/arm/stm32l4x5_soc.c
+++ b/hw/arm/stm32l4x5_soc.c
@@ -28,6 +28,7 @@
#include "sysemu/sysemu.h"
#include "hw/or-irq.h"
#include "hw/arm/stm32l4x5_soc.h"
+#include "hw/char/stm32l4x5_usart.h"
#include "hw/gpio/stm32l4x5_gpio.h"
#include "hw/qdev-clock.h"
#include "hw/misc/unimp.h"
@@ -116,6 +117,22 @@
{ 0x48001C00, 0x0000000F, 0x00000000, 0x00000000 },
};
+static const hwaddr usart_addr[] = {
+ 0x40013800, /* "USART1", 0x400 */
+ 0x40004400, /* "USART2", 0x400 */
+ 0x40004800, /* "USART3", 0x400 */
+};
+static const hwaddr uart_addr[] = {
+ 0x40004C00, /* "UART4" , 0x400 */
+ 0x40005000 /* "UART5" , 0x400 */
+};
+
+#define LPUART_BASE_ADDRESS 0x40008000
+
+static const int usart_irq[] = { 37, 38, 39 };
+static const int uart_irq[] = { 52, 53 };
+#define LPUART_IRQ 70
+
static void stm32l4x5_soc_initfn(Object *obj)
{
Stm32l4x5SocState *s = STM32L4X5_SOC(obj);
@@ -132,6 +149,18 @@
g_autofree char *name = g_strdup_printf("gpio%c", 'a' + i);
object_initialize_child(obj, name, &s->gpio[i], TYPE_STM32L4X5_GPIO);
}
+
+ for (int i = 0; i < STM_NUM_USARTS; i++) {
+ object_initialize_child(obj, "usart[*]", &s->usart[i],
+ TYPE_STM32L4X5_USART);
+ }
+
+ for (int i = 0; i < STM_NUM_UARTS; i++) {
+ object_initialize_child(obj, "uart[*]", &s->uart[i],
+ TYPE_STM32L4X5_UART);
+ }
+ object_initialize_child(obj, "lpuart1", &s->lpuart,
+ TYPE_STM32L4X5_LPUART);
}
static void stm32l4x5_soc_realize(DeviceState *dev_soc, Error **errp)
@@ -279,6 +308,54 @@
sysbus_mmio_map(busdev, 0, RCC_BASE_ADDRESS);
sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, RCC_IRQ));
+ /* USART devices */
+ for (int i = 0; i < STM_NUM_USARTS; i++) {
+ g_autofree char *name = g_strdup_printf("usart%d-out", i + 1);
+ dev = DEVICE(&(s->usart[i]));
+ qdev_prop_set_chr(dev, "chardev", serial_hd(i));
+ qdev_connect_clock_in(dev, "clk",
+ qdev_get_clock_out(DEVICE(&(s->rcc)), name));
+ busdev = SYS_BUS_DEVICE(dev);
+ if (!sysbus_realize(busdev, errp)) {
+ return;
+ }
+ sysbus_mmio_map(busdev, 0, usart_addr[i]);
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, usart_irq[i]));
+ }
+
+ /*
+ * TODO: Connect the USARTs, UARTs and LPUART to the EXTI once the EXTI
+ * can handle other gpio-in than the gpios. (e.g. Direct Lines for the
+ * usarts)
+ */
+
+ /* UART devices */
+ for (int i = 0; i < STM_NUM_UARTS; i++) {
+ g_autofree char *name = g_strdup_printf("uart%d-out", STM_NUM_USARTS + i + 1);
+ dev = DEVICE(&(s->uart[i]));
+ qdev_prop_set_chr(dev, "chardev", serial_hd(STM_NUM_USARTS + i));
+ qdev_connect_clock_in(dev, "clk",
+ qdev_get_clock_out(DEVICE(&(s->rcc)), name));
+ busdev = SYS_BUS_DEVICE(dev);
+ if (!sysbus_realize(busdev, errp)) {
+ return;
+ }
+ sysbus_mmio_map(busdev, 0, uart_addr[i]);
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, uart_irq[i]));
+ }
+
+ /* LPUART device*/
+ dev = DEVICE(&(s->lpuart));
+ qdev_prop_set_chr(dev, "chardev", serial_hd(STM_NUM_USARTS + STM_NUM_UARTS));
+ qdev_connect_clock_in(dev, "clk",
+ qdev_get_clock_out(DEVICE(&(s->rcc)), "lpuart1-out"));
+ busdev = SYS_BUS_DEVICE(dev);
+ if (!sysbus_realize(busdev, errp)) {
+ return;
+ }
+ sysbus_mmio_map(busdev, 0, LPUART_BASE_ADDRESS);
+ sysbus_connect_irq(busdev, 0, qdev_get_gpio_in(armv7m, LPUART_IRQ));
+
/* APB1 BUS */
create_unimplemented_device("TIM2", 0x40000000, 0x400);
create_unimplemented_device("TIM3", 0x40000400, 0x400);
@@ -294,10 +371,6 @@
create_unimplemented_device("SPI2", 0x40003800, 0x400);
create_unimplemented_device("SPI3", 0x40003C00, 0x400);
/* RESERVED: 0x40004000, 0x400 */
- create_unimplemented_device("USART2", 0x40004400, 0x400);
- create_unimplemented_device("USART3", 0x40004800, 0x400);
- create_unimplemented_device("UART4", 0x40004C00, 0x400);
- create_unimplemented_device("UART5", 0x40005000, 0x400);
create_unimplemented_device("I2C1", 0x40005400, 0x400);
create_unimplemented_device("I2C2", 0x40005800, 0x400);
create_unimplemented_device("I2C3", 0x40005C00, 0x400);
@@ -308,7 +381,6 @@
create_unimplemented_device("DAC1", 0x40007400, 0x400);
create_unimplemented_device("OPAMP", 0x40007800, 0x400);
create_unimplemented_device("LPTIM1", 0x40007C00, 0x400);
- create_unimplemented_device("LPUART1", 0x40008000, 0x400);
/* RESERVED: 0x40008400, 0x400 */
create_unimplemented_device("SWPMI1", 0x40008800, 0x400);
/* RESERVED: 0x40008C00, 0x800 */
@@ -325,7 +397,6 @@
create_unimplemented_device("TIM1", 0x40012C00, 0x400);
create_unimplemented_device("SPI1", 0x40013000, 0x400);
create_unimplemented_device("TIM8", 0x40013400, 0x400);
- create_unimplemented_device("USART1", 0x40013800, 0x400);
/* RESERVED: 0x40013C00, 0x400 */
create_unimplemented_device("TIM15", 0x40014000, 0x400);
create_unimplemented_device("TIM16", 0x40014400, 0x400);
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index c9119ef..3c93c0c 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -729,6 +729,20 @@
vms->msi_controller = VIRT_MSI_CTRL_GICV2M;
}
+/*
+ * If the CPU has FEAT_NMI, then turn on the NMI support in the GICv3 too.
+ * It's permitted to have a configuration with NMI in the CPU (and thus the
+ * GICv3 CPU interface) but not in the distributor/redistributors, but it's
+ * not very useful.
+ */
+static bool gicv3_nmi_present(VirtMachineState *vms)
+{
+ ARMCPU *cpu = ARM_CPU(qemu_get_cpu(0));
+
+ return tcg_enabled() && cpu_isar_feature(aa64_nmi, cpu) &&
+ (vms->gic_version != VIRT_GIC_VERSION_2);
+}
+
static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
{
MachineState *ms = MACHINE(vms);
@@ -802,6 +816,11 @@
vms->virt);
}
}
+
+ if (gicv3_nmi_present(vms)) {
+ qdev_prop_set_bit(vms->gic, "has-nmi", true);
+ }
+
gicbusdev = SYS_BUS_DEVICE(vms->gic);
sysbus_realize_and_unref(gicbusdev, &error_fatal);
sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);
@@ -821,7 +840,8 @@
/* Wire the outputs from each CPU's generic timer and the GICv3
* maintenance interrupt signal to the appropriate GIC PPI inputs,
- * and the GIC's IRQ/FIQ/VIRQ/VFIQ interrupt outputs to the CPU's inputs.
+ * and the GIC's IRQ/FIQ/VIRQ/VFIQ/NMI/VINMI interrupt outputs to the
+ * CPU's inputs.
*/
for (i = 0; i < smp_cpus; i++) {
DeviceState *cpudev = DEVICE(qemu_get_cpu(i));
@@ -865,6 +885,13 @@
qdev_get_gpio_in(cpudev, ARM_CPU_VIRQ));
sysbus_connect_irq(gicbusdev, i + 3 * smp_cpus,
qdev_get_gpio_in(cpudev, ARM_CPU_VFIQ));
+
+ if (vms->gic_version != VIRT_GIC_VERSION_2) {
+ sysbus_connect_irq(gicbusdev, i + 4 * smp_cpus,
+ qdev_get_gpio_in(cpudev, ARM_CPU_NMI));
+ sysbus_connect_irq(gicbusdev, i + 5 * smp_cpus,
+ qdev_get_gpio_in(cpudev, ARM_CPU_VINMI));
+ }
}
fdt_add_gic_node(vms);
diff --git a/hw/audio/asc.c b/hw/audio/asc.c
index 87b5624..8054163 100644
--- a/hw/audio/asc.c
+++ b/hw/audio/asc.c
@@ -610,7 +610,7 @@
g_free(name);
}
-static void asc_reset_hold(Object *obj)
+static void asc_reset_hold(Object *obj, ResetType type)
{
ASCState *s = ASC(obj);
diff --git a/hw/char/Kconfig b/hw/char/Kconfig
index 6b6cf2f..4fd74ea 100644
--- a/hw/char/Kconfig
+++ b/hw/char/Kconfig
@@ -41,6 +41,9 @@
config STM32F2XX_USART
bool
+config STM32L4X5_USART
+ bool
+
config CMSDK_APB_UART
bool
diff --git a/hw/char/cadence_uart.c b/hw/char/cadence_uart.c
index db31d7c..77d9a2a 100644
--- a/hw/char/cadence_uart.c
+++ b/hw/char/cadence_uart.c
@@ -525,7 +525,7 @@
s->r[R_TTRIG] = 0x00000020;
}
-static void cadence_uart_reset_hold(Object *obj)
+static void cadence_uart_reset_hold(Object *obj, ResetType type)
{
CadenceUARTState *s = CADENCE_UART(obj);
diff --git a/hw/char/meson.build b/hw/char/meson.build
index 006d20f..e5b13b6 100644
--- a/hw/char/meson.build
+++ b/hw/char/meson.build
@@ -31,6 +31,7 @@
system_ss.add(when: 'CONFIG_SIFIVE_UART', if_true: files('sifive_uart.c'))
system_ss.add(when: 'CONFIG_SH_SCI', if_true: files('sh_serial.c'))
system_ss.add(when: 'CONFIG_STM32F2XX_USART', if_true: files('stm32f2xx_usart.c'))
+system_ss.add(when: 'CONFIG_STM32L4X5_USART', if_true: files('stm32l4x5_usart.c'))
system_ss.add(when: 'CONFIG_MCHP_PFSOC_MMUART', if_true: files('mchp_pfsoc_mmuart.c'))
system_ss.add(when: 'CONFIG_HTIF', if_true: files('riscv_htif.c'))
system_ss.add(when: 'CONFIG_GOLDFISH_TTY', if_true: files('goldfish_tty.c'))
diff --git a/hw/char/sifive_uart.c b/hw/char/sifive_uart.c
index e8716c4..7fc6787 100644
--- a/hw/char/sifive_uart.c
+++ b/hw/char/sifive_uart.c
@@ -214,7 +214,7 @@
s->rx_fifo_len = 0;
}
-static void sifive_uart_reset_hold(Object *obj)
+static void sifive_uart_reset_hold(Object *obj, ResetType type)
{
SiFiveUARTState *s = SIFIVE_UART(obj);
qemu_irq_lower(s->irq);
diff --git a/hw/char/stm32l4x5_usart.c b/hw/char/stm32l4x5_usart.c
new file mode 100644
index 0000000..2627aab
--- /dev/null
+++ b/hw/char/stm32l4x5_usart.c
@@ -0,0 +1,637 @@
+/*
+ * STM32L4X5 USART (Universal Synchronous Asynchronous Receiver Transmitter)
+ *
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * The STM32L4X5 USART is heavily inspired by the stm32f2xx_usart
+ * by Alistair Francis.
+ * The reference used is the STMicroElectronics RM0351 Reference manual
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qapi/error.h"
+#include "chardev/char-fe.h"
+#include "chardev/char-serial.h"
+#include "migration/vmstate.h"
+#include "hw/char/stm32l4x5_usart.h"
+#include "hw/clock.h"
+#include "hw/irq.h"
+#include "hw/qdev-clock.h"
+#include "hw/qdev-properties.h"
+#include "hw/qdev-properties-system.h"
+#include "hw/registerfields.h"
+#include "trace.h"
+
+
+REG32(CR1, 0x00)
+ FIELD(CR1, M1, 28, 1) /* Word length (part 2, see M0) */
+ FIELD(CR1, EOBIE, 27, 1) /* End of Block interrupt enable */
+ FIELD(CR1, RTOIE, 26, 1) /* Receiver timeout interrupt enable */
+ FIELD(CR1, DEAT, 21, 5) /* Driver Enable assertion time */
+ FIELD(CR1, DEDT, 16, 5) /* Driver Enable de-assertion time */
+ FIELD(CR1, OVER8, 15, 1) /* Oversampling mode */
+ FIELD(CR1, CMIE, 14, 1) /* Character match interrupt enable */
+ FIELD(CR1, MME, 13, 1) /* Mute mode enable */
+ FIELD(CR1, M0, 12, 1) /* Word length (part 1, see M1) */
+ FIELD(CR1, WAKE, 11, 1) /* Receiver wakeup method */
+ FIELD(CR1, PCE, 10, 1) /* Parity control enable */
+ FIELD(CR1, PS, 9, 1) /* Parity selection */
+ FIELD(CR1, PEIE, 8, 1) /* PE interrupt enable */
+ FIELD(CR1, TXEIE, 7, 1) /* TXE interrupt enable */
+ FIELD(CR1, TCIE, 6, 1) /* Transmission complete interrupt enable */
+ FIELD(CR1, RXNEIE, 5, 1) /* RXNE interrupt enable */
+ FIELD(CR1, IDLEIE, 4, 1) /* IDLE interrupt enable */
+ FIELD(CR1, TE, 3, 1) /* Transmitter enable */
+ FIELD(CR1, RE, 2, 1) /* Receiver enable */
+ FIELD(CR1, UESM, 1, 1) /* USART enable in Stop mode */
+ FIELD(CR1, UE, 0, 1) /* USART enable */
+REG32(CR2, 0x04)
+ FIELD(CR2, ADD_1, 28, 4) /* ADD[7:4] */
+ FIELD(CR2, ADD_0, 24, 1) /* ADD[3:0] */
+ FIELD(CR2, RTOEN, 23, 1) /* Receiver timeout enable */
+ FIELD(CR2, ABRMOD, 21, 2) /* Auto baud rate mode */
+ FIELD(CR2, ABREN, 20, 1) /* Auto baud rate enable */
+ FIELD(CR2, MSBFIRST, 19, 1) /* Most significant bit first */
+ FIELD(CR2, DATAINV, 18, 1) /* Binary data inversion */
+ FIELD(CR2, TXINV, 17, 1) /* TX pin active level inversion */
+ FIELD(CR2, RXINV, 16, 1) /* RX pin active level inversion */
+ FIELD(CR2, SWAP, 15, 1) /* Swap RX/TX pins */
+ FIELD(CR2, LINEN, 14, 1) /* LIN mode enable */
+ FIELD(CR2, STOP, 12, 2) /* STOP bits */
+ FIELD(CR2, CLKEN, 11, 1) /* Clock enable */
+ FIELD(CR2, CPOL, 10, 1) /* Clock polarity */
+ FIELD(CR2, CPHA, 9, 1) /* Clock phase */
+ FIELD(CR2, LBCL, 8, 1) /* Last bit clock pulse */
+ FIELD(CR2, LBDIE, 6, 1) /* LIN break detection interrupt enable */
+ FIELD(CR2, LBDL, 5, 1) /* LIN break detection length */
+ FIELD(CR2, ADDM7, 4, 1) /* 7-bit / 4-bit Address Detection */
+
+REG32(CR3, 0x08)
+ /* TCBGTIE only on STM32L496xx/4A6xx devices */
+ FIELD(CR3, UCESM, 23, 1) /* USART Clock Enable in Stop Mode */
+ FIELD(CR3, WUFIE, 22, 1) /* Wakeup from Stop mode interrupt enable */
+ FIELD(CR3, WUS, 20, 2) /* Wakeup from Stop mode interrupt flag selection */
+ FIELD(CR3, SCARCNT, 17, 3) /* Smartcard auto-retry count */
+ FIELD(CR3, DEP, 15, 1) /* Driver enable polarity selection */
+ FIELD(CR3, DEM, 14, 1) /* Driver enable mode */
+ FIELD(CR3, DDRE, 13, 1) /* DMA Disable on Reception Error */
+ FIELD(CR3, OVRDIS, 12, 1) /* Overrun Disable */
+ FIELD(CR3, ONEBIT, 11, 1) /* One sample bit method enable */
+ FIELD(CR3, CTSIE, 10, 1) /* CTS interrupt enable */
+ FIELD(CR3, CTSE, 9, 1) /* CTS enable */
+ FIELD(CR3, RTSE, 8, 1) /* RTS enable */
+ FIELD(CR3, DMAT, 7, 1) /* DMA enable transmitter */
+ FIELD(CR3, DMAR, 6, 1) /* DMA enable receiver */
+ FIELD(CR3, SCEN, 5, 1) /* Smartcard mode enable */
+ FIELD(CR3, NACK, 4, 1) /* Smartcard NACK enable */
+ FIELD(CR3, HDSEL, 3, 1) /* Half-duplex selection */
+ FIELD(CR3, IRLP, 2, 1) /* IrDA low-power */
+ FIELD(CR3, IREN, 1, 1) /* IrDA mode enable */
+ FIELD(CR3, EIE, 0, 1) /* Error interrupt enable */
+REG32(BRR, 0x0C)
+ FIELD(BRR, BRR, 0, 16)
+REG32(GTPR, 0x10)
+ FIELD(GTPR, GT, 8, 8) /* Guard time value */
+ FIELD(GTPR, PSC, 0, 8) /* Prescaler value */
+REG32(RTOR, 0x14)
+ FIELD(RTOR, BLEN, 24, 8) /* Block Length */
+ FIELD(RTOR, RTO, 0, 24) /* Receiver timeout value */
+REG32(RQR, 0x18)
+ FIELD(RQR, TXFRQ, 4, 1) /* Transmit data flush request */
+ FIELD(RQR, RXFRQ, 3, 1) /* Receive data flush request */
+ FIELD(RQR, MMRQ, 2, 1) /* Mute mode request */
+ FIELD(RQR, SBKRQ, 1, 1) /* Send break request */
+ FIELD(RQR, ABBRRQ, 0, 1) /* Auto baud rate request */
+REG32(ISR, 0x1C)
+ /* TCBGT only for STM32L475xx/476xx/486xx devices */
+ FIELD(ISR, REACK, 22, 1) /* Receive enable acknowledge flag */
+ FIELD(ISR, TEACK, 21, 1) /* Transmit enable acknowledge flag */
+ FIELD(ISR, WUF, 20, 1) /* Wakeup from Stop mode flag */
+ FIELD(ISR, RWU, 19, 1) /* Receiver wakeup from Mute mode */
+ FIELD(ISR, SBKF, 18, 1) /* Send break flag */
+ FIELD(ISR, CMF, 17, 1) /* Character match flag */
+ FIELD(ISR, BUSY, 16, 1) /* Busy flag */
+ FIELD(ISR, ABRF, 15, 1) /* Auto Baud rate flag */
+ FIELD(ISR, ABRE, 14, 1) /* Auto Baud rate error */
+ FIELD(ISR, EOBF, 12, 1) /* End of block flag */
+ FIELD(ISR, RTOF, 11, 1) /* Receiver timeout */
+ FIELD(ISR, CTS, 10, 1) /* CTS flag */
+ FIELD(ISR, CTSIF, 9, 1) /* CTS interrupt flag */
+ FIELD(ISR, LBDF, 8, 1) /* LIN break detection flag */
+ FIELD(ISR, TXE, 7, 1) /* Transmit data register empty */
+ FIELD(ISR, TC, 6, 1) /* Transmission complete */
+ FIELD(ISR, RXNE, 5, 1) /* Read data register not empty */
+ FIELD(ISR, IDLE, 4, 1) /* Idle line detected */
+ FIELD(ISR, ORE, 3, 1) /* Overrun error */
+ FIELD(ISR, NF, 2, 1) /* START bit Noise detection flag */
+ FIELD(ISR, FE, 1, 1) /* Framing Error */
+ FIELD(ISR, PE, 0, 1) /* Parity Error */
+REG32(ICR, 0x20)
+ FIELD(ICR, WUCF, 20, 1) /* Wakeup from Stop mode clear flag */
+ FIELD(ICR, CMCF, 17, 1) /* Character match clear flag */
+ FIELD(ICR, EOBCF, 12, 1) /* End of block clear flag */
+ FIELD(ICR, RTOCF, 11, 1) /* Receiver timeout clear flag */
+ FIELD(ICR, CTSCF, 9, 1) /* CTS clear flag */
+ FIELD(ICR, LBDCF, 8, 1) /* LIN break detection clear flag */
+ /* TCBGTCF only on STM32L496xx/4A6xx devices */
+ FIELD(ICR, TCCF, 6, 1) /* Transmission complete clear flag */
+ FIELD(ICR, IDLECF, 4, 1) /* Idle line detected clear flag */
+ FIELD(ICR, ORECF, 3, 1) /* Overrun error clear flag */
+ FIELD(ICR, NCF, 2, 1) /* Noise detected clear flag */
+ FIELD(ICR, FECF, 1, 1) /* Framing error clear flag */
+ FIELD(ICR, PECF, 0, 1) /* Parity error clear flag */
+REG32(RDR, 0x24)
+ FIELD(RDR, RDR, 0, 9)
+REG32(TDR, 0x28)
+ FIELD(TDR, TDR, 0, 9)
+
+static void stm32l4x5_update_irq(Stm32l4x5UsartBaseState *s)
+{
+ if (((s->isr & R_ISR_WUF_MASK) && (s->cr3 & R_CR3_WUFIE_MASK)) ||
+ ((s->isr & R_ISR_CMF_MASK) && (s->cr1 & R_CR1_CMIE_MASK)) ||
+ ((s->isr & R_ISR_ABRF_MASK) && (s->cr1 & R_CR1_RXNEIE_MASK)) ||
+ ((s->isr & R_ISR_EOBF_MASK) && (s->cr1 & R_CR1_EOBIE_MASK)) ||
+ ((s->isr & R_ISR_RTOF_MASK) && (s->cr1 & R_CR1_RTOIE_MASK)) ||
+ ((s->isr & R_ISR_CTSIF_MASK) && (s->cr3 & R_CR3_CTSIE_MASK)) ||
+ ((s->isr & R_ISR_LBDF_MASK) && (s->cr2 & R_CR2_LBDIE_MASK)) ||
+ ((s->isr & R_ISR_TXE_MASK) && (s->cr1 & R_CR1_TXEIE_MASK)) ||
+ ((s->isr & R_ISR_TC_MASK) && (s->cr1 & R_CR1_TCIE_MASK)) ||
+ ((s->isr & R_ISR_RXNE_MASK) && (s->cr1 & R_CR1_RXNEIE_MASK)) ||
+ ((s->isr & R_ISR_IDLE_MASK) && (s->cr1 & R_CR1_IDLEIE_MASK)) ||
+ ((s->isr & R_ISR_ORE_MASK) &&
+ ((s->cr1 & R_CR1_RXNEIE_MASK) || (s->cr3 & R_CR3_EIE_MASK))) ||
+ /* TODO: Handle NF ? */
+ ((s->isr & R_ISR_FE_MASK) && (s->cr3 & R_CR3_EIE_MASK)) ||
+ ((s->isr & R_ISR_PE_MASK) && (s->cr1 & R_CR1_PEIE_MASK))) {
+ qemu_irq_raise(s->irq);
+ trace_stm32l4x5_usart_irq_raised(s->isr);
+ } else {
+ qemu_irq_lower(s->irq);
+ trace_stm32l4x5_usart_irq_lowered();
+ }
+}
+
+static int stm32l4x5_usart_base_can_receive(void *opaque)
+{
+ Stm32l4x5UsartBaseState *s = opaque;
+
+ if (!(s->isr & R_ISR_RXNE_MASK)) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static void stm32l4x5_usart_base_receive(void *opaque, const uint8_t *buf,
+ int size)
+{
+ Stm32l4x5UsartBaseState *s = opaque;
+
+ if (!((s->cr1 & R_CR1_UE_MASK) && (s->cr1 & R_CR1_RE_MASK))) {
+ trace_stm32l4x5_usart_receiver_not_enabled(
+ FIELD_EX32(s->cr1, CR1, UE), FIELD_EX32(s->cr1, CR1, RE));
+ return;
+ }
+
+ /* Check if overrun detection is enabled and if there is an overrun */
+ if (!(s->cr3 & R_CR3_OVRDIS_MASK) && (s->isr & R_ISR_RXNE_MASK)) {
+ /*
+ * A character has been received while
+ * the previous has not been read = Overrun.
+ */
+ s->isr |= R_ISR_ORE_MASK;
+ trace_stm32l4x5_usart_overrun_detected(s->rdr, *buf);
+ } else {
+ /* No overrun */
+ s->rdr = *buf;
+ s->isr |= R_ISR_RXNE_MASK;
+ trace_stm32l4x5_usart_rx(s->rdr);
+ }
+
+ stm32l4x5_update_irq(s);
+}
+
+/*
+ * Try to send tx data, and arrange to be called back later if
+ * we can't (ie the char backend is busy/blocking).
+ */
+static gboolean usart_transmit(void *do_not_use, GIOCondition cond,
+ void *opaque)
+{
+ Stm32l4x5UsartBaseState *s = STM32L4X5_USART_BASE(opaque);
+ int ret;
+ /* TODO: Handle 9 bits transmission */
+ uint8_t ch = s->tdr;
+
+ s->watch_tag = 0;
+
+ if (!(s->cr1 & R_CR1_TE_MASK) || (s->isr & R_ISR_TXE_MASK)) {
+ return G_SOURCE_REMOVE;
+ }
+
+ ret = qemu_chr_fe_write(&s->chr, &ch, 1);
+ if (ret <= 0) {
+ s->watch_tag = qemu_chr_fe_add_watch(&s->chr, G_IO_OUT | G_IO_HUP,
+ usart_transmit, s);
+ if (!s->watch_tag) {
+ /*
+ * Most common reason to be here is "no chardev backend":
+ * just insta-drain the buffer, so the serial output
+ * goes into a void, rather than blocking the guest.
+ */
+ goto buffer_drained;
+ }
+ /* Transmit pending */
+ trace_stm32l4x5_usart_tx_pending();
+ return G_SOURCE_REMOVE;
+ }
+
+buffer_drained:
+ /* Character successfully sent */
+ trace_stm32l4x5_usart_tx(ch);
+ s->isr |= R_ISR_TC_MASK | R_ISR_TXE_MASK;
+ stm32l4x5_update_irq(s);
+ return G_SOURCE_REMOVE;
+}
+
+static void usart_cancel_transmit(Stm32l4x5UsartBaseState *s)
+{
+ if (s->watch_tag) {
+ g_source_remove(s->watch_tag);
+ s->watch_tag = 0;
+ }
+}
+
+static void stm32l4x5_update_params(Stm32l4x5UsartBaseState *s)
+{
+ int speed, parity, data_bits, stop_bits;
+ uint32_t value, usart_div;
+ QEMUSerialSetParams ssp;
+
+ /* Select the parity type */
+ if (s->cr1 & R_CR1_PCE_MASK) {
+ if (s->cr1 & R_CR1_PS_MASK) {
+ parity = 'O';
+ } else {
+ parity = 'E';
+ }
+ } else {
+ parity = 'N';
+ }
+
+ /* Select the number of stop bits */
+ switch (FIELD_EX32(s->cr2, CR2, STOP)) {
+ case 0:
+ stop_bits = 1;
+ break;
+ case 2:
+ stop_bits = 2;
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP,
+ "UNIMPLEMENTED: fractionnal stop bits; CR2[13:12] = %u",
+ FIELD_EX32(s->cr2, CR2, STOP));
+ return;
+ }
+
+ /* Select the length of the word */
+ switch ((FIELD_EX32(s->cr1, CR1, M1) << 1) | FIELD_EX32(s->cr1, CR1, M0)) {
+ case 0:
+ data_bits = 8;
+ break;
+ case 1:
+ data_bits = 9;
+ break;
+ case 2:
+ data_bits = 7;
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "UNDEFINED: invalid word length, CR1.M = 0b11");
+ return;
+ }
+
+ /* Select the baud rate */
+ value = FIELD_EX32(s->brr, BRR, BRR);
+ if (value < 16) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "UNDEFINED: BRR less than 16: %u", value);
+ return;
+ }
+
+ if (FIELD_EX32(s->cr1, CR1, OVER8) == 0) {
+ /*
+ * Oversampling by 16
+ * BRR = USARTDIV
+ */
+ usart_div = value;
+ } else {
+ /*
+ * Oversampling by 8
+ * - BRR[2:0] = USARTDIV[3:0] shifted 1 bit to the right.
+ * - BRR[3] must be kept cleared.
+ * - BRR[15:4] = USARTDIV[15:4]
+ * - The frequency is multiplied by 2
+ */
+ usart_div = ((value & 0xFFF0) | ((value & 0x0007) << 1)) / 2;
+ }
+
+ speed = clock_get_hz(s->clk) / usart_div;
+
+ ssp.speed = speed;
+ ssp.parity = parity;
+ ssp.data_bits = data_bits;
+ ssp.stop_bits = stop_bits;
+
+ qemu_chr_fe_ioctl(&s->chr, CHR_IOCTL_SERIAL_SET_PARAMS, &ssp);
+
+ trace_stm32l4x5_usart_update_params(speed, parity, data_bits, stop_bits);
+}
+
+static void stm32l4x5_usart_base_reset_hold(Object *obj, ResetType type)
+{
+ Stm32l4x5UsartBaseState *s = STM32L4X5_USART_BASE(obj);
+
+ s->cr1 = 0x00000000;
+ s->cr2 = 0x00000000;
+ s->cr3 = 0x00000000;
+ s->brr = 0x00000000;
+ s->gtpr = 0x00000000;
+ s->rtor = 0x00000000;
+ s->isr = 0x020000C0;
+ s->rdr = 0x00000000;
+ s->tdr = 0x00000000;
+
+ usart_cancel_transmit(s);
+ stm32l4x5_update_irq(s);
+}
+
+static void usart_update_rqr(Stm32l4x5UsartBaseState *s, uint32_t value)
+{
+ /* TXFRQ */
+ /* Reset RXNE flag */
+ if (value & R_RQR_RXFRQ_MASK) {
+ s->isr &= ~R_ISR_RXNE_MASK;
+ }
+ /* MMRQ */
+ /* SBKRQ */
+ /* ABRRQ */
+ stm32l4x5_update_irq(s);
+}
+
+static uint64_t stm32l4x5_usart_base_read(void *opaque, hwaddr addr,
+ unsigned int size)
+{
+ Stm32l4x5UsartBaseState *s = opaque;
+ uint64_t retvalue = 0;
+
+ switch (addr) {
+ case A_CR1:
+ retvalue = s->cr1;
+ break;
+ case A_CR2:
+ retvalue = s->cr2;
+ break;
+ case A_CR3:
+ retvalue = s->cr3;
+ break;
+ case A_BRR:
+ retvalue = FIELD_EX32(s->brr, BRR, BRR);
+ break;
+ case A_GTPR:
+ retvalue = s->gtpr;
+ break;
+ case A_RTOR:
+ retvalue = s->rtor;
+ break;
+ case A_RQR:
+ /* RQR is a write only register */
+ retvalue = 0x00000000;
+ break;
+ case A_ISR:
+ retvalue = s->isr;
+ break;
+ case A_ICR:
+ /* ICR is a clear register */
+ retvalue = 0x00000000;
+ break;
+ case A_RDR:
+ retvalue = FIELD_EX32(s->rdr, RDR, RDR);
+ /* Reset RXNE flag */
+ s->isr &= ~R_ISR_RXNE_MASK;
+ stm32l4x5_update_irq(s);
+ break;
+ case A_TDR:
+ retvalue = FIELD_EX32(s->tdr, TDR, TDR);
+ break;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
+ break;
+ }
+
+ trace_stm32l4x5_usart_read(addr, retvalue);
+
+ return retvalue;
+}
+
+static void stm32l4x5_usart_base_write(void *opaque, hwaddr addr,
+ uint64_t val64, unsigned int size)
+{
+ Stm32l4x5UsartBaseState *s = opaque;
+ const uint32_t value = val64;
+
+ trace_stm32l4x5_usart_write(addr, value);
+
+ switch (addr) {
+ case A_CR1:
+ s->cr1 = value;
+ stm32l4x5_update_params(s);
+ stm32l4x5_update_irq(s);
+ return;
+ case A_CR2:
+ s->cr2 = value;
+ stm32l4x5_update_params(s);
+ return;
+ case A_CR3:
+ s->cr3 = value;
+ return;
+ case A_BRR:
+ s->brr = value;
+ stm32l4x5_update_params(s);
+ return;
+ case A_GTPR:
+ s->gtpr = value;
+ return;
+ case A_RTOR:
+ s->rtor = value;
+ return;
+ case A_RQR:
+ usart_update_rqr(s, value);
+ return;
+ case A_ISR:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: ISR is read only !\n", __func__);
+ return;
+ case A_ICR:
+ /* Clear the status flags */
+ s->isr &= ~value;
+ stm32l4x5_update_irq(s);
+ return;
+ case A_RDR:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: RDR is read only !\n", __func__);
+ return;
+ case A_TDR:
+ s->tdr = value;
+ s->isr &= ~R_ISR_TXE_MASK;
+ usart_transmit(NULL, G_IO_OUT, s);
+ return;
+ default:
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "%s: Bad offset 0x%"HWADDR_PRIx"\n", __func__, addr);
+ }
+}
+
+static const MemoryRegionOps stm32l4x5_usart_base_ops = {
+ .read = stm32l4x5_usart_base_read,
+ .write = stm32l4x5_usart_base_write,
+ .endianness = DEVICE_NATIVE_ENDIAN,
+ .valid = {
+ .max_access_size = 4,
+ .min_access_size = 4,
+ .unaligned = false
+ },
+ .impl = {
+ .max_access_size = 4,
+ .min_access_size = 4,
+ .unaligned = false
+ },
+};
+
+static Property stm32l4x5_usart_base_properties[] = {
+ DEFINE_PROP_CHR("chardev", Stm32l4x5UsartBaseState, chr),
+ DEFINE_PROP_END_OF_LIST(),
+};
+
+static void stm32l4x5_usart_base_init(Object *obj)
+{
+ Stm32l4x5UsartBaseState *s = STM32L4X5_USART_BASE(obj);
+
+ sysbus_init_irq(SYS_BUS_DEVICE(obj), &s->irq);
+
+ memory_region_init_io(&s->mmio, obj, &stm32l4x5_usart_base_ops, s,
+ TYPE_STM32L4X5_USART_BASE, 0x400);
+ sysbus_init_mmio(SYS_BUS_DEVICE(obj), &s->mmio);
+
+ s->clk = qdev_init_clock_in(DEVICE(s), "clk", NULL, s, 0);
+}
+
+static int stm32l4x5_usart_base_post_load(void *opaque, int version_id)
+{
+ Stm32l4x5UsartBaseState *s = (Stm32l4x5UsartBaseState *)opaque;
+
+ stm32l4x5_update_params(s);
+ return 0;
+}
+
+static const VMStateDescription vmstate_stm32l4x5_usart_base = {
+ .name = TYPE_STM32L4X5_USART_BASE,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .post_load = stm32l4x5_usart_base_post_load,
+ .fields = (VMStateField[]) {
+ VMSTATE_UINT32(cr1, Stm32l4x5UsartBaseState),
+ VMSTATE_UINT32(cr2, Stm32l4x5UsartBaseState),
+ VMSTATE_UINT32(cr3, Stm32l4x5UsartBaseState),
+ VMSTATE_UINT32(brr, Stm32l4x5UsartBaseState),
+ VMSTATE_UINT32(gtpr, Stm32l4x5UsartBaseState),
+ VMSTATE_UINT32(rtor, Stm32l4x5UsartBaseState),
+ VMSTATE_UINT32(isr, Stm32l4x5UsartBaseState),
+ VMSTATE_UINT32(rdr, Stm32l4x5UsartBaseState),
+ VMSTATE_UINT32(tdr, Stm32l4x5UsartBaseState),
+ VMSTATE_CLOCK(clk, Stm32l4x5UsartBaseState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
+
+static void stm32l4x5_usart_base_realize(DeviceState *dev, Error **errp)
+{
+ ERRP_GUARD();
+ Stm32l4x5UsartBaseState *s = STM32L4X5_USART_BASE(dev);
+ if (!clock_has_source(s->clk)) {
+ error_setg(errp, "USART clock must be wired up by SoC code");
+ return;
+ }
+
+ qemu_chr_fe_set_handlers(&s->chr, stm32l4x5_usart_base_can_receive,
+ stm32l4x5_usart_base_receive, NULL, NULL,
+ s, NULL, true);
+}
+
+static void stm32l4x5_usart_base_class_init(ObjectClass *klass, void *data)
+{
+ DeviceClass *dc = DEVICE_CLASS(klass);
+ ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+ rc->phases.hold = stm32l4x5_usart_base_reset_hold;
+ device_class_set_props(dc, stm32l4x5_usart_base_properties);
+ dc->realize = stm32l4x5_usart_base_realize;
+ dc->vmsd = &vmstate_stm32l4x5_usart_base;
+}
+
+static void stm32l4x5_usart_class_init(ObjectClass *oc, void *data)
+{
+ Stm32l4x5UsartBaseClass *subc = STM32L4X5_USART_BASE_CLASS(oc);
+
+ subc->type = STM32L4x5_USART;
+}
+
+static void stm32l4x5_uart_class_init(ObjectClass *oc, void *data)
+{
+ Stm32l4x5UsartBaseClass *subc = STM32L4X5_USART_BASE_CLASS(oc);
+
+ subc->type = STM32L4x5_UART;
+}
+
+static void stm32l4x5_lpuart_class_init(ObjectClass *oc, void *data)
+{
+ Stm32l4x5UsartBaseClass *subc = STM32L4X5_USART_BASE_CLASS(oc);
+
+ subc->type = STM32L4x5_LPUART;
+}
+
+static const TypeInfo stm32l4x5_usart_types[] = {
+ {
+ .name = TYPE_STM32L4X5_USART_BASE,
+ .parent = TYPE_SYS_BUS_DEVICE,
+ .instance_size = sizeof(Stm32l4x5UsartBaseState),
+ .instance_init = stm32l4x5_usart_base_init,
+ .class_init = stm32l4x5_usart_base_class_init,
+ .abstract = true,
+ }, {
+ .name = TYPE_STM32L4X5_USART,
+ .parent = TYPE_STM32L4X5_USART_BASE,
+ .class_init = stm32l4x5_usart_class_init,
+ }, {
+ .name = TYPE_STM32L4X5_UART,
+ .parent = TYPE_STM32L4X5_USART_BASE,
+ .class_init = stm32l4x5_uart_class_init,
+ }, {
+ .name = TYPE_STM32L4X5_LPUART,
+ .parent = TYPE_STM32L4X5_USART_BASE,
+ .class_init = stm32l4x5_lpuart_class_init,
+ }
+};
+
+DEFINE_TYPES(stm32l4x5_usart_types)
diff --git a/hw/char/trace-events b/hw/char/trace-events
index 7a398c8..8875758 100644
--- a/hw/char/trace-events
+++ b/hw/char/trace-events
@@ -106,6 +106,18 @@
sh_serial_read(char *id, unsigned size, uint64_t offs, uint64_t val) " %s size %d offs 0x%02" PRIx64 " -> 0x%02" PRIx64
sh_serial_write(char *id, unsigned size, uint64_t offs, uint64_t val) "%s size %d offs 0x%02" PRIx64 " <- 0x%02" PRIx64
+# stm32l4x5_usart.c
+stm32l4x5_usart_read(uint64_t addr, uint32_t data) "USART: Read <0x%" PRIx64 "> -> 0x%" PRIx32 ""
+stm32l4x5_usart_write(uint64_t addr, uint32_t data) "USART: Write <0x%" PRIx64 "> <- 0x%" PRIx32 ""
+stm32l4x5_usart_rx(uint8_t c) "USART: got character 0x%x from backend"
+stm32l4x5_usart_tx(uint8_t c) "USART: character 0x%x sent to backend"
+stm32l4x5_usart_tx_pending(void) "USART: character send to backend pending"
+stm32l4x5_usart_irq_raised(uint32_t reg) "USART: IRQ raised: 0x%08"PRIx32
+stm32l4x5_usart_irq_lowered(void) "USART: IRQ lowered"
+stm32l4x5_usart_overrun_detected(uint8_t current, uint8_t received) "USART: Overrun detected, RDR='0x%x', received 0x%x"
+stm32l4x5_usart_receiver_not_enabled(uint8_t ue_bit, uint8_t re_bit) "USART: Receiver not enabled, UE=0x%x, RE=0x%x"
+stm32l4x5_usart_update_params(int speed, uint8_t parity, int data, int stop) "USART: speed: %d, parity: %c, data bits: %d, stop bits: %d"
+
# xen_console.c
xen_console_connect(unsigned int idx, unsigned int ring_ref, unsigned int port, unsigned int limit) "idx %u ring_ref %u port %u limit %u"
xen_console_disconnect(unsigned int idx) "idx %u"
diff --git a/hw/core/cpu-common.c b/hw/core/cpu-common.c
index 4bd9c70..a72d48d 100644
--- a/hw/core/cpu-common.c
+++ b/hw/core/cpu-common.c
@@ -113,7 +113,7 @@
trace_cpu_reset(cpu->cpu_index);
}
-static void cpu_common_reset_hold(Object *obj)
+static void cpu_common_reset_hold(Object *obj, ResetType type)
{
CPUState *cpu = CPU(obj);
CPUClass *cc = CPU_GET_CLASS(cpu);
diff --git a/hw/core/loader.c b/hw/core/loader.c
index b8e52f3..2f8105d 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -305,7 +305,7 @@
#define elf_word uint32_t
#define elf_sword int32_t
#define bswapSZs bswap32s
-#include "hw/elf_ops.h"
+#include "hw/elf_ops.h.inc"
#undef elfhdr
#undef elf_phdr
@@ -327,7 +327,7 @@
#define elf_sword int64_t
#define bswapSZs bswap64s
#define SZ 64
-#include "hw/elf_ops.h"
+#include "hw/elf_ops.h.inc"
const char *load_elf_strerror(ssize_t error)
{
diff --git a/hw/core/machine-hmp-cmds.c b/hw/core/machine-hmp-cmds.c
index a6ff6a4..8701f00 100644
--- a/hw/core/machine-hmp-cmds.c
+++ b/hw/core/machine-hmp-cmds.c
@@ -87,6 +87,10 @@
monitor_printf(mon, " cluster-id: \"%" PRIu64 "\"\n",
c->cluster_id);
}
+ if (c->has_module_id) {
+ monitor_printf(mon, " module-id: \"%" PRIu64 "\"\n",
+ c->module_id);
+ }
if (c->has_core_id) {
monitor_printf(mon, " core-id: \"%" PRIu64 "\"\n", c->core_id);
}
diff --git a/hw/core/machine-qmp-cmds.c b/hw/core/machine-qmp-cmds.c
index c20829b..5972100 100644
--- a/hw/core/machine-qmp-cmds.c
+++ b/hw/core/machine-qmp-cmds.c
@@ -64,7 +64,8 @@
return head;
}
-MachineInfoList *qmp_query_machines(Error **errp)
+MachineInfoList *qmp_query_machines(bool has_compat_props, bool compat_props,
+ Error **errp)
{
GSList *el, *machines = object_class_get_list(TYPE_MACHINE, false);
MachineInfoList *mach_list = NULL;
@@ -96,6 +97,26 @@
info->default_ram_id = g_strdup(mc->default_ram_id);
}
+ if (compat_props && mc->compat_props) {
+ int i;
+ info->compat_props = NULL;
+ CompatPropertyList **tail = &(info->compat_props);
+ info->has_compat_props = true;
+
+ for (i = 0; i < mc->compat_props->len; i++) {
+ GlobalProperty *mt_prop = g_ptr_array_index(mc->compat_props,
+ i);
+ CompatProperty *prop;
+
+ prop = g_malloc0(sizeof(*prop));
+ prop->qom_type = g_strdup(mt_prop->driver);
+ prop->property = g_strdup(mt_prop->property);
+ prop->value = g_strdup(mt_prop->value);
+
+ QAPI_LIST_APPEND(tail, prop);
+ }
+ }
+
QAPI_LIST_PREPEND(mach_list, info);
}
diff --git a/hw/core/machine-smp.c b/hw/core/machine-smp.c
index 27864c9..2b93fa9 100644
--- a/hw/core/machine-smp.c
+++ b/hw/core/machine-smp.c
@@ -51,6 +51,10 @@
g_string_append_printf(s, " * clusters (%u)", ms->smp.clusters);
}
+ if (mc->smp_props.modules_supported) {
+ g_string_append_printf(s, " * modules (%u)", ms->smp.modules);
+ }
+
g_string_append_printf(s, " * cores (%u)", ms->smp.cores);
g_string_append_printf(s, " * threads (%u)", ms->smp.threads);
@@ -88,6 +92,7 @@
unsigned sockets = config->has_sockets ? config->sockets : 0;
unsigned dies = config->has_dies ? config->dies : 0;
unsigned clusters = config->has_clusters ? config->clusters : 0;
+ unsigned modules = config->has_modules ? config->modules : 0;
unsigned cores = config->has_cores ? config->cores : 0;
unsigned threads = config->has_threads ? config->threads : 0;
unsigned maxcpus = config->has_maxcpus ? config->maxcpus : 0;
@@ -103,6 +108,7 @@
(config->has_sockets && config->sockets == 0) ||
(config->has_dies && config->dies == 0) ||
(config->has_clusters && config->clusters == 0) ||
+ (config->has_modules && config->modules == 0) ||
(config->has_cores && config->cores == 0) ||
(config->has_threads && config->threads == 0) ||
(config->has_maxcpus && config->maxcpus == 0)) {
@@ -115,6 +121,20 @@
* If not supported by the machine, a topology parameter must be
* omitted.
*/
+ if (!mc->smp_props.modules_supported && config->has_modules) {
+ if (config->modules > 1) {
+ error_setg(errp, "modules not supported by this "
+ "machine's CPU topology");
+ return;
+ } else {
+ /* Here modules only equals 1 since we've checked zero case. */
+ warn_report("Deprecated CPU topology (considered invalid): "
+ "Unsupported modules parameter mustn't be "
+ "specified as 1");
+ }
+ }
+ modules = modules > 0 ? modules : 1;
+
if (!mc->smp_props.clusters_supported && config->has_clusters) {
if (config->clusters > 1) {
error_setg(errp, "clusters not supported by this "
@@ -185,11 +205,13 @@
cores = cores > 0 ? cores : 1;
threads = threads > 0 ? threads : 1;
sockets = maxcpus /
- (drawers * books * dies * clusters * cores * threads);
+ (drawers * books * dies * clusters *
+ modules * cores * threads);
} else if (cores == 0) {
threads = threads > 0 ? threads : 1;
cores = maxcpus /
- (drawers * books * sockets * dies * clusters * threads);
+ (drawers * books * sockets * dies *
+ clusters * modules * threads);
}
} else {
/* prefer cores over sockets since 6.2 */
@@ -197,22 +219,26 @@
sockets = sockets > 0 ? sockets : 1;
threads = threads > 0 ? threads : 1;
cores = maxcpus /
- (drawers * books * sockets * dies * clusters * threads);
+ (drawers * books * sockets * dies *
+ clusters * modules * threads);
} else if (sockets == 0) {
threads = threads > 0 ? threads : 1;
sockets = maxcpus /
- (drawers * books * dies * clusters * cores * threads);
+ (drawers * books * dies * clusters *
+ modules * cores * threads);
}
}
/* try to calculate omitted threads at last */
if (threads == 0) {
threads = maxcpus /
- (drawers * books * sockets * dies * clusters * cores);
+ (drawers * books * sockets * dies *
+ clusters * modules * cores);
}
}
- total_cpus = drawers * books * sockets * dies * clusters * cores * threads;
+ total_cpus = drawers * books * sockets * dies *
+ clusters * modules * cores * threads;
maxcpus = maxcpus > 0 ? maxcpus : total_cpus;
cpus = cpus > 0 ? cpus : maxcpus;
@@ -222,6 +248,7 @@
ms->smp.sockets = sockets;
ms->smp.dies = dies;
ms->smp.clusters = clusters;
+ ms->smp.modules = modules;
ms->smp.cores = cores;
ms->smp.threads = threads;
ms->smp.max_cpus = maxcpus;
@@ -266,7 +293,7 @@
unsigned int machine_topo_get_cores_per_socket(const MachineState *ms)
{
- return ms->smp.cores * ms->smp.clusters * ms->smp.dies;
+ return ms->smp.cores * ms->smp.modules * ms->smp.clusters * ms->smp.dies;
}
unsigned int machine_topo_get_threads_per_socket(const MachineState *ms)
diff --git a/hw/core/machine.c b/hw/core/machine.c
index 582c2df..0dec48e 100644
--- a/hw/core/machine.c
+++ b/hw/core/machine.c
@@ -800,6 +800,11 @@
return;
}
+ if (props->has_module_id && !slot->props.has_module_id) {
+ error_setg(errp, "module-id is not supported");
+ return;
+ }
+
if (props->has_cluster_id && !slot->props.has_cluster_id) {
error_setg(errp, "cluster-id is not supported");
return;
@@ -824,6 +829,11 @@
continue;
}
+ if (props->has_module_id &&
+ props->module_id != slot->props.module_id) {
+ continue;
+ }
+
if (props->has_cluster_id &&
props->cluster_id != slot->props.cluster_id) {
continue;
@@ -881,6 +891,7 @@
.has_sockets = true, .sockets = ms->smp.sockets,
.has_dies = true, .dies = ms->smp.dies,
.has_clusters = true, .clusters = ms->smp.clusters,
+ .has_modules = true, .modules = ms->smp.modules,
.has_cores = true, .cores = ms->smp.cores,
.has_threads = true, .threads = ms->smp.threads,
.has_maxcpus = true, .maxcpus = ms->smp.max_cpus,
@@ -1157,6 +1168,7 @@
ms->smp.sockets = 1;
ms->smp.dies = 1;
ms->smp.clusters = 1;
+ ms->smp.modules = 1;
ms->smp.cores = 1;
ms->smp.threads = 1;
@@ -1224,6 +1236,12 @@
}
g_string_append_printf(s, "cluster-id: %"PRId64, cpu->props.cluster_id);
}
+ if (cpu->props.has_module_id) {
+ if (s->len) {
+ g_string_append_printf(s, ", ");
+ }
+ g_string_append_printf(s, "module-id: %"PRId64, cpu->props.module_id);
+ }
if (cpu->props.has_core_id) {
if (s->len) {
g_string_append_printf(s, ", ");
diff --git a/hw/core/qdev.c b/hw/core/qdev.c
index 00efaf1..f3a996f 100644
--- a/hw/core/qdev.c
+++ b/hw/core/qdev.c
@@ -760,10 +760,10 @@
rc->phases.enter(OBJECT(dev), RESET_TYPE_COLD);
}
if (rc->phases.hold) {
- rc->phases.hold(OBJECT(dev));
+ rc->phases.hold(OBJECT(dev), RESET_TYPE_COLD);
}
if (rc->phases.exit) {
- rc->phases.exit(OBJECT(dev));
+ rc->phases.exit(OBJECT(dev), RESET_TYPE_COLD);
}
}
diff --git a/hw/core/reset.c b/hw/core/reset.c
index d50da7e..58dfc8d 100644
--- a/hw/core/reset.c
+++ b/hw/core/reset.c
@@ -44,13 +44,6 @@
}
/*
- * Reason why the currently in-progress qemu_devices_reset() was called.
- * If we made at least SHUTDOWN_CAUSE_SNAPSHOT_LOAD have a corresponding
- * ResetType we could perhaps avoid the need for this global.
- */
-static ShutdownCause device_reset_reason;
-
-/*
* This is an Object which implements Resettable simply to call the
* callback function in the hold phase.
*/
@@ -73,12 +66,11 @@
return &lr->reset_state;
}
-static void legacy_reset_hold(Object *obj)
+static void legacy_reset_hold(Object *obj, ResetType type)
{
LegacyReset *lr = LEGACY_RESET(obj);
- if (device_reset_reason == SHUTDOWN_CAUSE_SNAPSHOT_LOAD &&
- lr->skip_on_snapshot_load) {
+ if (type == RESET_TYPE_SNAPSHOT_LOAD && lr->skip_on_snapshot_load) {
return;
}
lr->func(lr->opaque);
@@ -180,8 +172,9 @@
void qemu_devices_reset(ShutdownCause reason)
{
- device_reset_reason = reason;
+ ResetType type = (reason == SHUTDOWN_CAUSE_SNAPSHOT_LOAD) ?
+ RESET_TYPE_SNAPSHOT_LOAD : RESET_TYPE_COLD;
/* Reset the simulation */
- resettable_reset(OBJECT(get_root_reset_container()), RESET_TYPE_COLD);
+ resettable_reset(OBJECT(get_root_reset_container()), type);
}
diff --git a/hw/core/resettable.c b/hw/core/resettable.c
index c3df75c..6dd3e3d 100644
--- a/hw/core/resettable.c
+++ b/hw/core/resettable.c
@@ -48,8 +48,6 @@
void resettable_assert_reset(Object *obj, ResetType type)
{
- /* TODO: change this assert when adding support for other reset types */
- assert(type == RESET_TYPE_COLD);
trace_resettable_reset_assert_begin(obj, type);
assert(!enter_phase_in_progress);
@@ -64,8 +62,6 @@
void resettable_release_reset(Object *obj, ResetType type)
{
- /* TODO: change this assert when adding support for other reset types */
- assert(type == RESET_TYPE_COLD);
trace_resettable_reset_release_begin(obj, type);
assert(!enter_phase_in_progress);
@@ -181,7 +177,7 @@
trace_resettable_transitional_function(obj, obj_typename);
tr_func(obj);
} else if (rc->phases.hold) {
- rc->phases.hold(obj);
+ rc->phases.hold(obj, type);
}
}
trace_resettable_phase_hold_end(obj, obj_typename, s->count);
@@ -204,7 +200,7 @@
if (--s->count == 0) {
trace_resettable_phase_exit_exec(obj, obj_typename, !!rc->phases.exit);
if (rc->phases.exit && !resettable_get_tr_func(rc, obj)) {
- rc->phases.exit(obj);
+ rc->phases.exit(obj, type);
}
}
s->exit_phase_in_progress = false;
diff --git a/hw/cpu/Kconfig b/hw/cpu/Kconfig
index 1767d02..baff478 100644
--- a/hw/cpu/Kconfig
+++ b/hw/cpu/Kconfig
@@ -1,8 +1,17 @@
-config ARM11MPCORE
- bool
-
config A9MPCORE
bool
+ select A9_GTIMER
+ select A9SCU # snoop control unit
+ select ARM_GIC
+ select ARM_MPTIMER
config A15MPCORE
bool
+ select ARM_GIC
+
+config ARM11MPCORE
+ bool
+ select ARM11SCU
+
+config CPU_CLUSTER
+ bool
diff --git a/hw/cpu/meson.build b/hw/cpu/meson.build
index 38cdcfb..9d36bf8 100644
--- a/hw/cpu/meson.build
+++ b/hw/cpu/meson.build
@@ -1,4 +1,5 @@
-system_ss.add(files('core.c', 'cluster.c'))
+system_ss.add(files('core.c'))
+system_ss.add(when: 'CONFIG_CPU_CLUSTER', if_true: files('cluster.c'))
system_ss.add(when: 'CONFIG_ARM11MPCORE', if_true: files('arm11mpcore.c'))
system_ss.add(when: 'CONFIG_REALVIEW', if_true: files('realview_mpcore.c'))
diff --git a/hw/cxl/cxl-cdat.c b/hw/cxl/cxl-cdat.c
index 551545f..959a555 100644
--- a/hw/cxl/cxl-cdat.c
+++ b/hw/cxl/cxl-cdat.c
@@ -44,7 +44,7 @@
}
}
-static void ct3_build_cdat(CDATObject *cdat, Error **errp)
+static bool ct3_build_cdat(CDATObject *cdat, Error **errp)
{
g_autofree CDATTableHeader *cdat_header = NULL;
g_autofree CDATEntry *cdat_st = NULL;
@@ -58,7 +58,7 @@
cdat_header = g_malloc0(sizeof(*cdat_header));
if (!cdat_header) {
error_setg(errp, "Failed to allocate CDAT header");
- return;
+ return false;
}
cdat->built_buf_len = cdat->build_cdat_table(&cdat->built_buf,
@@ -67,14 +67,14 @@
if (cdat->built_buf_len <= 0) {
/* Build later as not all data available yet */
cdat->to_update = true;
- return;
+ return true;
}
cdat->to_update = false;
cdat_st = g_malloc0(sizeof(*cdat_st) * (cdat->built_buf_len + 1));
if (!cdat_st) {
error_setg(errp, "Failed to allocate CDAT entry array");
- return;
+ return false;
}
/* Entry 0 for CDAT header, starts with Entry 1 */
@@ -109,9 +109,10 @@
cdat_st[0].length = sizeof(*cdat_header);
cdat->entry_len = 1 + cdat->built_buf_len;
cdat->entry = g_steal_pointer(&cdat_st);
+ return true;
}
-static void ct3_load_cdat(CDATObject *cdat, Error **errp)
+static bool ct3_load_cdat(CDATObject *cdat, Error **errp)
{
g_autofree CDATEntry *cdat_st = NULL;
g_autofree uint8_t *buf = NULL;
@@ -127,11 +128,11 @@
&file_size, &error)) {
error_setg(errp, "CDAT: File read failed: %s", error->message);
g_error_free(error);
- return;
+ return false;
}
if (file_size < sizeof(CDATTableHeader)) {
error_setg(errp, "CDAT: File too short");
- return;
+ return false;
}
i = sizeof(CDATTableHeader);
num_ent = 1;
@@ -139,19 +140,19 @@
hdr = (CDATSubHeader *)(buf + i);
if (i + sizeof(CDATSubHeader) > file_size) {
error_setg(errp, "CDAT: Truncated table");
- return;
+ return false;
}
cdat_len_check(hdr, errp);
i += hdr->length;
if (i > file_size) {
error_setg(errp, "CDAT: Truncated table");
- return;
+ return false;
}
num_ent++;
}
if (i != file_size) {
error_setg(errp, "CDAT: File length mismatch");
- return;
+ return false;
}
cdat_st = g_new0(CDATEntry, num_ent);
@@ -185,16 +186,17 @@
cdat->entry_len = num_ent;
cdat->entry = g_steal_pointer(&cdat_st);
cdat->buf = g_steal_pointer(&buf);
+ return true;
}
-void cxl_doe_cdat_init(CXLComponentState *cxl_cstate, Error **errp)
+bool cxl_doe_cdat_init(CXLComponentState *cxl_cstate, Error **errp)
{
CDATObject *cdat = &cxl_cstate->cdat;
if (cdat->filename) {
- ct3_load_cdat(cdat, errp);
+ return ct3_load_cdat(cdat, errp);
} else {
- ct3_build_cdat(cdat, errp);
+ return ct3_build_cdat(cdat, errp);
}
}
diff --git a/hw/display/virtio-vga.c b/hw/display/virtio-vga.c
index 94d3353..276f315 100644
--- a/hw/display/virtio-vga.c
+++ b/hw/display/virtio-vga.c
@@ -180,14 +180,14 @@
}
}
-static void virtio_vga_base_reset_hold(Object *obj)
+static void virtio_vga_base_reset_hold(Object *obj, ResetType type)
{
VirtIOVGABaseClass *klass = VIRTIO_VGA_BASE_GET_CLASS(obj);
VirtIOVGABase *vvga = VIRTIO_VGA_BASE(obj);
/* reset virtio-gpu */
if (klass->parent_phases.hold) {
- klass->parent_phases.hold(obj);
+ klass->parent_phases.hold(obj, type);
}
/* reset vga */
diff --git a/hw/dma/soc_dma.c b/hw/dma/soc_dma.c
index 3a43005..d5c52b8 100644
--- a/hw/dma/soc_dma.c
+++ b/hw/dma/soc_dma.c
@@ -209,9 +209,9 @@
dma->enabled_count += level - ch->enable;
if (level)
- dma->ch_enable_mask |= 1 << ch->num;
+ dma->ch_enable_mask |= (uint64_t)1 << ch->num;
else
- dma->ch_enable_mask &= ~(1 << ch->num);
+ dma->ch_enable_mask &= ~((uint64_t)1 << ch->num);
if (level != ch->enable) {
soc_dma_ch_freq_update(dma);
diff --git a/hw/gpio/npcm7xx_gpio.c b/hw/gpio/npcm7xx_gpio.c
index 6e70ac1..ba19b9e 100644
--- a/hw/gpio/npcm7xx_gpio.c
+++ b/hw/gpio/npcm7xx_gpio.c
@@ -352,7 +352,7 @@
s->regs[NPCM7XX_GPIO_ODSC] = s->reset_odsc;
}
-static void npcm7xx_gpio_hold_reset(Object *obj)
+static void npcm7xx_gpio_hold_reset(Object *obj, ResetType type)
{
NPCM7xxGPIOState *s = NPCM7XX_GPIO(obj);
diff --git a/hw/gpio/pl061.c b/hw/gpio/pl061.c
index 86f2383..d5838b8 100644
--- a/hw/gpio/pl061.c
+++ b/hw/gpio/pl061.c
@@ -484,7 +484,7 @@
s->amsel = 0;
}
-static void pl061_hold_reset(Object *obj)
+static void pl061_hold_reset(Object *obj, ResetType type)
{
PL061State *s = PL061(obj);
int i, level;
diff --git a/hw/gpio/stm32l4x5_gpio.c b/hw/gpio/stm32l4x5_gpio.c
index 63b8763..71bf5fd 100644
--- a/hw/gpio/stm32l4x5_gpio.c
+++ b/hw/gpio/stm32l4x5_gpio.c
@@ -70,7 +70,7 @@
return extract32(s->otyper, pin, 1) == 0;
}
-static void stm32l4x5_gpio_reset_hold(Object *obj)
+static void stm32l4x5_gpio_reset_hold(Object *obj, ResetType type)
{
Stm32l4x5GpioState *s = STM32L4X5_GPIO(obj);
diff --git a/hw/hyperv/vmbus.c b/hw/hyperv/vmbus.c
index f33afee..490d805 100644
--- a/hw/hyperv/vmbus.c
+++ b/hw/hyperv/vmbus.c
@@ -2453,7 +2453,7 @@
qemu_mutex_destroy(&vmbus->rx_queue_lock);
}
-static void vmbus_reset_hold(Object *obj)
+static void vmbus_reset_hold(Object *obj, ResetType type)
{
vmbus_deinit(VMBUS(obj));
}
diff --git a/hw/i2c/allwinner-i2c.c b/hw/i2c/allwinner-i2c.c
index 8abcc39..16f1d6d 100644
--- a/hw/i2c/allwinner-i2c.c
+++ b/hw/i2c/allwinner-i2c.c
@@ -170,7 +170,7 @@
return s->cntr & TWI_CNTR_INT_EN;
}
-static void allwinner_i2c_reset_hold(Object *obj)
+static void allwinner_i2c_reset_hold(Object *obj, ResetType type)
{
AWI2CState *s = AW_I2C(obj);
@@ -385,8 +385,7 @@
break;
case TWI_SRST_REG:
if (((value & TWI_SRST_MASK) == 0) && (s->srst & TWI_SRST_MASK)) {
- /* Perform reset */
- allwinner_i2c_reset_hold(OBJECT(s));
+ device_cold_reset(DEVICE(s));
}
s->srst = value & TWI_SRST_MASK;
break;
diff --git a/hw/i2c/npcm7xx_smbus.c b/hw/i2c/npcm7xx_smbus.c
index 0ea3083..22d68fc 100644
--- a/hw/i2c/npcm7xx_smbus.c
+++ b/hw/i2c/npcm7xx_smbus.c
@@ -1022,7 +1022,7 @@
s->rx_cur = 0;
}
-static void npcm7xx_smbus_hold_reset(Object *obj)
+static void npcm7xx_smbus_hold_reset(Object *obj, ResetType type)
{
NPCM7xxSMBusState *s = NPCM7XX_SMBUS(obj);
diff --git a/hw/i386/pc_sysfw.c b/hw/i386/pc_sysfw.c
index 3efabbb..87b5bf5 100644
--- a/hw/i386/pc_sysfw.c
+++ b/hw/i386/pc_sysfw.c
@@ -41,8 +41,7 @@
#define FLASH_SECTOR_SIZE 4096
static void pc_isa_bios_init(MemoryRegion *rom_memory,
- MemoryRegion *flash_mem,
- int ram_size)
+ MemoryRegion *flash_mem)
{
int isa_bios_size;
MemoryRegion *isa_bios;
@@ -186,7 +185,7 @@
if (i == 0) {
flash_mem = pflash_cfi01_get_memory(system_flash);
- pc_isa_bios_init(rom_memory, flash_mem, size);
+ pc_isa_bios_init(rom_memory, flash_mem);
/* Encrypt the pflash boot ROM */
if (sev_enabled()) {
diff --git a/hw/input/adb.c b/hw/input/adb.c
index 98f39b4..aff7130 100644
--- a/hw/input/adb.c
+++ b/hw/input/adb.c
@@ -231,7 +231,7 @@
}
};
-static void adb_bus_reset_hold(Object *obj)
+static void adb_bus_reset_hold(Object *obj, ResetType type)
{
ADBBusState *adb_bus = ADB_BUS(obj);
diff --git a/hw/input/ps2.c b/hw/input/ps2.c
index 00b695a..d6f8344 100644
--- a/hw/input/ps2.c
+++ b/hw/input/ps2.c
@@ -1007,7 +1007,7 @@
}
}
-static void ps2_reset_hold(Object *obj)
+static void ps2_reset_hold(Object *obj, ResetType type)
{
PS2State *s = PS2_DEVICE(obj);
@@ -1015,7 +1015,7 @@
ps2_reset_queue(s);
}
-static void ps2_reset_exit(Object *obj)
+static void ps2_reset_exit(Object *obj, ResetType type)
{
PS2State *s = PS2_DEVICE(obj);
@@ -1048,7 +1048,7 @@
q->cwptr = ccount ? (q->rptr + ccount) & (PS2_BUFFER_SIZE - 1) : -1;
}
-static void ps2_kbd_reset_hold(Object *obj)
+static void ps2_kbd_reset_hold(Object *obj, ResetType type)
{
PS2DeviceClass *ps2dc = PS2_DEVICE_GET_CLASS(obj);
PS2KbdState *s = PS2_KBD_DEVICE(obj);
@@ -1056,7 +1056,7 @@
trace_ps2_kbd_reset(s);
if (ps2dc->parent_phases.hold) {
- ps2dc->parent_phases.hold(obj);
+ ps2dc->parent_phases.hold(obj, type);
}
s->scan_enabled = 1;
@@ -1065,7 +1065,7 @@
s->modifiers = 0;
}
-static void ps2_mouse_reset_hold(Object *obj)
+static void ps2_mouse_reset_hold(Object *obj, ResetType type)
{
PS2DeviceClass *ps2dc = PS2_DEVICE_GET_CLASS(obj);
PS2MouseState *s = PS2_MOUSE_DEVICE(obj);
@@ -1073,7 +1073,7 @@
trace_ps2_mouse_reset(s);
if (ps2dc->parent_phases.hold) {
- ps2dc->parent_phases.hold(obj);
+ ps2dc->parent_phases.hold(obj, type);
}
s->mouse_status = 0;
diff --git a/hw/intc/arm_gic_common.c b/hw/intc/arm_gic_common.c
index 94c173c..53fb2c4 100644
--- a/hw/intc/arm_gic_common.c
+++ b/hw/intc/arm_gic_common.c
@@ -263,7 +263,7 @@
}
}
-static void arm_gic_common_reset_hold(Object *obj)
+static void arm_gic_common_reset_hold(Object *obj, ResetType type)
{
GICState *s = ARM_GIC_COMMON(obj);
int i, j;
diff --git a/hw/intc/arm_gic_kvm.c b/hw/intc/arm_gic_kvm.c
index e0d9e51..53defee 100644
--- a/hw/intc/arm_gic_kvm.c
+++ b/hw/intc/arm_gic_kvm.c
@@ -473,13 +473,13 @@
}
}
-static void kvm_arm_gic_reset_hold(Object *obj)
+static void kvm_arm_gic_reset_hold(Object *obj, ResetType type)
{
GICState *s = ARM_GIC_COMMON(obj);
KVMARMGICClass *kgc = KVM_ARM_GIC_GET_CLASS(s);
if (kgc->parent_phases.hold) {
- kgc->parent_phases.hold(obj);
+ kgc->parent_phases.hold(obj, type);
}
if (kvm_arm_gic_can_save_restore(s)) {
diff --git a/hw/intc/arm_gicv3.c b/hw/intc/arm_gicv3.c
index 0b8f79a..58e18ff 100644
--- a/hw/intc/arm_gicv3.c
+++ b/hw/intc/arm_gicv3.c
@@ -21,7 +21,7 @@
#include "hw/intc/arm_gicv3.h"
#include "gicv3_internal.h"
-static bool irqbetter(GICv3CPUState *cs, int irq, uint8_t prio)
+static bool irqbetter(GICv3CPUState *cs, int irq, uint8_t prio, bool nmi)
{
/* Return true if this IRQ at this priority should take
* precedence over the current recorded highest priority
@@ -30,14 +30,23 @@
* is the same as this one (a property which the calling code
* relies on).
*/
- if (prio < cs->hppi.prio) {
- return true;
+ if (prio != cs->hppi.prio) {
+ return prio < cs->hppi.prio;
}
+
+ /*
+ * The same priority IRQ with non-maskable property should signal to
+ * the CPU as it have the priority higher than the labelled 0x80 or 0x00.
+ */
+ if (nmi != cs->hppi.nmi) {
+ return nmi;
+ }
+
/* If multiple pending interrupts have the same priority then it is an
* IMPDEF choice which of them to signal to the CPU. We choose to
* signal the one with the lowest interrupt number.
*/
- if (prio == cs->hppi.prio && irq <= cs->hppi.irq) {
+ if (irq <= cs->hppi.irq) {
return true;
}
return false;
@@ -129,6 +138,40 @@
return pend;
}
+static bool gicv3_get_priority(GICv3CPUState *cs, bool is_redist, int irq,
+ uint8_t *prio)
+{
+ uint32_t nmi = 0x0;
+
+ if (is_redist) {
+ nmi = extract32(cs->gicr_inmir0, irq, 1);
+ } else {
+ nmi = *gic_bmp_ptr32(cs->gic->nmi, irq);
+ nmi = nmi & (1 << (irq & 0x1f));
+ }
+
+ if (nmi) {
+ /* DS = 0 & Non-secure NMI */
+ if (!(cs->gic->gicd_ctlr & GICD_CTLR_DS) &&
+ ((is_redist && extract32(cs->gicr_igroupr0, irq, 1)) ||
+ (!is_redist && gicv3_gicd_group_test(cs->gic, irq)))) {
+ *prio = 0x80;
+ } else {
+ *prio = 0x0;
+ }
+
+ return true;
+ }
+
+ if (is_redist) {
+ *prio = cs->gicr_ipriorityr[irq];
+ } else {
+ *prio = cs->gic->gicd_ipriority[irq];
+ }
+
+ return false;
+}
+
/* Update the interrupt status after state in a redistributor
* or CPU interface has changed, but don't tell the CPU i/f.
*/
@@ -141,6 +184,7 @@
uint8_t prio;
int i;
uint32_t pend;
+ bool nmi = false;
/* Find out which redistributor interrupts are eligible to be
* signaled to the CPU interface.
@@ -152,10 +196,11 @@
if (!(pend & (1 << i))) {
continue;
}
- prio = cs->gicr_ipriorityr[i];
- if (irqbetter(cs, i, prio)) {
+ nmi = gicv3_get_priority(cs, true, i, &prio);
+ if (irqbetter(cs, i, prio, nmi)) {
cs->hppi.irq = i;
cs->hppi.prio = prio;
+ cs->hppi.nmi = nmi;
seenbetter = true;
}
}
@@ -168,9 +213,10 @@
if ((cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS) && cs->gic->lpi_enable &&
(cs->gic->gicd_ctlr & GICD_CTLR_EN_GRP1NS) &&
(cs->hpplpi.prio != 0xff)) {
- if (irqbetter(cs, cs->hpplpi.irq, cs->hpplpi.prio)) {
+ if (irqbetter(cs, cs->hpplpi.irq, cs->hpplpi.prio, cs->hpplpi.nmi)) {
cs->hppi.irq = cs->hpplpi.irq;
cs->hppi.prio = cs->hpplpi.prio;
+ cs->hppi.nmi = cs->hpplpi.nmi;
cs->hppi.grp = cs->hpplpi.grp;
seenbetter = true;
}
@@ -213,6 +259,7 @@
int i;
uint8_t prio;
uint32_t pend = 0;
+ bool nmi = false;
assert(start >= GIC_INTERNAL);
assert(len > 0);
@@ -240,10 +287,11 @@
*/
continue;
}
- prio = s->gicd_ipriority[i];
- if (irqbetter(cs, i, prio)) {
+ nmi = gicv3_get_priority(cs, false, i, &prio);
+ if (irqbetter(cs, i, prio, nmi)) {
cs->hppi.irq = i;
cs->hppi.prio = prio;
+ cs->hppi.nmi = nmi;
cs->seenbetter = true;
}
}
@@ -293,6 +341,7 @@
for (i = 0; i < s->num_cpu; i++) {
s->cpu[i].hppi.prio = 0xff;
+ s->cpu[i].hppi.nmi = false;
}
/* Note that we can guarantee that these functions will not
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index cb55c72..bd50a1b 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -164,6 +164,24 @@
}
};
+static bool gicv3_cpu_nmi_needed(void *opaque)
+{
+ GICv3CPUState *cs = opaque;
+
+ return cs->gic->nmi_support;
+}
+
+static const VMStateDescription vmstate_gicv3_cpu_nmi = {
+ .name = "arm_gicv3_cpu/nmi",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = gicv3_cpu_nmi_needed,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT32(gicr_inmir0, GICv3CPUState),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription vmstate_gicv3_cpu = {
.name = "arm_gicv3_cpu",
.version_id = 1,
@@ -196,6 +214,7 @@
&vmstate_gicv3_cpu_virt,
&vmstate_gicv3_cpu_sre_el1,
&vmstate_gicv3_gicv4,
+ &vmstate_gicv3_cpu_nmi,
NULL
}
};
@@ -238,6 +257,24 @@
}
};
+static bool gicv3_nmi_needed(void *opaque)
+{
+ GICv3State *cs = opaque;
+
+ return cs->nmi_support;
+}
+
+const VMStateDescription vmstate_gicv3_gicd_nmi = {
+ .name = "arm_gicv3/gicd_nmi",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = gicv3_nmi_needed,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT32_ARRAY(nmi, GICv3State, GICV3_BMP_SIZE),
+ VMSTATE_END_OF_LIST()
+ }
+};
+
static const VMStateDescription vmstate_gicv3 = {
.name = "arm_gicv3",
.version_id = 1,
@@ -266,6 +303,7 @@
},
.subsections = (const VMStateDescription * const []) {
&vmstate_gicv3_gicd_no_migration_shift_bug,
+ &vmstate_gicv3_gicd_nmi,
NULL
}
};
@@ -299,6 +337,12 @@
for (i = 0; i < s->num_cpu; i++) {
sysbus_init_irq(sbd, &s->cpu[i].parent_vfiq);
}
+ for (i = 0; i < s->num_cpu; i++) {
+ sysbus_init_irq(sbd, &s->cpu[i].parent_nmi);
+ }
+ for (i = 0; i < s->num_cpu; i++) {
+ sysbus_init_irq(sbd, &s->cpu[i].parent_vnmi);
+ }
memory_region_init_io(&s->iomem_dist, OBJECT(s), ops, s,
"gicv3_dist", 0x10000);
@@ -451,7 +495,7 @@
g_free(s->redist_region_count);
}
-static void arm_gicv3_common_reset_hold(Object *obj)
+static void arm_gicv3_common_reset_hold(Object *obj, ResetType type)
{
GICv3State *s = ARM_GICV3_COMMON(obj);
int i;
@@ -492,8 +536,11 @@
memset(cs->gicr_ipriorityr, 0, sizeof(cs->gicr_ipriorityr));
cs->hppi.prio = 0xff;
+ cs->hppi.nmi = false;
cs->hpplpi.prio = 0xff;
+ cs->hpplpi.nmi = false;
cs->hppvlpi.prio = 0xff;
+ cs->hppvlpi.nmi = false;
/* State in the CPU interface must *not* be reset here, because it
* is part of the CPU's reset domain, not the GIC device's.
@@ -563,6 +610,7 @@
DEFINE_PROP_UINT32("num-irq", GICv3State, num_irq, 32),
DEFINE_PROP_UINT32("revision", GICv3State, revision, 3),
DEFINE_PROP_BOOL("has-lpi", GICv3State, lpi_enable, 0),
+ DEFINE_PROP_BOOL("has-nmi", GICv3State, nmi_support, 0),
DEFINE_PROP_BOOL("has-security-extensions", GICv3State, security_extn, 0),
/*
* Compatibility property: force 8 bits of physical priority, even
diff --git a/hw/intc/arm_gicv3_cpuif.c b/hw/intc/arm_gicv3_cpuif.c
index 67d8fd0..bdb13b0 100644
--- a/hw/intc/arm_gicv3_cpuif.c
+++ b/hw/intc/arm_gicv3_cpuif.c
@@ -21,6 +21,7 @@
#include "hw/irq.h"
#include "cpu.h"
#include "target/arm/cpregs.h"
+#include "target/arm/cpu-features.h"
#include "sysemu/tcg.h"
#include "sysemu/qtest.h"
@@ -157,6 +158,10 @@
int i;
int aprmax = ich_num_aprs(cs);
+ if (cs->ich_apr[GICV3_G1NS][0] & ICV_AP1R_EL1_NMI) {
+ return 0x0;
+ }
+
for (i = 0; i < aprmax; i++) {
uint32_t apr = cs->ich_apr[GICV3_G0][i] |
cs->ich_apr[GICV3_G1NS][i];
@@ -191,6 +196,7 @@
* correct behaviour.
*/
int prio = 0xff;
+ bool nmi = false;
if (!(cs->ich_vmcr_el2 & (ICH_VMCR_EL2_VENG0 | ICH_VMCR_EL2_VENG1))) {
/* Both groups disabled, definitely nothing to do */
@@ -199,6 +205,7 @@
for (i = 0; i < cs->num_list_regs; i++) {
uint64_t lr = cs->ich_lr_el2[i];
+ bool thisnmi;
int thisprio;
if (ich_lr_state(lr) != ICH_LR_EL2_STATE_PENDING) {
@@ -217,10 +224,12 @@
}
}
+ thisnmi = lr & ICH_LR_EL2_NMI;
thisprio = ich_lr_prio(lr);
- if (thisprio < prio) {
+ if ((thisprio < prio) || ((thisprio == prio) && (thisnmi & (!nmi)))) {
prio = thisprio;
+ nmi = thisnmi;
idx = i;
}
}
@@ -289,6 +298,7 @@
* equivalent of these checks.
*/
int grp;
+ bool is_nmi;
uint32_t mask, prio, rprio, vpmr;
if (!(cs->ich_hcr_el2 & ICH_HCR_EL2_EN)) {
@@ -301,10 +311,11 @@
*/
prio = ich_lr_prio(lr);
+ is_nmi = lr & ICH_LR_EL2_NMI;
vpmr = extract64(cs->ich_vmcr_el2, ICH_VMCR_EL2_VPMR_SHIFT,
ICH_VMCR_EL2_VPMR_LENGTH);
- if (prio >= vpmr) {
+ if (!is_nmi && prio >= vpmr) {
/* Priority mask masks this interrupt */
return false;
}
@@ -326,6 +337,11 @@
return true;
}
+ if ((prio & mask) == (rprio & mask) && is_nmi &&
+ !(cs->ich_apr[GICV3_G1NS][0] & ICV_AP1R_EL1_NMI)) {
+ return true;
+ }
+
return false;
}
@@ -465,6 +481,7 @@
int idx;
int irqlevel = 0;
int fiqlevel = 0;
+ int nmilevel = 0;
idx = hppvi_index(cs);
trace_gicv3_cpuif_virt_update(gicv3_redist_affid(cs), idx,
@@ -482,9 +499,17 @@
uint64_t lr = cs->ich_lr_el2[idx];
if (icv_hppi_can_preempt(cs, lr)) {
- /* Virtual interrupts are simple: G0 are always FIQ, and G1 IRQ */
+ /*
+ * Virtual interrupts are simple: G0 are always FIQ, and G1 are
+ * IRQ or NMI which depends on the ICH_LR<n>_EL2.NMI to have
+ * non-maskable property.
+ */
if (lr & ICH_LR_EL2_GROUP) {
- irqlevel = 1;
+ if (lr & ICH_LR_EL2_NMI) {
+ nmilevel = 1;
+ } else {
+ irqlevel = 1;
+ }
} else {
fiqlevel = 1;
}
@@ -494,6 +519,7 @@
trace_gicv3_cpuif_virt_set_irqs(gicv3_redist_affid(cs), fiqlevel, irqlevel);
qemu_set_irq(cs->parent_vfiq, fiqlevel);
qemu_set_irq(cs->parent_virq, irqlevel);
+ qemu_set_irq(cs->parent_vnmi, nmilevel);
}
static void gicv3_cpuif_virt_update(GICv3CPUState *cs)
@@ -550,7 +576,11 @@
trace_gicv3_icv_ap_write(ri->crm & 1, regno, gicv3_redist_affid(cs), value);
- cs->ich_apr[grp][regno] = value & 0xFFFFFFFFU;
+ if (cs->nmi_support) {
+ cs->ich_apr[grp][regno] = value & (0xFFFFFFFFU | ICV_AP1R_EL1_NMI);
+ } else {
+ cs->ich_apr[grp][regno] = value & 0xFFFFFFFFU;
+ }
gicv3_cpuif_virt_irq_fiq_update(cs);
return;
@@ -697,7 +727,11 @@
static uint64_t icv_rpr_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
GICv3CPUState *cs = icc_cs_from_env(env);
- int prio = ich_highest_active_virt_prio(cs);
+ uint64_t prio = ich_highest_active_virt_prio(cs);
+
+ if (cs->ich_apr[GICV3_G1NS][0] & ICV_AP1R_EL1_NMI) {
+ prio |= ICV_RPR_EL1_NMI;
+ }
trace_gicv3_icv_rpr_read(gicv3_redist_affid(cs), prio);
return prio;
@@ -736,13 +770,19 @@
*/
uint32_t mask = icv_gprio_mask(cs, grp);
int prio = ich_lr_prio(cs->ich_lr_el2[idx]) & mask;
+ bool nmi = cs->ich_lr_el2[idx] & ICH_LR_EL2_NMI;
int aprbit = prio >> (8 - cs->vprebits);
int regno = aprbit / 32;
int regbit = aprbit % 32;
cs->ich_lr_el2[idx] &= ~ICH_LR_EL2_STATE_PENDING_BIT;
cs->ich_lr_el2[idx] |= ICH_LR_EL2_STATE_ACTIVE_BIT;
- cs->ich_apr[grp][regno] |= (1 << regbit);
+
+ if (nmi) {
+ cs->ich_apr[grp][regno] |= ICV_AP1R_EL1_NMI;
+ } else {
+ cs->ich_apr[grp][regno] |= (1 << regbit);
+ }
}
static void icv_activate_vlpi(GICv3CPUState *cs)
@@ -763,6 +803,7 @@
int grp = ri->crm == 8 ? GICV3_G0 : GICV3_G1NS;
int idx = hppvi_index(cs);
uint64_t intid = INTID_SPURIOUS;
+ int el = arm_current_el(env);
if (idx == HPPVI_INDEX_VLPI) {
if (cs->hppvlpi.grp == grp && icv_hppvlpi_can_preempt(cs)) {
@@ -772,11 +813,16 @@
} else if (idx >= 0) {
uint64_t lr = cs->ich_lr_el2[idx];
int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
+ bool nmi = env->cp15.sctlr_el[el] & SCTLR_NMI && lr & ICH_LR_EL2_NMI;
if (thisgrp == grp && icv_hppi_can_preempt(cs, lr)) {
intid = ich_lr_vintid(lr);
if (!gicv3_intid_is_special(intid)) {
- icv_activate_irq(cs, idx, grp);
+ if (!nmi) {
+ icv_activate_irq(cs, idx, grp);
+ } else {
+ intid = INTID_NMI;
+ }
} else {
/* Interrupt goes from Pending to Invalid */
cs->ich_lr_el2[idx] &= ~ICH_LR_EL2_STATE_PENDING_BIT;
@@ -795,6 +841,42 @@
return intid;
}
+static uint64_t icv_nmiar1_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ GICv3CPUState *cs = icc_cs_from_env(env);
+ int idx = hppvi_index(cs);
+ uint64_t intid = INTID_SPURIOUS;
+
+ if (idx >= 0 && idx != HPPVI_INDEX_VLPI) {
+ uint64_t lr = cs->ich_lr_el2[idx];
+ int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
+
+ if ((thisgrp == GICV3_G1NS) && icv_hppi_can_preempt(cs, lr)) {
+ intid = ich_lr_vintid(lr);
+ if (!gicv3_intid_is_special(intid)) {
+ if (lr & ICH_LR_EL2_NMI) {
+ icv_activate_irq(cs, idx, GICV3_G1NS);
+ } else {
+ intid = INTID_SPURIOUS;
+ }
+ } else {
+ /* Interrupt goes from Pending to Invalid */
+ cs->ich_lr_el2[idx] &= ~ICH_LR_EL2_STATE_PENDING_BIT;
+ /*
+ * We will now return the (bogus) ID from the list register,
+ * as per the pseudocode.
+ */
+ }
+ }
+ }
+
+ trace_gicv3_icv_nmiar1_read(gicv3_redist_affid(cs), intid);
+
+ gicv3_cpuif_virt_update(cs);
+
+ return intid;
+}
+
static uint32_t icc_fullprio_mask(GICv3CPUState *cs)
{
/*
@@ -832,6 +914,23 @@
*/
int i;
+ if (cs->nmi_support) {
+ /*
+ * If an NMI is active this takes precedence over anything else
+ * for priority purposes; the NMI bit is only in the AP1R0 bit.
+ * We return here the effective priority of the NMI, which is
+ * either 0x0 or 0x80. Callers will need to check NMI again for
+ * purposes of either setting the RPR register bits or for
+ * prioritization of NMI vs non-NMI.
+ */
+ if (cs->icc_apr[GICV3_G1][0] & ICC_AP1R_EL1_NMI) {
+ return 0;
+ }
+ if (cs->icc_apr[GICV3_G1NS][0] & ICC_AP1R_EL1_NMI) {
+ return (cs->gic->gicd_ctlr & GICD_CTLR_DS) ? 0 : 0x80;
+ }
+ }
+
for (i = 0; i < icc_num_aprs(cs); i++) {
uint32_t apr = cs->icc_apr[GICV3_G0][i] |
cs->icc_apr[GICV3_G1][i] | cs->icc_apr[GICV3_G1NS][i];
@@ -898,12 +997,24 @@
*/
int rprio;
uint32_t mask;
+ ARMCPU *cpu = ARM_CPU(cs->cpu);
+ CPUARMState *env = &cpu->env;
if (icc_no_enabled_hppi(cs)) {
return false;
}
- if (cs->hppi.prio >= cs->icc_pmr_el1) {
+ if (cs->hppi.nmi) {
+ if (!(cs->gic->gicd_ctlr & GICD_CTLR_DS) &&
+ cs->hppi.grp == GICV3_G1NS) {
+ if (cs->icc_pmr_el1 < 0x80) {
+ return false;
+ }
+ if (arm_is_secure(env) && cs->icc_pmr_el1 == 0x80) {
+ return false;
+ }
+ }
+ } else if (cs->hppi.prio >= cs->icc_pmr_el1) {
/* Priority mask masks this interrupt */
return false;
}
@@ -923,6 +1034,12 @@
return true;
}
+ if (cs->hppi.nmi && (cs->hppi.prio & mask) == (rprio & mask)) {
+ if (!(cs->icc_apr[cs->hppi.grp][0] & ICC_AP1R_EL1_NMI)) {
+ return true;
+ }
+ }
+
return false;
}
@@ -931,6 +1048,7 @@
/* Tell the CPU about its highest priority pending interrupt */
int irqlevel = 0;
int fiqlevel = 0;
+ int nmilevel = 0;
ARMCPU *cpu = ARM_CPU(cs->cpu);
CPUARMState *env = &cpu->env;
@@ -969,6 +1087,8 @@
if (isfiq) {
fiqlevel = 1;
+ } else if (cs->hppi.nmi) {
+ nmilevel = 1;
} else {
irqlevel = 1;
}
@@ -978,6 +1098,7 @@
qemu_set_irq(cs->parent_fiq, fiqlevel);
qemu_set_irq(cs->parent_irq, irqlevel);
+ qemu_set_irq(cs->parent_nmi, nmilevel);
}
static uint64_t icc_pmr_read(CPUARMState *env, const ARMCPRegInfo *ri)
@@ -1044,8 +1165,13 @@
int aprbit = prio >> (8 - cs->prebits);
int regno = aprbit / 32;
int regbit = aprbit % 32;
+ bool nmi = cs->hppi.nmi;
- cs->icc_apr[cs->hppi.grp][regno] |= (1 << regbit);
+ if (nmi) {
+ cs->icc_apr[cs->hppi.grp][regno] |= ICC_AP1R_EL1_NMI;
+ } else {
+ cs->icc_apr[cs->hppi.grp][regno] |= (1 << regbit);
+ }
if (irq < GIC_INTERNAL) {
cs->gicr_iactiver0 = deposit32(cs->gicr_iactiver0, irq, 1, 1);
@@ -1159,6 +1285,7 @@
static uint64_t icc_iar1_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
GICv3CPUState *cs = icc_cs_from_env(env);
+ int el = arm_current_el(env);
uint64_t intid;
if (icv_access(env, HCR_IMO)) {
@@ -1172,13 +1299,44 @@
}
if (!gicv3_intid_is_special(intid)) {
- icc_activate_irq(cs, intid);
+ if (cs->hppi.nmi && env->cp15.sctlr_el[el] & SCTLR_NMI) {
+ intid = INTID_NMI;
+ } else {
+ icc_activate_irq(cs, intid);
+ }
}
trace_gicv3_icc_iar1_read(gicv3_redist_affid(cs), intid);
return intid;
}
+static uint64_t icc_nmiar1_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ GICv3CPUState *cs = icc_cs_from_env(env);
+ uint64_t intid;
+
+ if (icv_access(env, HCR_IMO)) {
+ return icv_nmiar1_read(env, ri);
+ }
+
+ if (!icc_hppi_can_preempt(cs)) {
+ intid = INTID_SPURIOUS;
+ } else {
+ intid = icc_hppir1_value(cs, env);
+ }
+
+ if (!gicv3_intid_is_special(intid)) {
+ if (!cs->hppi.nmi) {
+ intid = INTID_SPURIOUS;
+ } else {
+ icc_activate_irq(cs, intid);
+ }
+ }
+
+ trace_gicv3_icc_nmiar1_read(gicv3_redist_affid(cs), intid);
+ return intid;
+}
+
static void icc_drop_prio(GICv3CPUState *cs, int grp)
{
/* Drop the priority of the currently active interrupt in
@@ -1205,6 +1363,12 @@
if (!*papr) {
continue;
}
+
+ if (i == 0 && cs->nmi_support && (*papr & ICC_AP1R_EL1_NMI)) {
+ *papr &= (~ICC_AP1R_EL1_NMI);
+ break;
+ }
+
/* Clear the lowest set bit */
*papr &= *papr - 1;
break;
@@ -1239,6 +1403,15 @@
*/
int i;
+ if (cs->nmi_support) {
+ if (cs->icc_apr[GICV3_G1][0] & ICC_AP1R_EL1_NMI) {
+ return GICV3_G1;
+ }
+ if (cs->icc_apr[GICV3_G1NS][0] & ICC_AP1R_EL1_NMI) {
+ return GICV3_G1NS;
+ }
+ }
+
for (i = 0; i < ARRAY_SIZE(cs->icc_apr[0]); i++) {
int g0ctz = ctz32(cs->icc_apr[GICV3_G0][i]);
int g1ctz = ctz32(cs->icc_apr[GICV3_G1][i]);
@@ -1329,7 +1502,7 @@
ICH_HCR_EL2_EOICOUNT_LENGTH, eoicount + 1);
}
-static int icv_drop_prio(GICv3CPUState *cs)
+static int icv_drop_prio(GICv3CPUState *cs, bool *nmi)
{
/* Drop the priority of the currently active virtual interrupt
* (favouring group 0 if there is a set active bit at
@@ -1351,6 +1524,12 @@
continue;
}
+ if (i == 0 && cs->nmi_support && (*papr1 & ICV_AP1R_EL1_NMI)) {
+ *papr1 &= (~ICV_AP1R_EL1_NMI);
+ *nmi = true;
+ return 0xff;
+ }
+
/* We can't just use the bit-twiddling hack icc_drop_prio() does
* because we need to return the bit number we cleared so
* it can be compared against the list register's priority field.
@@ -1410,6 +1589,7 @@
int irq = value & 0xffffff;
int grp = ri->crm == 8 ? GICV3_G0 : GICV3_G1NS;
int idx, dropprio;
+ bool nmi = false;
trace_gicv3_icv_eoir_write(ri->crm == 8 ? 0 : 1,
gicv3_redist_affid(cs), value);
@@ -1422,8 +1602,8 @@
* error checks" (because that lets us avoid scanning the AP
* registers twice).
*/
- dropprio = icv_drop_prio(cs);
- if (dropprio == 0xff) {
+ dropprio = icv_drop_prio(cs, &nmi);
+ if (dropprio == 0xff && !nmi) {
/* No active interrupt. It is CONSTRAINED UNPREDICTABLE
* whether the list registers are checked in this
* situation; we choose not to.
@@ -1445,8 +1625,9 @@
uint64_t lr = cs->ich_lr_el2[idx];
int thisgrp = (lr & ICH_LR_EL2_GROUP) ? GICV3_G1NS : GICV3_G0;
int lr_gprio = ich_lr_prio(lr) & icv_gprio_mask(cs, grp);
+ bool thisnmi = lr & ICH_LR_EL2_NMI;
- if (thisgrp == grp && lr_gprio == dropprio) {
+ if (thisgrp == grp && (lr_gprio == dropprio || (thisnmi & nmi))) {
if (!icv_eoi_split(env, cs) || irq >= GICV3_LPI_INTID_START) {
/*
* Priority drop and deactivate not split: deactivate irq now.
@@ -1693,7 +1874,11 @@
return;
}
- cs->icc_apr[grp][regno] = value & 0xFFFFFFFFU;
+ if (cs->nmi_support) {
+ cs->icc_apr[grp][regno] = value & (0xFFFFFFFFU | ICC_AP1R_EL1_NMI);
+ } else {
+ cs->icc_apr[grp][regno] = value & 0xFFFFFFFFU;
+ }
gicv3_cpuif_update(cs);
}
@@ -1783,7 +1968,7 @@
static uint64_t icc_rpr_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
GICv3CPUState *cs = icc_cs_from_env(env);
- int prio;
+ uint64_t prio;
if (icv_access(env, HCR_FMO | HCR_IMO)) {
return icv_rpr_read(env, ri);
@@ -1803,6 +1988,22 @@
}
}
+ if (cs->nmi_support) {
+ /* NMI info is reported in the high bits of RPR */
+ if (arm_feature(env, ARM_FEATURE_EL3) && !arm_is_secure(env)) {
+ if (cs->icc_apr[GICV3_G1NS][0] & ICC_AP1R_EL1_NMI) {
+ prio |= ICC_RPR_EL1_NMI;
+ }
+ } else {
+ if (cs->icc_apr[GICV3_G1NS][0] & ICC_AP1R_EL1_NMI) {
+ prio |= ICC_RPR_EL1_NSNMI;
+ }
+ if (cs->icc_apr[GICV3_G1][0] & ICC_AP1R_EL1_NMI) {
+ prio |= ICC_RPR_EL1_NMI;
+ }
+ }
+ }
+
trace_gicv3_icc_rpr_read(gicv3_redist_affid(cs), prio);
return prio;
}
@@ -2482,6 +2683,15 @@
},
};
+static const ARMCPRegInfo gicv3_cpuif_gicv3_nmi_reginfo[] = {
+ { .name = "ICC_NMIAR1_EL1", .state = ARM_CP_STATE_BOTH,
+ .opc0 = 3, .opc1 = 0, .crn = 12, .crm = 9, .opc2 = 5,
+ .type = ARM_CP_IO | ARM_CP_NO_RAW,
+ .access = PL1_R, .accessfn = gicv3_irq_access,
+ .readfn = icc_nmiar1_read,
+ },
+};
+
static uint64_t ich_ap_read(CPUARMState *env, const ARMCPRegInfo *ri)
{
GICv3CPUState *cs = icc_cs_from_env(env);
@@ -2503,7 +2713,11 @@
trace_gicv3_ich_ap_write(ri->crm & 1, regno, gicv3_redist_affid(cs), value);
- cs->ich_apr[grp][regno] = value & 0xFFFFFFFFU;
+ if (cs->nmi_support) {
+ cs->ich_apr[grp][regno] = value & (0xFFFFFFFFU | ICV_AP1R_EL1_NMI);
+ } else {
+ cs->ich_apr[grp][regno] = value & 0xFFFFFFFFU;
+ }
gicv3_cpuif_virt_irq_fiq_update(cs);
}
@@ -2620,6 +2834,11 @@
8 - cs->vpribits, 0);
}
+ /* Enforce RES0 bit in NMI field when FEAT_GICv3_NMI is not implemented */
+ if (!cs->nmi_support) {
+ value &= ~ICH_LR_EL2_NMI;
+ }
+
cs->ich_lr_el2[regno] = value;
gicv3_cpuif_virt_update(cs);
}
@@ -2839,6 +3058,19 @@
define_arm_cp_regs(cpu, gicv3_cpuif_reginfo);
/*
+ * If the CPU implements FEAT_NMI and FEAT_GICv3 it must also
+ * implement FEAT_GICv3_NMI, which is the CPU interface part
+ * of NMI support. This is distinct from whether the GIC proper
+ * (redistributors and distributor) have NMI support. In QEMU
+ * that is a property of the GIC device in s->nmi_support;
+ * cs->nmi_support indicates the CPU interface's support.
+ */
+ if (cpu_isar_feature(aa64_nmi, cpu)) {
+ cs->nmi_support = true;
+ define_arm_cp_regs(cpu, gicv3_cpuif_gicv3_nmi_reginfo);
+ }
+
+ /*
* The CPU implementation specifies the number of supported
* bits of physical priority. For backwards compatibility
* of migration, we have a compat property that forces use
diff --git a/hw/intc/arm_gicv3_dist.c b/hw/intc/arm_gicv3_dist.c
index 35e8506..d8207ac 100644
--- a/hw/intc/arm_gicv3_dist.c
+++ b/hw/intc/arm_gicv3_dist.c
@@ -89,6 +89,29 @@
return extract32(s->gicd_nsacr[irq / 16], (irq % 16) * 2, 2);
}
+static void gicd_write_bitmap_reg(GICv3State *s, MemTxAttrs attrs,
+ uint32_t *bmp, maskfn *maskfn,
+ int offset, uint32_t val)
+{
+ /*
+ * Helper routine to implement writing to a "set" register
+ * (GICD_INMIR, etc).
+ * Semantics implemented here:
+ * RAZ/WI for SGIs, PPIs, unimplemented IRQs
+ * Bits corresponding to Group 0 or Secure Group 1 interrupts RAZ/WI.
+ * offset should be the offset in bytes of the register from the start
+ * of its group.
+ */
+ int irq = offset * 8;
+
+ if (irq < GIC_INTERNAL || irq >= s->num_irq) {
+ return;
+ }
+ val &= mask_group_and_nsacr(s, attrs, maskfn, irq);
+ *gic_bmp_ptr32(bmp, irq) = val;
+ gicv3_update(s, irq, 32);
+}
+
static void gicd_write_set_bitmap_reg(GICv3State *s, MemTxAttrs attrs,
uint32_t *bmp,
maskfn *maskfn,
@@ -389,6 +412,7 @@
* by GICD_TYPER.IDbits)
* MBIS == 0 (message-based SPIs not supported)
* SecurityExtn == 1 if security extns supported
+ * NMI = 1 if Non-maskable interrupt property is supported
* CPUNumber == 0 since for us ARE is always 1
* ITLinesNumber == (((max SPI IntID + 1) / 32) - 1)
*/
@@ -402,6 +426,7 @@
bool dvis = s->revision >= 4;
*data = (1 << 25) | (1 << 24) | (dvis << 18) | (sec_extn << 10) |
+ (s->nmi_support << GICD_TYPER_NMI_SHIFT) |
(s->lpi_enable << GICD_TYPER_LPIS_SHIFT) |
(0xf << 19) | itlinesnumber;
return true;
@@ -543,6 +568,11 @@
/* RAZ/WI since affinity routing is always enabled */
*data = 0;
return true;
+ case GICD_INMIR ... GICD_INMIR + 0x7f:
+ *data = (!s->nmi_support) ? 0 :
+ gicd_read_bitmap_reg(s, attrs, s->nmi, NULL,
+ offset - GICD_INMIR);
+ return true;
case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
{
uint64_t r;
@@ -752,6 +782,12 @@
case GICD_SPENDSGIR ... GICD_SPENDSGIR + 0xf:
/* RAZ/WI since affinity routing is always enabled */
return true;
+ case GICD_INMIR ... GICD_INMIR + 0x7f:
+ if (s->nmi_support) {
+ gicd_write_bitmap_reg(s, attrs, s->nmi, NULL,
+ offset - GICD_INMIR, value);
+ }
+ return true;
case GICD_IROUTER ... GICD_IROUTER + 0x1fdf:
{
uint64_t r;
diff --git a/hw/intc/arm_gicv3_its.c b/hw/intc/arm_gicv3_its.c
index 52e9aca..bf31158 100644
--- a/hw/intc/arm_gicv3_its.c
+++ b/hw/intc/arm_gicv3_its.c
@@ -1950,13 +1950,13 @@
}
}
-static void gicv3_its_reset_hold(Object *obj)
+static void gicv3_its_reset_hold(Object *obj, ResetType type)
{
GICv3ITSState *s = ARM_GICV3_ITS_COMMON(obj);
GICv3ITSClass *c = ARM_GICV3_ITS_GET_CLASS(s);
if (c->parent_phases.hold) {
- c->parent_phases.hold(obj);
+ c->parent_phases.hold(obj, type);
}
/* Quiescent bit reset to 1 */
diff --git a/hw/intc/arm_gicv3_its_common.c b/hw/intc/arm_gicv3_its_common.c
index 331d6b9..0b97362 100644
--- a/hw/intc/arm_gicv3_its_common.c
+++ b/hw/intc/arm_gicv3_its_common.c
@@ -123,7 +123,7 @@
msi_nonbroken = true;
}
-static void gicv3_its_common_reset_hold(Object *obj)
+static void gicv3_its_common_reset_hold(Object *obj, ResetType type)
{
GICv3ITSState *s = ARM_GICV3_ITS_COMMON(obj);
diff --git a/hw/intc/arm_gicv3_its_kvm.c b/hw/intc/arm_gicv3_its_kvm.c
index 3befc96..35539c0 100644
--- a/hw/intc/arm_gicv3_its_kvm.c
+++ b/hw/intc/arm_gicv3_its_kvm.c
@@ -197,14 +197,14 @@
GITS_CTLR, &s->ctlr, true, &error_abort);
}
-static void kvm_arm_its_reset_hold(Object *obj)
+static void kvm_arm_its_reset_hold(Object *obj, ResetType type)
{
GICv3ITSState *s = ARM_GICV3_ITS_COMMON(obj);
KVMARMITSClass *c = KVM_ARM_ITS_GET_CLASS(s);
int i;
if (c->parent_phases.hold) {
- c->parent_phases.hold(obj);
+ c->parent_phases.hold(obj, type);
}
if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL,
diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c
index 77eb37e..9ea6b8e 100644
--- a/hw/intc/arm_gicv3_kvm.c
+++ b/hw/intc/arm_gicv3_kvm.c
@@ -703,7 +703,7 @@
c->icc_ctlr_el1[GICV3_S] = c->icc_ctlr_el1[GICV3_NS];
}
-static void kvm_arm_gicv3_reset_hold(Object *obj)
+static void kvm_arm_gicv3_reset_hold(Object *obj, ResetType type)
{
GICv3State *s = ARM_GICV3_COMMON(obj);
KVMARMGICv3Class *kgc = KVM_ARM_GICV3_GET_CLASS(s);
@@ -711,7 +711,7 @@
DPRINTF("Reset\n");
if (kgc->parent_phases.hold) {
- kgc->parent_phases.hold(obj);
+ kgc->parent_phases.hold(obj, type);
}
if (s->migration_blocker) {
@@ -805,6 +805,11 @@
return;
}
+ if (s->nmi_support) {
+ error_setg(errp, "NMI is not supported with the in-kernel GIC");
+ return;
+ }
+
gicv3_init_irqs_and_mmio(s, kvm_arm_gicv3_set_irq, NULL);
for (i = 0; i < s->num_cpu; i++) {
diff --git a/hw/intc/arm_gicv3_redist.c b/hw/intc/arm_gicv3_redist.c
index 8153525..90b238f 100644
--- a/hw/intc/arm_gicv3_redist.c
+++ b/hw/intc/arm_gicv3_redist.c
@@ -35,6 +35,15 @@
return extract32(cs->gicr_nsacr, irq * 2, 2);
}
+static void gicr_write_bitmap_reg(GICv3CPUState *cs, MemTxAttrs attrs,
+ uint32_t *reg, uint32_t val)
+{
+ /* Helper routine to implement writing to a "set" register */
+ val &= mask_group(cs, attrs);
+ *reg = val;
+ gicv3_redist_update(cs);
+}
+
static void gicr_write_set_bitmap_reg(GICv3CPUState *cs, MemTxAttrs attrs,
uint32_t *reg, uint32_t val)
{
@@ -111,6 +120,7 @@
((prio == hpp->prio) && (irq <= hpp->irq))) {
hpp->irq = irq;
hpp->prio = prio;
+ hpp->nmi = false;
/* LPIs and vLPIs are always non-secure Grp1 interrupts */
hpp->grp = GICV3_G1NS;
}
@@ -147,6 +157,7 @@
int i, bit;
hpp->prio = 0xff;
+ hpp->nmi = false;
for (i = GICV3_LPI_INTID_START / 8; i < pendt_size / 8; i++) {
address_space_read(as, ptbase + i, MEMTXATTRS_UNSPECIFIED, &pend, 1);
@@ -232,6 +243,7 @@
if (!FIELD_EX64(cs->gicr_vpendbaser, GICR_VPENDBASER, VALID)) {
cs->hppvlpi.prio = 0xff;
+ cs->hppvlpi.nmi = false;
return;
}
@@ -406,6 +418,10 @@
*data = value;
return MEMTX_OK;
}
+ case GICR_INMIR0:
+ *data = cs->gic->nmi_support ?
+ gicr_read_bitmap_reg(cs, attrs, cs->gicr_inmir0) : 0;
+ return MEMTX_OK;
case GICR_ICFGR0:
case GICR_ICFGR1:
{
@@ -555,6 +571,12 @@
gicv3_redist_update(cs);
return MEMTX_OK;
}
+ case GICR_INMIR0:
+ if (cs->gic->nmi_support) {
+ gicr_write_bitmap_reg(cs, attrs, &cs->gicr_inmir0, value);
+ }
+ return MEMTX_OK;
+
case GICR_ICFGR0:
/* Register is all RAZ/WI or RAO/WI bits */
return MEMTX_OK;
diff --git a/hw/intc/gicv3_internal.h b/hw/intc/gicv3_internal.h
index 29d5cdc..bc9f518 100644
--- a/hw/intc/gicv3_internal.h
+++ b/hw/intc/gicv3_internal.h
@@ -52,6 +52,8 @@
#define GICD_SGIR 0x0F00
#define GICD_CPENDSGIR 0x0F10
#define GICD_SPENDSGIR 0x0F20
+#define GICD_INMIR 0x0F80
+#define GICD_INMIRnE 0x3B00
#define GICD_IROUTER 0x6000
#define GICD_IDREGS 0xFFD0
@@ -68,6 +70,7 @@
#define GICD_CTLR_E1NWF (1U << 7)
#define GICD_CTLR_RWP (1U << 31)
+#define GICD_TYPER_NMI_SHIFT 9
#define GICD_TYPER_LPIS_SHIFT 17
/* 16 bits EventId */
@@ -109,6 +112,7 @@
#define GICR_ICFGR1 (GICR_SGI_OFFSET + 0x0C04)
#define GICR_IGRPMODR0 (GICR_SGI_OFFSET + 0x0D00)
#define GICR_NSACR (GICR_SGI_OFFSET + 0x0E00)
+#define GICR_INMIR0 (GICR_SGI_OFFSET + 0x0F80)
/* VLPI redistributor registers, offsets from VLPI_base */
#define GICR_VPROPBASER (GICR_VLPI_OFFSET + 0x70)
@@ -190,6 +194,10 @@
#define ICC_CTLR_EL3_A3V (1U << 15)
#define ICC_CTLR_EL3_NDS (1U << 17)
+#define ICC_AP1R_EL1_NMI (1ULL << 63)
+#define ICC_RPR_EL1_NSNMI (1ULL << 62)
+#define ICC_RPR_EL1_NMI (1ULL << 63)
+
#define ICH_VMCR_EL2_VENG0_SHIFT 0
#define ICH_VMCR_EL2_VENG0 (1U << ICH_VMCR_EL2_VENG0_SHIFT)
#define ICH_VMCR_EL2_VENG1_SHIFT 1
@@ -238,6 +246,7 @@
#define ICH_LR_EL2_PRIORITY_SHIFT 48
#define ICH_LR_EL2_PRIORITY_LENGTH 8
#define ICH_LR_EL2_PRIORITY_MASK (0xffULL << ICH_LR_EL2_PRIORITY_SHIFT)
+#define ICH_LR_EL2_NMI (1ULL << 59)
#define ICH_LR_EL2_GROUP (1ULL << 60)
#define ICH_LR_EL2_HW (1ULL << 61)
#define ICH_LR_EL2_STATE_SHIFT 62
@@ -269,6 +278,9 @@
#define ICH_VTR_EL2_PREBITS_SHIFT 26
#define ICH_VTR_EL2_PRIBITS_SHIFT 29
+#define ICV_AP1R_EL1_NMI (1ULL << 63)
+#define ICV_RPR_EL1_NMI (1ULL << 63)
+
/* ITS Registers */
FIELD(GITS_BASER, SIZE, 0, 8)
@@ -507,6 +519,7 @@
/* Special interrupt IDs */
#define INTID_SECURE 1020
#define INTID_NONSECURE 1021
+#define INTID_NMI 1022
#define INTID_SPURIOUS 1023
/* Functions internal to the emulated GICv3 */
diff --git a/hw/intc/trace-events b/hw/intc/trace-events
index 1ef29d0..47340b5 100644
--- a/hw/intc/trace-events
+++ b/hw/intc/trace-events
@@ -116,6 +116,7 @@
gicv3_icc_generate_sgi(uint32_t cpuid, int irq, int irm, uint32_t aff, uint32_t targetlist) "GICv3 CPU i/f 0x%x generating SGI %d IRM %d target affinity 0x%xxx targetlist 0x%x"
gicv3_icc_iar0_read(uint32_t cpu, uint64_t val) "GICv3 ICC_IAR0 read cpu 0x%x value 0x%" PRIx64
gicv3_icc_iar1_read(uint32_t cpu, uint64_t val) "GICv3 ICC_IAR1 read cpu 0x%x value 0x%" PRIx64
+gicv3_icc_nmiar1_read(uint32_t cpu, uint64_t val) "GICv3 ICC_NMIAR1 read cpu 0x%x value 0x%" PRIx64
gicv3_icc_eoir_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICC_EOIR%d write cpu 0x%x value 0x%" PRIx64
gicv3_icc_hppir0_read(uint32_t cpu, uint64_t val) "GICv3 ICC_HPPIR0 read cpu 0x%x value 0x%" PRIx64
gicv3_icc_hppir1_read(uint32_t cpu, uint64_t val) "GICv3 ICC_HPPIR1 read cpu 0x%x value 0x%" PRIx64
@@ -151,6 +152,7 @@
gicv3_icv_hppir_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_HPPIR%d read cpu 0x%x value 0x%" PRIx64
gicv3_icv_dir_write(uint32_t cpu, uint64_t val) "GICv3 ICV_DIR write cpu 0x%x value 0x%" PRIx64
gicv3_icv_iar_read(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_IAR%d read cpu 0x%x value 0x%" PRIx64
+gicv3_icv_nmiar1_read(uint32_t cpu, uint64_t val) "GICv3 ICV_NMIAR1 read cpu 0x%x value 0x%" PRIx64
gicv3_icv_eoir_write(int grp, uint32_t cpu, uint64_t val) "GICv3 ICV_EOIR%d write cpu 0x%x value 0x%" PRIx64
gicv3_cpuif_virt_update(uint32_t cpuid, int idx, int hppvlpi, int grp, int prio) "GICv3 CPU i/f 0x%x virt HPPI update LR index %d HPPVLPI %d grp %d prio %d"
gicv3_cpuif_virt_set_irqs(uint32_t cpuid, int fiqlevel, int irqlevel) "GICv3 CPU i/f 0x%x virt HPPI update: setting FIQ %d IRQ %d"
diff --git a/hw/intc/xics.c b/hw/intc/xics.c
index 700abfa..9b3b7ab 100644
--- a/hw/intc/xics.c
+++ b/hw/intc/xics.c
@@ -579,7 +579,7 @@
irq->saved_priority = 0xff;
}
-static void ics_reset_hold(Object *obj)
+static void ics_reset_hold(Object *obj, ResetType type)
{
ICSState *ics = ICS(obj);
g_autofree uint8_t *flags = g_malloc(ics->nr_irqs);
diff --git a/hw/m68k/q800-glue.c b/hw/m68k/q800-glue.c
index b5a7713..e2ae7c3 100644
--- a/hw/m68k/q800-glue.c
+++ b/hw/m68k/q800-glue.c
@@ -175,7 +175,7 @@
GLUE_set_irq(s, GLUE_IRQ_IN_NMI, 0);
}
-static void glue_reset_hold(Object *obj)
+static void glue_reset_hold(Object *obj, ResetType type)
{
GLUEState *s = GLUE(obj);
diff --git a/hw/mem/cxl_type3.c b/hw/mem/cxl_type3.c
index b0a7e9f..3e42490 100644
--- a/hw/mem/cxl_type3.c
+++ b/hw/mem/cxl_type3.c
@@ -705,8 +705,7 @@
cxl_cstate->cdat.build_cdat_table = ct3_build_cdat_table;
cxl_cstate->cdat.free_cdat_table = ct3_free_cdat_table;
cxl_cstate->cdat.private = ct3d;
- cxl_doe_cdat_init(cxl_cstate, errp);
- if (*errp) {
+ if (!cxl_doe_cdat_init(cxl_cstate, errp)) {
goto err_free_special_ops;
}
diff --git a/hw/misc/applesmc.c b/hw/misc/applesmc.c
index 14e3ef6..59a4899 100644
--- a/hw/misc/applesmc.c
+++ b/hw/misc/applesmc.c
@@ -145,7 +145,7 @@
s->data_pos = 0;
}
-static struct AppleSMCData *applesmc_find_key(AppleSMCState *s)
+static const struct AppleSMCData *applesmc_find_key(AppleSMCState *s)
{
struct AppleSMCData *d;
@@ -161,7 +161,7 @@
unsigned size)
{
AppleSMCState *s = opaque;
- struct AppleSMCData *d;
+ const struct AppleSMCData *d;
smc_debug("DATA received: 0x%02x\n", (uint8_t)val);
switch (s->cmd) {
@@ -269,23 +269,10 @@
static void qdev_applesmc_isa_reset(DeviceState *dev)
{
AppleSMCState *s = APPLE_SMC(dev);
- struct AppleSMCData *d, *next;
- /* Remove existing entries */
- QLIST_FOREACH_SAFE(d, &s->data_def, node, next) {
- QLIST_REMOVE(d, node);
- g_free(d);
- }
s->status = 0x00;
s->status_1e = 0x00;
s->last_ret = 0x00;
-
- applesmc_add_key(s, "REV ", 6, "\x01\x13\x0f\x00\x00\x03");
- applesmc_add_key(s, "OSK0", 32, s->osk);
- applesmc_add_key(s, "OSK1", 32, s->osk + 32);
- applesmc_add_key(s, "NATJ", 1, "\0");
- applesmc_add_key(s, "MSSP", 1, "\0");
- applesmc_add_key(s, "MSSD", 1, "\0x3");
}
static const MemoryRegionOps applesmc_data_io_ops = {
@@ -343,6 +330,24 @@
}
QLIST_INIT(&s->data_def);
+ applesmc_add_key(s, "REV ", 6, "\x01\x13\x0f\x00\x00\x03");
+ applesmc_add_key(s, "OSK0", 32, s->osk);
+ applesmc_add_key(s, "OSK1", 32, s->osk + 32);
+ applesmc_add_key(s, "NATJ", 1, "\0");
+ applesmc_add_key(s, "MSSP", 1, "\0");
+ applesmc_add_key(s, "MSSD", 1, "\0x3");
+}
+
+static void applesmc_unrealize(DeviceState *dev)
+{
+ AppleSMCState *s = APPLE_SMC(dev);
+ struct AppleSMCData *d, *next;
+
+ /* Remove existing entries */
+ QLIST_FOREACH_SAFE(d, &s->data_def, node, next) {
+ QLIST_REMOVE(d, node);
+ g_free(d);
+ }
}
static Property applesmc_isa_properties[] = {
@@ -377,6 +382,7 @@
AcpiDevAmlIfClass *adevc = ACPI_DEV_AML_IF_CLASS(klass);
dc->realize = applesmc_isa_realize;
+ dc->unrealize = applesmc_unrealize;
dc->reset = qdev_applesmc_isa_reset;
device_class_set_props(dc, applesmc_isa_properties);
set_bit(DEVICE_CATEGORY_MISC, dc->categories);
diff --git a/hw/misc/djmemc.c b/hw/misc/djmemc.c
index 9b69656..96d5efb 100644
--- a/hw/misc/djmemc.c
+++ b/hw/misc/djmemc.c
@@ -96,7 +96,7 @@
sysbus_init_mmio(sbd, &s->mem_regs);
}
-static void djmemc_reset_hold(Object *obj)
+static void djmemc_reset_hold(Object *obj, ResetType type)
{
DJMEMCState *s = DJMEMC(obj);
diff --git a/hw/misc/imx25_ccm.c b/hw/misc/imx25_ccm.c
index d888966..faa726a 100644
--- a/hw/misc/imx25_ccm.c
+++ b/hw/misc/imx25_ccm.c
@@ -91,7 +91,7 @@
case IMX25_CCM_LPIMR1_REG:
return "lpimr1";
default:
- sprintf(unknown, "[%u ?]", reg);
+ snprintf(unknown, sizeof(unknown), "[%u ?]", reg);
return unknown;
}
}
diff --git a/hw/misc/imx31_ccm.c b/hw/misc/imx31_ccm.c
index a9059bb..125d4fc 100644
--- a/hw/misc/imx31_ccm.c
+++ b/hw/misc/imx31_ccm.c
@@ -89,7 +89,7 @@
case IMX31_CCM_PDR2_REG:
return "PDR2";
default:
- sprintf(unknown, "[%u ?]", reg);
+ snprintf(unknown, sizeof(unknown), "[%u ?]", reg);
return unknown;
}
}
diff --git a/hw/misc/imx6_ccm.c b/hw/misc/imx6_ccm.c
index 56489d8..b1def7f 100644
--- a/hw/misc/imx6_ccm.c
+++ b/hw/misc/imx6_ccm.c
@@ -85,7 +85,7 @@
case CCM_CMEOR:
return "CMEOR";
default:
- sprintf(unknown, "%u ?", reg);
+ snprintf(unknown, sizeof(unknown), "%u ?", reg);
return unknown;
}
}
@@ -224,7 +224,7 @@
case USB_ANALOG_DIGPROG:
return "USB_ANALOG_DIGPROG";
default:
- sprintf(unknown, "%u ?", reg);
+ snprintf(unknown, sizeof(unknown), "%u ?", reg);
return unknown;
}
}
diff --git a/hw/misc/imx6_src.c b/hw/misc/imx6_src.c
index 0c60035..3766bdf 100644
--- a/hw/misc/imx6_src.c
+++ b/hw/misc/imx6_src.c
@@ -68,7 +68,7 @@
case SRC_GPR10:
return "SRC_GPR10";
default:
- sprintf(unknown, "%u ?", reg);
+ snprintf(unknown, sizeof(unknown), "%u ?", reg);
return unknown;
}
}
diff --git a/hw/misc/imx6ul_ccm.c b/hw/misc/imx6ul_ccm.c
index bbc0be9..0ac49ea 100644
--- a/hw/misc/imx6ul_ccm.c
+++ b/hw/misc/imx6ul_ccm.c
@@ -143,7 +143,7 @@
case CCM_CMEOR:
return "CMEOR";
default:
- sprintf(unknown, "%u ?", reg);
+ snprintf(unknown, sizeof(unknown), "%u ?", reg);
return unknown;
}
}
@@ -274,7 +274,7 @@
case USB_ANALOG_DIGPROG:
return "USB_ANALOG_DIGPROG";
default:
- sprintf(unknown, "%u ?", reg);
+ snprintf(unknown, sizeof(unknown), "%u ?", reg);
return unknown;
}
}
diff --git a/hw/misc/imx7_src.c b/hw/misc/imx7_src.c
index b3725ff..d19f045 100644
--- a/hw/misc/imx7_src.c
+++ b/hw/misc/imx7_src.c
@@ -75,7 +75,7 @@
case SRC_GPR10:
return "SRC_GPR10";
default:
- sprintf(unknown, "%u ?", reg);
+ snprintf(unknown, sizeof(unknown), "%u ?", reg);
return unknown;
}
}
diff --git a/hw/misc/iosb.c b/hw/misc/iosb.c
index e20305e..31927ea 100644
--- a/hw/misc/iosb.c
+++ b/hw/misc/iosb.c
@@ -81,7 +81,7 @@
.endianness = DEVICE_BIG_ENDIAN,
};
-static void iosb_reset_hold(Object *obj)
+static void iosb_reset_hold(Object *obj, ResetType type)
{
IOSBState *s = IOSB(obj);
diff --git a/hw/misc/mac_via.c b/hw/misc/mac_via.c
index db6142b..652395b 100644
--- a/hw/misc/mac_via.c
+++ b/hw/misc/mac_via.c
@@ -1203,7 +1203,7 @@
}
/* VIA 1 */
-static void mos6522_q800_via1_reset_hold(Object *obj)
+static void mos6522_q800_via1_reset_hold(Object *obj, ResetType type)
{
MOS6522Q800VIA1State *v1s = MOS6522_Q800_VIA1(obj);
MOS6522State *ms = MOS6522(v1s);
@@ -1211,7 +1211,7 @@
ADBBusState *adb_bus = &v1s->adb_bus;
if (mdc->parent_phases.hold) {
- mdc->parent_phases.hold(obj);
+ mdc->parent_phases.hold(obj, type);
}
ms->timers[0].frequency = VIA_TIMER_FREQ;
@@ -1359,13 +1359,13 @@
}
}
-static void mos6522_q800_via2_reset_hold(Object *obj)
+static void mos6522_q800_via2_reset_hold(Object *obj, ResetType type)
{
MOS6522State *ms = MOS6522(obj);
MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms);
if (mdc->parent_phases.hold) {
- mdc->parent_phases.hold(obj);
+ mdc->parent_phases.hold(obj, type);
}
ms->timers[0].frequency = VIA_TIMER_FREQ;
diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
index 41934e2..beab0ff 100644
--- a/hw/misc/macio/cuda.c
+++ b/hw/misc/macio/cuda.c
@@ -586,13 +586,13 @@
cuda_update(cs);
}
-static void mos6522_cuda_reset_hold(Object *obj)
+static void mos6522_cuda_reset_hold(Object *obj, ResetType type)
{
MOS6522State *ms = MOS6522(obj);
MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms);
if (mdc->parent_phases.hold) {
- mdc->parent_phases.hold(obj);
+ mdc->parent_phases.hold(obj, type);
}
ms->timers[0].frequency = CUDA_TIMER_FREQ;
diff --git a/hw/misc/macio/pmu.c b/hw/misc/macio/pmu.c
index e40c51b..238da58 100644
--- a/hw/misc/macio/pmu.c
+++ b/hw/misc/macio/pmu.c
@@ -792,7 +792,7 @@
pmu_update(ps);
}
-static void mos6522_pmu_reset_hold(Object *obj)
+static void mos6522_pmu_reset_hold(Object *obj, ResetType type)
{
MOS6522State *ms = MOS6522(obj);
MOS6522PMUState *mps = container_of(ms, MOS6522PMUState, parent_obj);
@@ -800,7 +800,7 @@
MOS6522DeviceClass *mdc = MOS6522_GET_CLASS(ms);
if (mdc->parent_phases.hold) {
- mdc->parent_phases.hold(obj);
+ mdc->parent_phases.hold(obj, type);
}
ms->timers[0].frequency = VIA_TIMER_FREQ;
diff --git a/hw/misc/mos6522.c b/hw/misc/mos6522.c
index e3fe87c..515f62e 100644
--- a/hw/misc/mos6522.c
+++ b/hw/misc/mos6522.c
@@ -642,7 +642,7 @@
}
};
-static void mos6522_reset_hold(Object *obj)
+static void mos6522_reset_hold(Object *obj, ResetType type)
{
MOS6522State *s = MOS6522(obj);
diff --git a/hw/misc/npcm7xx_clk.c b/hw/misc/npcm7xx_clk.c
index ac1622c..2098c85 100644
--- a/hw/misc/npcm7xx_clk.c
+++ b/hw/misc/npcm7xx_clk.c
@@ -873,20 +873,13 @@
QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values));
- switch (type) {
- case RESET_TYPE_COLD:
- memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
- s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
- npcm7xx_clk_update_all_clocks(s);
- return;
- }
-
+ memcpy(s->regs, cold_reset_values, sizeof(cold_reset_values));
+ s->ref_ns = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
+ npcm7xx_clk_update_all_clocks(s);
/*
* A small number of registers need to be reset on a core domain reset,
* but no such reset type exists yet.
*/
- qemu_log_mask(LOG_UNIMP, "%s: reset type %d not implemented.",
- __func__, type);
}
static void npcm7xx_clk_init_clock_hierarchy(NPCM7xxCLKState *s)
diff --git a/hw/misc/npcm7xx_gcr.c b/hw/misc/npcm7xx_gcr.c
index 9252f9d..c4c4e24 100644
--- a/hw/misc/npcm7xx_gcr.c
+++ b/hw/misc/npcm7xx_gcr.c
@@ -159,14 +159,10 @@
QEMU_BUILD_BUG_ON(sizeof(s->regs) != sizeof(cold_reset_values));
- switch (type) {
- case RESET_TYPE_COLD:
- memcpy(s->regs, cold_reset_values, sizeof(s->regs));
- s->regs[NPCM7XX_GCR_PWRON] = s->reset_pwron;
- s->regs[NPCM7XX_GCR_MDLR] = s->reset_mdlr;
- s->regs[NPCM7XX_GCR_INTCR3] = s->reset_intcr3;
- break;
- }
+ memcpy(s->regs, cold_reset_values, sizeof(s->regs));
+ s->regs[NPCM7XX_GCR_PWRON] = s->reset_pwron;
+ s->regs[NPCM7XX_GCR_MDLR] = s->reset_mdlr;
+ s->regs[NPCM7XX_GCR_INTCR3] = s->reset_intcr3;
}
static void npcm7xx_gcr_realize(DeviceState *dev, Error **errp)
diff --git a/hw/misc/npcm7xx_mft.c b/hw/misc/npcm7xx_mft.c
index 9a84858..9fcc69f 100644
--- a/hw/misc/npcm7xx_mft.c
+++ b/hw/misc/npcm7xx_mft.c
@@ -467,7 +467,7 @@
npcm7xx_mft_reset(s);
}
-static void npcm7xx_mft_hold_reset(Object *obj)
+static void npcm7xx_mft_hold_reset(Object *obj, ResetType type)
{
NPCM7xxMFTState *s = NPCM7XX_MFT(obj);
diff --git a/hw/misc/npcm7xx_pwm.c b/hw/misc/npcm7xx_pwm.c
index fca2dd2..f7f77e3 100644
--- a/hw/misc/npcm7xx_pwm.c
+++ b/hw/misc/npcm7xx_pwm.c
@@ -468,7 +468,7 @@
s->piir = 0x00000000;
}
-static void npcm7xx_pwm_hold_reset(Object *obj)
+static void npcm7xx_pwm_hold_reset(Object *obj, ResetType type)
{
NPCM7xxPWMState *s = NPCM7XX_PWM(obj);
int i;
diff --git a/hw/misc/stm32l4x5_exti.c b/hw/misc/stm32l4x5_exti.c
index 9fd8591..495a000 100644
--- a/hw/misc/stm32l4x5_exti.c
+++ b/hw/misc/stm32l4x5_exti.c
@@ -59,25 +59,25 @@
static unsigned regbank_index_by_irq(unsigned irq)
{
- return irq >= EXTI_MAX_IRQ_PER_BANK ? 1 : 0;
+ return irq >= EXTI_MAX_IRQ_PER_BANK ? 1 : 0;
}
static unsigned regbank_index_by_addr(hwaddr addr)
{
- return addr >= EXTI_IMR2 ? 1 : 0;
+ return addr >= EXTI_IMR2 ? 1 : 0;
}
static unsigned valid_mask(unsigned bank)
{
- return MAKE_64BIT_MASK(0, irqs_per_bank[bank]);
+ return MAKE_64BIT_MASK(0, irqs_per_bank[bank]);
}
static unsigned configurable_mask(unsigned bank)
{
- return valid_mask(bank) & ~exti_romask[bank];
+ return valid_mask(bank) & ~exti_romask[bank];
}
-static void stm32l4x5_exti_reset_hold(Object *obj)
+static void stm32l4x5_exti_reset_hold(Object *obj, ResetType type)
{
Stm32l4x5ExtiState *s = STM32L4X5_EXTI(obj);
diff --git a/hw/misc/stm32l4x5_rcc.c b/hw/misc/stm32l4x5_rcc.c
index ed2dbd9..417bd5e 100644
--- a/hw/misc/stm32l4x5_rcc.c
+++ b/hw/misc/stm32l4x5_rcc.c
@@ -113,13 +113,13 @@
set_clock_mux_init_info(s, s->id);
}
-static void clock_mux_reset_hold(Object *obj)
+static void clock_mux_reset_hold(Object *obj, ResetType type)
{
RccClockMuxState *s = RCC_CLOCK_MUX(obj);
clock_mux_update(s, true);
}
-static void clock_mux_reset_exit(Object *obj)
+static void clock_mux_reset_exit(Object *obj, ResetType type)
{
RccClockMuxState *s = RCC_CLOCK_MUX(obj);
clock_mux_update(s, false);
@@ -263,13 +263,13 @@
set_pll_init_info(s, s->id);
}
-static void pll_reset_hold(Object *obj)
+static void pll_reset_hold(Object *obj, ResetType type)
{
RccPllState *s = RCC_PLL(obj);
pll_update(s, true);
}
-static void pll_reset_exit(Object *obj)
+static void pll_reset_exit(Object *obj, ResetType type)
{
RccPllState *s = RCC_PLL(obj);
pll_update(s, false);
@@ -907,7 +907,7 @@
rcc_update_irq(s);
}
-static void stm32l4x5_rcc_reset_hold(Object *obj)
+static void stm32l4x5_rcc_reset_hold(Object *obj, ResetType type)
{
Stm32l4x5RccState *s = STM32L4X5_RCC(obj);
s->cr = 0x00000063;
diff --git a/hw/misc/stm32l4x5_syscfg.c b/hw/misc/stm32l4x5_syscfg.c
index 3dafc00..a5a1ce2 100644
--- a/hw/misc/stm32l4x5_syscfg.c
+++ b/hw/misc/stm32l4x5_syscfg.c
@@ -65,7 +65,7 @@
#define NUM_LINES_PER_EXTICR_REG 4
-static void stm32l4x5_syscfg_hold_reset(Object *obj)
+static void stm32l4x5_syscfg_hold_reset(Object *obj, ResetType type)
{
Stm32l4x5SyscfgState *s = STM32L4X5_SYSCFG(obj);
diff --git a/hw/misc/xlnx-versal-cframe-reg.c b/hw/misc/xlnx-versal-cframe-reg.c
index a6ab287..3fc838b 100644
--- a/hw/misc/xlnx-versal-cframe-reg.c
+++ b/hw/misc/xlnx-versal-cframe-reg.c
@@ -542,7 +542,7 @@
}
}
-static void cframe_reg_reset_hold(Object *obj)
+static void cframe_reg_reset_hold(Object *obj, ResetType type)
{
XlnxVersalCFrameReg *s = XLNX_VERSAL_CFRAME_REG(obj);
diff --git a/hw/misc/xlnx-versal-crl.c b/hw/misc/xlnx-versal-crl.c
index 1f1762e..f143900 100644
--- a/hw/misc/xlnx-versal-crl.c
+++ b/hw/misc/xlnx-versal-crl.c
@@ -311,7 +311,7 @@
}
}
-static void crl_reset_hold(Object *obj)
+static void crl_reset_hold(Object *obj, ResetType type)
{
XlnxVersalCRL *s = XLNX_VERSAL_CRL(obj);
diff --git a/hw/misc/xlnx-versal-pmc-iou-slcr.c b/hw/misc/xlnx-versal-pmc-iou-slcr.c
index 60e13a7..e469c04 100644
--- a/hw/misc/xlnx-versal-pmc-iou-slcr.c
+++ b/hw/misc/xlnx-versal-pmc-iou-slcr.c
@@ -1350,7 +1350,7 @@
}
}
-static void xlnx_versal_pmc_iou_slcr_reset_hold(Object *obj)
+static void xlnx_versal_pmc_iou_slcr_reset_hold(Object *obj, ResetType type)
{
XlnxVersalPmcIouSlcr *s = XILINX_VERSAL_PMC_IOU_SLCR(obj);
diff --git a/hw/misc/xlnx-versal-trng.c b/hw/misc/xlnx-versal-trng.c
index 6495188..51eb760 100644
--- a/hw/misc/xlnx-versal-trng.c
+++ b/hw/misc/xlnx-versal-trng.c
@@ -632,7 +632,7 @@
s->prng = NULL;
}
-static void trng_reset_hold(Object *obj)
+static void trng_reset_hold(Object *obj, ResetType type)
{
trng_reset(XLNX_VERSAL_TRNG(obj));
}
diff --git a/hw/misc/xlnx-versal-xramc.c b/hw/misc/xlnx-versal-xramc.c
index a5f78c1..ad839ce 100644
--- a/hw/misc/xlnx-versal-xramc.c
+++ b/hw/misc/xlnx-versal-xramc.c
@@ -137,7 +137,7 @@
ARRAY_FIELD_DP32(s->regs, XRAM_IMP, SIZE, s->cfg.encoded_size);
}
-static void xram_ctrl_reset_hold(Object *obj)
+static void xram_ctrl_reset_hold(Object *obj, ResetType type)
{
XlnxXramCtrl *s = XLNX_XRAM_CTRL(obj);
diff --git a/hw/misc/xlnx-zynqmp-apu-ctrl.c b/hw/misc/xlnx-zynqmp-apu-ctrl.c
index 1d441b4..87e4a14 100644
--- a/hw/misc/xlnx-zynqmp-apu-ctrl.c
+++ b/hw/misc/xlnx-zynqmp-apu-ctrl.c
@@ -150,7 +150,7 @@
s->cpu_in_wfi = 0;
}
-static void zynqmp_apu_reset_hold(Object *obj)
+static void zynqmp_apu_reset_hold(Object *obj, ResetType type)
{
XlnxZynqMPAPUCtrl *s = XLNX_ZYNQMP_APU_CTRL(obj);
diff --git a/hw/misc/xlnx-zynqmp-crf.c b/hw/misc/xlnx-zynqmp-crf.c
index a83efb44..e5aba56 100644
--- a/hw/misc/xlnx-zynqmp-crf.c
+++ b/hw/misc/xlnx-zynqmp-crf.c
@@ -191,7 +191,7 @@
}
}
-static void crf_reset_hold(Object *obj)
+static void crf_reset_hold(Object *obj, ResetType type)
{
XlnxZynqMPCRF *s = XLNX_ZYNQMP_CRF(obj);
ir_update_irq(s);
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
index d2ac2e7..3412ff0 100644
--- a/hw/misc/zynq_slcr.c
+++ b/hw/misc/zynq_slcr.c
@@ -416,7 +416,7 @@
s->regs[R_DDRIOB + 12] = 0x00000021;
}
-static void zynq_slcr_reset_hold(Object *obj)
+static void zynq_slcr_reset_hold(Object *obj, ResetType type)
{
ZynqSLCRState *s = ZYNQ_SLCR(obj);
@@ -425,7 +425,7 @@
zynq_slcr_propagate_clocks(s);
}
-static void zynq_slcr_reset_exit(Object *obj)
+static void zynq_slcr_reset_exit(Object *obj, ResetType type)
{
ZynqSLCRState *s = ZYNQ_SLCR(obj);
diff --git a/hw/net/can/xlnx-zynqmp-can.c b/hw/net/can/xlnx-zynqmp-can.c
index ca0ce4e..58f1432 100644
--- a/hw/net/can/xlnx-zynqmp-can.c
+++ b/hw/net/can/xlnx-zynqmp-can.c
@@ -1006,7 +1006,7 @@
ptimer_transaction_commit(s->can_timer);
}
-static void xlnx_zynqmp_can_reset_hold(Object *obj)
+static void xlnx_zynqmp_can_reset_hold(Object *obj, ResetType type)
{
XlnxZynqMPCANState *s = XLNX_ZYNQMP_CAN(obj);
unsigned int i;
diff --git a/hw/net/e1000.c b/hw/net/e1000.c
index 43f3a4a..5012b96 100644
--- a/hw/net/e1000.c
+++ b/hw/net/e1000.c
@@ -373,7 +373,7 @@
return chkflag(VET);
}
-static void e1000_reset_hold(Object *obj)
+static void e1000_reset_hold(Object *obj, ResetType type)
{
E1000State *d = E1000(obj);
E1000BaseClass *edc = E1000_GET_CLASS(d);
diff --git a/hw/net/e1000e.c b/hw/net/e1000e.c
index 7c6f602..edc101e 100644
--- a/hw/net/e1000e.c
+++ b/hw/net/e1000e.c
@@ -513,7 +513,7 @@
msi_uninit(pci_dev);
}
-static void e1000e_qdev_reset_hold(Object *obj)
+static void e1000e_qdev_reset_hold(Object *obj, ResetType type)
{
E1000EState *s = E1000E(obj);
diff --git a/hw/net/igb.c b/hw/net/igb.c
index 9b37523..1ef6170 100644
--- a/hw/net/igb.c
+++ b/hw/net/igb.c
@@ -486,7 +486,7 @@
msi_uninit(pci_dev);
}
-static void igb_qdev_reset_hold(Object *obj)
+static void igb_qdev_reset_hold(Object *obj, ResetType type)
{
IGBState *s = IGB(obj);
diff --git a/hw/net/igbvf.c b/hw/net/igbvf.c
index 94a4e88..21a97d4 100644
--- a/hw/net/igbvf.c
+++ b/hw/net/igbvf.c
@@ -282,7 +282,7 @@
pcie_ari_init(dev, 0x150);
}
-static void igbvf_qdev_reset_hold(Object *obj)
+static void igbvf_qdev_reset_hold(Object *obj, ResetType type)
{
PCIDevice *vf = PCI_DEVICE(obj);
diff --git a/hw/net/imx_fec.c b/hw/net/imx_fec.c
index cee84af..8c91d20 100644
--- a/hw/net/imx_fec.c
+++ b/hw/net/imx_fec.c
@@ -41,7 +41,7 @@
static const char *imx_default_reg_name(IMXFECState *s, uint32_t index)
{
static char tmp[20];
- sprintf(tmp, "index %d", index);
+ snprintf(tmp, sizeof(tmp), "index %d", index);
return tmp;
}
diff --git a/hw/nvram/xlnx-bbram.c b/hw/nvram/xlnx-bbram.c
index 0a71a00..09575a7 100644
--- a/hw/nvram/xlnx-bbram.c
+++ b/hw/nvram/xlnx-bbram.c
@@ -417,7 +417,7 @@
}
};
-static void bbram_ctrl_reset_hold(Object *obj)
+static void bbram_ctrl_reset_hold(Object *obj, ResetType type)
{
XlnxBBRam *s = XLNX_BBRAM(obj);
unsigned int i;
diff --git a/hw/nvram/xlnx-versal-efuse-ctrl.c b/hw/nvram/xlnx-versal-efuse-ctrl.c
index e4b9e11..def6fe33 100644
--- a/hw/nvram/xlnx-versal-efuse-ctrl.c
+++ b/hw/nvram/xlnx-versal-efuse-ctrl.c
@@ -658,7 +658,7 @@
register_reset(reg);
}
-static void efuse_ctrl_reset_hold(Object *obj)
+static void efuse_ctrl_reset_hold(Object *obj, ResetType type)
{
XlnxVersalEFuseCtrl *s = XLNX_VERSAL_EFUSE_CTRL(obj);
unsigned int i;
diff --git a/hw/nvram/xlnx-zynqmp-efuse.c b/hw/nvram/xlnx-zynqmp-efuse.c
index ec98456..2d465f0 100644
--- a/hw/nvram/xlnx-zynqmp-efuse.c
+++ b/hw/nvram/xlnx-zynqmp-efuse.c
@@ -770,7 +770,7 @@
register_reset(reg);
}
-static void zynqmp_efuse_reset_hold(Object *obj)
+static void zynqmp_efuse_reset_hold(Object *obj, ResetType type)
{
XlnxZynqMPEFuse *s = XLNX_ZYNQMP_EFUSE(obj);
unsigned int i;
diff --git a/hw/pci-bridge/cxl_root_port.c b/hw/pci-bridge/cxl_root_port.c
index 8a30da6..2dd1023 100644
--- a/hw/pci-bridge/cxl_root_port.c
+++ b/hw/pci-bridge/cxl_root_port.c
@@ -186,13 +186,13 @@
component_bar);
}
-static void cxl_rp_reset_hold(Object *obj)
+static void cxl_rp_reset_hold(Object *obj, ResetType type)
{
PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(obj);
CXLRootPort *crp = CXL_ROOT_PORT(obj);
if (rpc->parent_phases.hold) {
- rpc->parent_phases.hold(obj);
+ rpc->parent_phases.hold(obj, type);
}
latch_registers(crp);
diff --git a/hw/pci-bridge/cxl_upstream.c b/hw/pci-bridge/cxl_upstream.c
index 783fa6a..e51221a 100644
--- a/hw/pci-bridge/cxl_upstream.c
+++ b/hw/pci-bridge/cxl_upstream.c
@@ -338,8 +338,7 @@
cxl_cstate->cdat.build_cdat_table = build_cdat_table;
cxl_cstate->cdat.free_cdat_table = free_default_cdat_table;
cxl_cstate->cdat.private = d;
- cxl_doe_cdat_init(cxl_cstate, errp);
- if (*errp) {
+ if (!cxl_doe_cdat_init(cxl_cstate, errp)) {
goto err_cap;
}
diff --git a/hw/pci-bridge/pcie_root_port.c b/hw/pci-bridge/pcie_root_port.c
index efd96bf..09a3478 100644
--- a/hw/pci-bridge/pcie_root_port.c
+++ b/hw/pci-bridge/pcie_root_port.c
@@ -43,7 +43,7 @@
pcie_aer_root_write_config(d, address, val, len, root_cmd);
}
-static void rp_reset_hold(Object *obj)
+static void rp_reset_hold(Object *obj, ResetType type)
{
PCIDevice *d = PCI_DEVICE(obj);
DeviceState *qdev = DEVICE(obj);
diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c
index 1f0c435..1516d00 100644
--- a/hw/pci-host/bonito.c
+++ b/hw/pci-host/bonito.c
@@ -590,7 +590,7 @@
}
}
-static void bonito_reset_hold(Object *obj)
+static void bonito_reset_hold(Object *obj, ResetType type)
{
PCIBonitoState *s = PCI_BONITO(obj);
uint32_t val = 0;
diff --git a/hw/pci-host/pnv_phb.c b/hw/pci-host/pnv_phb.c
index 157c007..d4c118d 100644
--- a/hw/pci-host/pnv_phb.c
+++ b/hw/pci-host/pnv_phb.c
@@ -208,7 +208,7 @@
dc->user_creatable = true;
}
-static void pnv_phb_root_port_reset_hold(Object *obj)
+static void pnv_phb_root_port_reset_hold(Object *obj, ResetType type)
{
PCIERootPortClass *rpc = PCIE_ROOT_PORT_GET_CLASS(obj);
PnvPHBRootPort *phb_rp = PNV_PHB_ROOT_PORT(obj);
@@ -216,7 +216,7 @@
uint8_t *conf = d->config;
if (rpc->parent_phases.hold) {
- rpc->parent_phases.hold(obj);
+ rpc->parent_phases.hold(obj, type);
}
if (phb_rp->version == 3) {
diff --git a/hw/pci-host/pnv_phb3_msi.c b/hw/pci-host/pnv_phb3_msi.c
index dc8d863..a6d827f 100644
--- a/hw/pci-host/pnv_phb3_msi.c
+++ b/hw/pci-host/pnv_phb3_msi.c
@@ -228,13 +228,13 @@
}
}
-static void phb3_msi_reset_hold(Object *obj)
+static void phb3_msi_reset_hold(Object *obj, ResetType type)
{
Phb3MsiState *msi = PHB3_MSI(obj);
ICSStateClass *icsc = ICS_GET_CLASS(obj);
if (icsc->parent_phases.hold) {
- icsc->parent_phases.hold(obj);
+ icsc->parent_phases.hold(obj, type);
}
memset(msi->rba, 0, sizeof(msi->rba));
diff --git a/hw/pci/pci.c b/hw/pci/pci.c
index e7a39cb..324c130 100644
--- a/hw/pci/pci.c
+++ b/hw/pci/pci.c
@@ -64,7 +64,7 @@
static char *pcibus_get_dev_path(DeviceState *dev);
static char *pcibus_get_fw_dev_path(DeviceState *dev);
-static void pcibus_reset_hold(Object *obj);
+static void pcibus_reset_hold(Object *obj, ResetType type);
static bool pcie_has_upstream_port(PCIDevice *dev);
static Property pci_props[] = {
@@ -427,7 +427,7 @@
* Called via bus_cold_reset on RST# assert, after the devices
* have been reset device_cold_reset-ed already.
*/
-static void pcibus_reset_hold(Object *obj)
+static void pcibus_reset_hold(Object *obj, ResetType type)
{
PCIBus *bus = PCI_BUS(obj);
int i;
diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
index 5d644eb..fc72ef0 100644
--- a/hw/riscv/Kconfig
+++ b/hw/riscv/Kconfig
@@ -9,6 +9,7 @@
config MICROCHIP_PFSOC
bool
select CADENCE_SDHCI
+ select CPU_CLUSTER
select MCHP_PFSOC_DMC
select MCHP_PFSOC_IOSCB
select MCHP_PFSOC_MMUART
@@ -68,6 +69,7 @@
config SIFIVE_U
bool
select CADENCE
+ select CPU_CLUSTER
select RISCV_ACLINT
select SIFIVE_GPIO
select SIFIVE_PDMA
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index d171e74..4fdb660 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -1617,10 +1617,8 @@
static char *virt_get_aia_guests(Object *obj, Error **errp)
{
RISCVVirtState *s = RISCV_VIRT_MACHINE(obj);
- char val[32];
- sprintf(val, "%d", s->aia_guests);
- return g_strdup(val);
+ return g_strdup_printf("%d", s->aia_guests);
}
static void virt_set_aia_guests(Object *obj, const char *val, Error **errp)
@@ -1741,7 +1739,6 @@
static void virt_machine_class_init(ObjectClass *oc, void *data)
{
- char str[128];
MachineClass *mc = MACHINE_CLASS(oc);
HotplugHandlerClass *hc = HOTPLUG_HANDLER_CLASS(oc);
@@ -1767,7 +1764,6 @@
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",
@@ -1785,9 +1781,14 @@
object_class_property_add_str(oc, "aia-guests",
virt_get_aia_guests,
virt_set_aia_guests);
- sprintf(str, "Set number of guest MMIO pages for AIA IMSIC. Valid value "
- "should be between 0 and %d.", VIRT_IRQCHIP_MAX_GUESTS);
- object_class_property_set_description(oc, "aia-guests", str);
+ {
+ g_autofree char *str =
+ g_strdup_printf("Set number of guest MMIO pages for AIA IMSIC. "
+ "Valid value should be between 0 and %d.",
+ VIRT_IRQCHIP_MAX_GUESTS);
+ object_class_property_set_description(oc, "aia-guests", str);
+ }
+
object_class_property_add(oc, "acpi", "OnOffAuto",
virt_get_acpi, virt_set_acpi,
NULL, NULL);
diff --git a/hw/rtc/mc146818rtc.c b/hw/rtc/mc146818rtc.c
index f4c1869..3379f92 100644
--- a/hw/rtc/mc146818rtc.c
+++ b/hw/rtc/mc146818rtc.c
@@ -998,7 +998,7 @@
}
}
-static void rtc_reset_hold(Object *obj)
+static void rtc_reset_hold(Object *obj, ResetType type)
{
MC146818RtcState *s = MC146818_RTC(obj);
diff --git a/hw/s390x/css-bridge.c b/hw/s390x/css-bridge.c
index 34639f2..8657ff7 100644
--- a/hw/s390x/css-bridge.c
+++ b/hw/s390x/css-bridge.c
@@ -56,7 +56,7 @@
qdev_unrealize(dev);
}
-static void virtual_css_bus_reset_hold(Object *obj)
+static void virtual_css_bus_reset_hold(Object *obj, ResetType type)
{
/* This should actually be modelled via the generic css */
css_reset();
diff --git a/hw/s390x/s390-stattrib.c b/hw/s390x/s390-stattrib.c
index bc04187..c4259b5 100644
--- a/hw/s390x/s390-stattrib.c
+++ b/hw/s390x/s390-stattrib.c
@@ -19,6 +19,7 @@
#include "exec/ram_addr.h"
#include "qapi/error.h"
#include "qapi/qmp/qdict.h"
+#include "cpu.h"
/* 512KiB cover 2GB of guest memory */
#define CMMA_BLOCK_SIZE (512 * KiB)
diff --git a/hw/s390x/s390-virtio-hcall.h b/hw/s390x/s390-virtio-hcall.h
index 9800c4b..3ae6d6a 100644
--- a/hw/s390x/s390-virtio-hcall.h
+++ b/hw/s390x/s390-virtio-hcall.h
@@ -13,6 +13,7 @@
#define HW_S390_VIRTIO_HCALL_H
#include "standard-headers/asm-s390/virtio-ccw.h"
+#include "cpu.h"
/* The only thing that we need from the old kvm_virtio.h file */
#define KVM_S390_VIRTIO_NOTIFY 0
@@ -20,4 +21,5 @@
typedef int (*s390_virtio_fn)(const uint64_t *args);
void s390_register_virtio_hypercall(uint64_t code, s390_virtio_fn fn);
int s390_virtio_hypercall(CPUS390XState *env);
+
#endif /* HW_S390_VIRTIO_HCALL_H */
diff --git a/hw/sensor/adm1266.c b/hw/sensor/adm1266.c
index 5454b73..25b87a7 100644
--- a/hw/sensor/adm1266.c
+++ b/hw/sensor/adm1266.c
@@ -76,7 +76,7 @@
static const uint8_t adm1266_ic_device_rev[] = {0x08, 0x01, 0x08, 0x07, 0x0,
0x0, 0x07, 0x41, 0x30};
-static void adm1266_exit_reset(Object *obj)
+static void adm1266_exit_reset(Object *obj, ResetType type)
{
ADM1266State *s = ADM1266(obj);
PMBusDevice *pmdev = PMBUS_DEVICE(obj);
diff --git a/hw/sensor/adm1272.c b/hw/sensor/adm1272.c
index 1f7c8ab..3fc1e5d 100644
--- a/hw/sensor/adm1272.c
+++ b/hw/sensor/adm1272.c
@@ -185,7 +185,7 @@
return pmbus_direct_mode2data(c, value);
}
-static void adm1272_exit_reset(Object *obj)
+static void adm1272_exit_reset(Object *obj, ResetType type)
{
ADM1272State *s = ADM1272(obj);
PMBusDevice *pmdev = PMBUS_DEVICE(obj);
@@ -386,7 +386,7 @@
break;
case ADM1272_MFR_POWER_CYCLE:
- adm1272_exit_reset((Object *)s);
+ device_cold_reset(DEVICE(s));
break;
case ADM1272_HYSTERESIS_LOW:
diff --git a/hw/sensor/isl_pmbus_vr.c b/hw/sensor/isl_pmbus_vr.c
index e51269f..304a66e 100644
--- a/hw/sensor/isl_pmbus_vr.c
+++ b/hw/sensor/isl_pmbus_vr.c
@@ -63,7 +63,7 @@
pmbus_check_limits(pmdev);
}
-static void isl_pmbus_vr_exit_reset(Object *obj)
+static void isl_pmbus_vr_exit_reset(Object *obj, ResetType type)
{
PMBusDevice *pmdev = PMBUS_DEVICE(obj);
@@ -102,11 +102,11 @@
}
/* The raa228000 uses different direct mode coefficients from most isl devices */
-static void raa228000_exit_reset(Object *obj)
+static void raa228000_exit_reset(Object *obj, ResetType type)
{
PMBusDevice *pmdev = PMBUS_DEVICE(obj);
- isl_pmbus_vr_exit_reset(obj);
+ isl_pmbus_vr_exit_reset(obj, type);
pmdev->pages[0].read_iout = 0;
pmdev->pages[0].read_pout = 0;
@@ -119,13 +119,13 @@
pmdev->pages[0].read_temperature_3 = 0;
}
-static void isl69259_exit_reset(Object *obj)
+static void isl69259_exit_reset(Object *obj, ResetType type)
{
ISLState *s = ISL69260(obj);
static const uint8_t ic_device_id[] = {0x04, 0x00, 0x81, 0xD2, 0x49, 0x3c};
g_assert(sizeof(ic_device_id) <= sizeof(s->ic_device_id));
- isl_pmbus_vr_exit_reset(obj);
+ isl_pmbus_vr_exit_reset(obj, type);
s->ic_device_id_len = sizeof(ic_device_id);
memcpy(s->ic_device_id, ic_device_id, sizeof(ic_device_id));
diff --git a/hw/sensor/max31785.c b/hw/sensor/max31785.c
index 916ed4d..3577a7c 100644
--- a/hw/sensor/max31785.c
+++ b/hw/sensor/max31785.c
@@ -444,7 +444,7 @@
return 0;
}
-static void max31785_exit_reset(Object *obj)
+static void max31785_exit_reset(Object *obj, ResetType type)
{
PMBusDevice *pmdev = PMBUS_DEVICE(obj);
MAX31785State *s = MAX31785(obj);
diff --git a/hw/sensor/max34451.c b/hw/sensor/max34451.c
index 031ae53..93b53f3 100644
--- a/hw/sensor/max34451.c
+++ b/hw/sensor/max34451.c
@@ -608,7 +608,7 @@
return s;
}
-static void max34451_exit_reset(Object *obj)
+static void max34451_exit_reset(Object *obj, ResetType type)
{
PMBusDevice *pmdev = PMBUS_DEVICE(obj);
MAX34451State *s = MAX34451(obj);
diff --git a/hw/ssi/imx_spi.c b/hw/ssi/imx_spi.c
index d8a7583..12d897d 100644
--- a/hw/ssi/imx_spi.c
+++ b/hw/ssi/imx_spi.c
@@ -53,7 +53,7 @@
case ECSPI_MSGDATA:
return "ECSPI_MSGDATA";
default:
- sprintf(unknown, "%u ?", reg);
+ snprintf(unknown, sizeof(unknown), "%u ?", reg);
return unknown;
}
}
diff --git a/hw/ssi/npcm7xx_fiu.c b/hw/ssi/npcm7xx_fiu.c
index 81dd972..119c38c 100644
--- a/hw/ssi/npcm7xx_fiu.c
+++ b/hw/ssi/npcm7xx_fiu.c
@@ -483,7 +483,7 @@
s->regs[NPCM7XX_FIU_CFG] = 0x0000000b;
}
-static void npcm7xx_fiu_hold_reset(Object *obj)
+static void npcm7xx_fiu_hold_reset(Object *obj, ResetType type)
{
NPCM7xxFIUState *s = NPCM7XX_FIU(obj);
int i;
diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c
index da7c946..dd6d96b 100644
--- a/hw/timer/etraxfs_timer.c
+++ b/hw/timer/etraxfs_timer.c
@@ -357,7 +357,7 @@
t->rw_intr_mask = 0;
}
-static void etraxfs_timer_reset_hold(Object *obj)
+static void etraxfs_timer_reset_hold(Object *obj, ResetType type)
{
ETRAXTimerState *t = ETRAX_TIMER(obj);
diff --git a/hw/timer/npcm7xx_timer.c b/hw/timer/npcm7xx_timer.c
index 779c604..c55ba02 100644
--- a/hw/timer/npcm7xx_timer.c
+++ b/hw/timer/npcm7xx_timer.c
@@ -592,7 +592,7 @@
}
}
-static void npcm7xx_timer_hold_reset(Object *obj)
+static void npcm7xx_timer_hold_reset(Object *obj, ResetType type)
{
NPCM7xxTimerCtrlState *s = NPCM7XX_TIMER(obj);
int i;
diff --git a/hw/usb/hcd-dwc2.c b/hw/usb/hcd-dwc2.c
index 222eef8..8cac9c0 100644
--- a/hw/usb/hcd-dwc2.c
+++ b/hw/usb/hcd-dwc2.c
@@ -1305,7 +1305,7 @@
}
}
-static void dwc2_reset_hold(Object *obj)
+static void dwc2_reset_hold(Object *obj, ResetType type)
{
DWC2Class *c = DWC2_USB_GET_CLASS(obj);
DWC2State *s = DWC2_USB(obj);
@@ -1313,13 +1313,13 @@
trace_usb_dwc2_reset_hold();
if (c->parent_phases.hold) {
- c->parent_phases.hold(obj);
+ c->parent_phases.hold(obj, type);
}
dwc2_update_irq(s);
}
-static void dwc2_reset_exit(Object *obj)
+static void dwc2_reset_exit(Object *obj, ResetType type)
{
DWC2Class *c = DWC2_USB_GET_CLASS(obj);
DWC2State *s = DWC2_USB(obj);
@@ -1327,7 +1327,7 @@
trace_usb_dwc2_reset_exit();
if (c->parent_phases.exit) {
- c->parent_phases.exit(obj);
+ c->parent_phases.exit(obj, type);
}
s->hprt0 = HPRT0_PWR;
diff --git a/hw/usb/xlnx-versal-usb2-ctrl-regs.c b/hw/usb/xlnx-versal-usb2-ctrl-regs.c
index 6fc4538..66c793a 100644
--- a/hw/usb/xlnx-versal-usb2-ctrl-regs.c
+++ b/hw/usb/xlnx-versal-usb2-ctrl-regs.c
@@ -153,7 +153,7 @@
}
}
-static void usb2_ctrl_regs_reset_hold(Object *obj)
+static void usb2_ctrl_regs_reset_hold(Object *obj, ResetType type)
{
VersalUsb2CtrlRegs *s = XILINX_VERSAL_USB2_CTRL_REGS(obj);
diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
index cb159fd..b1d02f4 100644
--- a/hw/virtio/virtio-pci.c
+++ b/hw/virtio/virtio-pci.c
@@ -2292,7 +2292,7 @@
}
}
-static void virtio_pci_bus_reset_hold(Object *obj)
+static void virtio_pci_bus_reset_hold(Object *obj, ResetType type)
{
PCIDevice *dev = PCI_DEVICE(obj);
DeviceState *qdev = DEVICE(obj);
diff --git a/hw/xtensa/bootparam.h b/hw/xtensa/bootparam.h
index ade7891..f57ff85 100644
--- a/hw/xtensa/bootparam.h
+++ b/hw/xtensa/bootparam.h
@@ -1,6 +1,8 @@
#ifndef HW_XTENSA_BOOTPARAM_H
#define HW_XTENSA_BOOTPARAM_H
+#include "exec/cpu-common.h"
+
#define BP_TAG_COMMAND_LINE 0x1001 /* command line (0-terminated string)*/
#define BP_TAG_INITRD 0x1002 /* ramdisk addr and size (bp_meminfo) */
#define BP_TAG_MEMORY 0x1003 /* memory addr and size (bp_meminfo) */
diff --git a/include/hw/arm/stm32l4x5_soc.h b/include/hw/arm/stm32l4x5_soc.h
index ee5f362..c243fb0 100644
--- a/include/hw/arm/stm32l4x5_soc.h
+++ b/include/hw/arm/stm32l4x5_soc.h
@@ -31,6 +31,7 @@
#include "hw/misc/stm32l4x5_exti.h"
#include "hw/misc/stm32l4x5_rcc.h"
#include "hw/gpio/stm32l4x5_gpio.h"
+#include "hw/char/stm32l4x5_usart.h"
#include "qom/object.h"
#define TYPE_STM32L4X5_SOC "stm32l4x5-soc"
@@ -41,6 +42,9 @@
#define NUM_EXTI_OR_GATES 4
+#define STM_NUM_USARTS 3
+#define STM_NUM_UARTS 2
+
struct Stm32l4x5SocState {
SysBusDevice parent_obj;
@@ -51,6 +55,9 @@
Stm32l4x5SyscfgState syscfg;
Stm32l4x5RccState rcc;
Stm32l4x5GpioState gpio[NUM_GPIOS];
+ Stm32l4x5UsartBaseState usart[STM_NUM_USARTS];
+ Stm32l4x5UsartBaseState uart[STM_NUM_UARTS];
+ Stm32l4x5UsartBaseState lpuart;
MemoryRegion sram1;
MemoryRegion sram2;
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 69c1ba4..2fa800f 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -144,6 +144,7 @@
* provided SMP configuration
* @books_supported - whether books are supported by the machine
* @drawers_supported - whether drawers are supported by the machine
+ * @modules_supported - whether modules are supported by the machine
*/
typedef struct {
bool prefer_sockets;
@@ -152,6 +153,7 @@
bool has_clusters;
bool books_supported;
bool drawers_supported;
+ bool modules_supported;
} SMPCompatProps;
/**
@@ -339,6 +341,7 @@
* @sockets: the number of sockets in one book
* @dies: the number of dies in one socket
* @clusters: the number of clusters in one die
+ * @modules: the number of modules in one cluster
* @cores: the number of cores in one cluster
* @threads: the number of threads in one core
* @max_cpus: the maximum number of logical processors on the machine
@@ -350,6 +353,7 @@
unsigned int sockets;
unsigned int dies;
unsigned int clusters;
+ unsigned int modules;
unsigned int cores;
unsigned int threads;
unsigned int max_cpus;
diff --git a/include/hw/char/stm32l4x5_usart.h b/include/hw/char/stm32l4x5_usart.h
new file mode 100644
index 0000000..dd38666
--- /dev/null
+++ b/include/hw/char/stm32l4x5_usart.h
@@ -0,0 +1,67 @@
+/*
+ * STM32L4X5 USART (Universal Synchronous Asynchronous Receiver Transmitter)
+ *
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ *
+ * The STM32L4X5 USART is heavily inspired by the stm32f2xx_usart
+ * by Alistair Francis.
+ * The reference used is the STMicroElectronics RM0351 Reference manual
+ * for STM32L4x5 and STM32L4x6 advanced Arm ® -based 32-bit MCUs.
+ */
+
+#ifndef HW_STM32L4X5_USART_H
+#define HW_STM32L4X5_USART_H
+
+#include "hw/sysbus.h"
+#include "chardev/char-fe.h"
+#include "qom/object.h"
+
+#define TYPE_STM32L4X5_USART_BASE "stm32l4x5-usart-base"
+#define TYPE_STM32L4X5_USART "stm32l4x5-usart"
+#define TYPE_STM32L4X5_UART "stm32l4x5-uart"
+#define TYPE_STM32L4X5_LPUART "stm32l4x5-lpuart"
+OBJECT_DECLARE_TYPE(Stm32l4x5UsartBaseState, Stm32l4x5UsartBaseClass,
+ STM32L4X5_USART_BASE)
+
+typedef enum {
+ STM32L4x5_USART,
+ STM32L4x5_UART,
+ STM32L4x5_LPUART,
+} Stm32l4x5UsartType;
+
+struct Stm32l4x5UsartBaseState {
+ SysBusDevice parent_obj;
+
+ MemoryRegion mmio;
+
+ uint32_t cr1;
+ uint32_t cr2;
+ uint32_t cr3;
+ uint32_t brr;
+ uint32_t gtpr;
+ uint32_t rtor;
+ /* rqr is write-only */
+ uint32_t isr;
+ /* icr is a clear register */
+ uint32_t rdr;
+ uint32_t tdr;
+
+ Clock *clk;
+ CharBackend chr;
+ qemu_irq irq;
+ guint watch_tag;
+};
+
+struct Stm32l4x5UsartBaseClass {
+ SysBusDeviceClass parent_class;
+
+ Stm32l4x5UsartType type;
+};
+
+#endif /* HW_STM32L4X5_USART_H */
diff --git a/include/hw/core/tcg-cpu-ops.h b/include/hw/core/tcg-cpu-ops.h
index bf8ff8e..dc1f16a 100644
--- a/include/hw/core/tcg-cpu-ops.h
+++ b/include/hw/core/tcg-cpu-ops.h
@@ -49,7 +49,6 @@
/** @debug_excp_handler: Callback for handling debug exceptions */
void (*debug_excp_handler)(CPUState *cpu);
-#ifdef NEED_CPU_H
#ifdef CONFIG_USER_ONLY
/**
* @fake_user_interrupt: Callback for 'fake exception' handling.
@@ -174,8 +173,6 @@
*/
bool (*need_replay_interrupt)(int interrupt_request);
#endif /* !CONFIG_USER_ONLY */
-#endif /* NEED_CPU_H */
-
};
#if defined(CONFIG_USER_ONLY)
diff --git a/include/hw/cxl/cxl_component.h b/include/hw/cxl/cxl_component.h
index 5012fab..945ee6f 100644
--- a/include/hw/cxl/cxl_component.h
+++ b/include/hw/cxl/cxl_component.h
@@ -273,7 +273,7 @@
CXLComponentState *cxl_get_hb_cstate(PCIHostState *hb);
bool cxl_get_hb_passthrough(PCIHostState *hb);
-void cxl_doe_cdat_init(CXLComponentState *cxl_cstate, Error **errp);
+bool cxl_doe_cdat_init(CXLComponentState *cxl_cstate, Error **errp);
void cxl_doe_cdat_release(CXLComponentState *cxl_cstate);
void cxl_doe_cdat_update(CXLComponentState *cxl_cstate, Error **errp);
diff --git a/include/hw/elf_ops.h b/include/hw/elf_ops.h.inc
similarity index 100%
rename from include/hw/elf_ops.h
rename to include/hw/elf_ops.h.inc
diff --git a/include/hw/intc/arm_gic_common.h b/include/hw/intc/arm_gic_common.h
index 7080375..97fea41 100644
--- a/include/hw/intc/arm_gic_common.h
+++ b/include/hw/intc/arm_gic_common.h
@@ -71,6 +71,8 @@
qemu_irq parent_fiq[GIC_NCPU];
qemu_irq parent_virq[GIC_NCPU];
qemu_irq parent_vfiq[GIC_NCPU];
+ qemu_irq parent_nmi[GIC_NCPU];
+ qemu_irq parent_vnmi[GIC_NCPU];
qemu_irq maintenance_irq[GIC_NCPU];
/* GICD_CTLR; for a GIC with the security extensions the NS banked version
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
index 4e2fb51..cd09bee 100644
--- a/include/hw/intc/arm_gicv3_common.h
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -146,6 +146,7 @@
int irq;
uint8_t prio;
int grp;
+ bool nmi;
} PendingIrq;
struct GICv3CPUState {
@@ -155,6 +156,8 @@
qemu_irq parent_fiq;
qemu_irq parent_virq;
qemu_irq parent_vfiq;
+ qemu_irq parent_nmi;
+ qemu_irq parent_vnmi;
/* Redistributor */
uint32_t level; /* Current IRQ level */
@@ -170,6 +173,7 @@
uint32_t gicr_ienabler0;
uint32_t gicr_ipendr0;
uint32_t gicr_iactiver0;
+ uint32_t gicr_inmir0;
uint32_t edge_trigger; /* ICFGR0 and ICFGR1 even bits */
uint32_t gicr_igrpmodr0;
uint32_t gicr_nsacr;
@@ -221,6 +225,13 @@
/* This is temporary working state, to avoid a malloc in gicv3_update() */
bool seenbetter;
+
+ /*
+ * Whether the CPU interface has NMI support (FEAT_GICv3_NMI). The
+ * CPU interface may support NMIs even when the GIC proper (what the
+ * spec calls the IRI; the redistributors and distributor) does not.
+ */
+ bool nmi_support;
};
/*
@@ -247,6 +258,7 @@
uint32_t num_irq;
uint32_t revision;
bool lpi_enable;
+ bool nmi_support;
bool security_extn;
bool force_8bit_prio;
bool irq_reset_nonsecure;
@@ -272,6 +284,7 @@
GIC_DECLARE_BITMAP(active); /* GICD_ISACTIVER */
GIC_DECLARE_BITMAP(level); /* Current level */
GIC_DECLARE_BITMAP(edge_trigger); /* GICD_ICFGR even bits */
+ GIC_DECLARE_BITMAP(nmi); /* GICD_INMIR */
uint8_t gicd_ipriority[GICV3_MAXIRQ];
uint64_t gicd_irouter[GICV3_MAXIRQ];
/* Cached information: pointer to the cpu i/f for the CPUs specified
@@ -311,6 +324,7 @@
GICV3_BITMAP_ACCESSORS(active)
GICV3_BITMAP_ACCESSORS(level)
GICV3_BITMAP_ACCESSORS(edge_trigger)
+GICV3_BITMAP_ACCESSORS(nmi)
#define TYPE_ARM_GICV3_COMMON "arm-gicv3-common"
typedef struct ARMGICv3CommonClass ARMGICv3CommonClass;
diff --git a/include/hw/resettable.h b/include/hw/resettable.h
index bdcd127..7e249de 100644
--- a/include/hw/resettable.h
+++ b/include/hw/resettable.h
@@ -35,6 +35,7 @@
*/
typedef enum ResetType {
RESET_TYPE_COLD,
+ RESET_TYPE_SNAPSHOT_LOAD,
} ResetType;
/*
@@ -103,8 +104,8 @@
* the callback.
*/
typedef void (*ResettableEnterPhase)(Object *obj, ResetType type);
-typedef void (*ResettableHoldPhase)(Object *obj);
-typedef void (*ResettableExitPhase)(Object *obj);
+typedef void (*ResettableHoldPhase)(Object *obj, ResetType type);
+typedef void (*ResettableExitPhase)(Object *obj, ResetType type);
typedef ResettableState * (*ResettableGetState)(Object *obj);
typedef void (*ResettableTrFunction)(Object *obj);
typedef ResettableTrFunction (*ResettableGetTrFunction)(Object *obj);
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index f4a0b78..a0999da 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -3572,7 +3572,7 @@
return "";
}
-/* FIXME: This should use elf_ops.h */
+/* FIXME: This should use elf_ops.h.inc */
static int symcmp(const void *s0, const void *s1)
{
struct elf_sym *sym0 = (struct elf_sym *)s0;
diff --git a/linux-user/flat.h b/linux-user/flat.h
index ed518e2..e374b73 100644
--- a/linux-user/flat.h
+++ b/linux-user/flat.h
@@ -12,11 +12,8 @@
#define FLAT_VERSION 0x00000004L
-#ifdef CONFIG_BINFMT_SHARED_FLAT
-#define MAX_SHARED_LIBS (4)
-#else
+/* QEMU doesn't support bflt shared libraries */
#define MAX_SHARED_LIBS (1)
-#endif
/*
* To make everything easier to port and manage cross platform
diff --git a/linux-user/flatload.c b/linux-user/flatload.c
index 5b62aa0..04d8138 100644
--- a/linux-user/flatload.c
+++ b/linux-user/flatload.c
@@ -29,8 +29,6 @@
* JAN/99 -- coded full program relocation (gerg@snapgear.com)
*/
-/* ??? ZFLAT and shared library support is currently disabled. */
-
/****************************************************************************/
#include "qemu/osdep.h"
@@ -64,10 +62,6 @@
short loaded; /* Has this library been loaded? */
};
-#ifdef CONFIG_BINFMT_SHARED_FLAT
-static int load_flat_shared_library(int id, struct lib_info *p);
-#endif
-
struct linux_binprm;
/****************************************************************************/
@@ -108,153 +102,6 @@
unlock_user(buf, ptr, len);
return ret;
}
-/****************************************************************************/
-
-#ifdef CONFIG_BINFMT_ZFLAT
-
-#include <linux/zlib.h>
-
-#define LBUFSIZE 4000
-
-/* gzip flag byte */
-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ASCII text */
-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */
-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */
-#define ORIG_NAME 0x08 /* bit 3 set: original file name present */
-#define COMMENT 0x10 /* bit 4 set: file comment present */
-#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */
-#define RESERVED 0xC0 /* bit 6,7: reserved */
-
-static int decompress_exec(
- struct linux_binprm *bprm,
- unsigned long offset,
- char *dst,
- long len,
- int fd)
-{
- unsigned char *buf;
- z_stream strm;
- loff_t fpos;
- int ret, retval;
-
- DBG_FLT("decompress_exec(offset=%x,buf=%x,len=%x)\n",(int)offset, (int)dst, (int)len);
-
- memset(&strm, 0, sizeof(strm));
- strm.workspace = kmalloc(zlib_inflate_workspacesize(), GFP_KERNEL);
- if (strm.workspace == NULL) {
- DBG_FLT("binfmt_flat: no memory for decompress workspace\n");
- return -ENOMEM;
- }
- buf = kmalloc(LBUFSIZE, GFP_KERNEL);
- if (buf == NULL) {
- DBG_FLT("binfmt_flat: no memory for read buffer\n");
- retval = -ENOMEM;
- goto out_free;
- }
-
- /* Read in first chunk of data and parse gzip header. */
- fpos = offset;
- ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
-
- strm.next_in = buf;
- strm.avail_in = ret;
- strm.total_in = 0;
-
- retval = -ENOEXEC;
-
- /* Check minimum size -- gzip header */
- if (ret < 10) {
- DBG_FLT("binfmt_flat: file too small?\n");
- goto out_free_buf;
- }
-
- /* Check gzip magic number */
- if ((buf[0] != 037) || ((buf[1] != 0213) && (buf[1] != 0236))) {
- DBG_FLT("binfmt_flat: unknown compression magic?\n");
- goto out_free_buf;
- }
-
- /* Check gzip method */
- if (buf[2] != 8) {
- DBG_FLT("binfmt_flat: unknown compression method?\n");
- goto out_free_buf;
- }
- /* Check gzip flags */
- if ((buf[3] & ENCRYPTED) || (buf[3] & CONTINUATION) ||
- (buf[3] & RESERVED)) {
- DBG_FLT("binfmt_flat: unknown flags?\n");
- goto out_free_buf;
- }
-
- ret = 10;
- if (buf[3] & EXTRA_FIELD) {
- ret += 2 + buf[10] + (buf[11] << 8);
- if (unlikely(LBUFSIZE == ret)) {
- DBG_FLT("binfmt_flat: buffer overflow (EXTRA)?\n");
- goto out_free_buf;
- }
- }
- if (buf[3] & ORIG_NAME) {
- for (; ret < LBUFSIZE && (buf[ret] != 0); ret++)
- ;
- if (unlikely(LBUFSIZE == ret)) {
- DBG_FLT("binfmt_flat: buffer overflow (ORIG_NAME)?\n");
- goto out_free_buf;
- }
- }
- if (buf[3] & COMMENT) {
- for (; ret < LBUFSIZE && (buf[ret] != 0); ret++)
- ;
- if (unlikely(LBUFSIZE == ret)) {
- DBG_FLT("binfmt_flat: buffer overflow (COMMENT)?\n");
- goto out_free_buf;
- }
- }
-
- strm.next_in += ret;
- strm.avail_in -= ret;
-
- strm.next_out = dst;
- strm.avail_out = len;
- strm.total_out = 0;
-
- if (zlib_inflateInit2(&strm, -MAX_WBITS) != Z_OK) {
- DBG_FLT("binfmt_flat: zlib init failed?\n");
- goto out_free_buf;
- }
-
- while ((ret = zlib_inflate(&strm, Z_NO_FLUSH)) == Z_OK) {
- ret = bprm->file->f_op->read(bprm->file, buf, LBUFSIZE, &fpos);
- if (ret <= 0)
- break;
- if (is_error(ret)) {
- break;
- }
- len -= ret;
-
- strm.next_in = buf;
- strm.avail_in = ret;
- strm.total_in = 0;
- }
-
- if (ret < 0) {
- DBG_FLT("binfmt_flat: decompression failed (%d), %s\n",
- ret, strm.msg);
- goto out_zlib;
- }
-
- retval = 0;
-out_zlib:
- zlib_inflateEnd(&strm);
-out_free_buf:
- kfree(buf);
-out_free:
- kfree(strm.workspace);
-out:
- return retval;
-}
-
-#endif /* CONFIG_BINFMT_ZFLAT */
/****************************************************************************/
@@ -268,40 +115,7 @@
abi_ulong text_len;
abi_ulong start_code;
-#ifdef CONFIG_BINFMT_SHARED_FLAT
-#error needs checking
- if (r == 0)
- id = curid; /* Relocs of 0 are always self referring */
- else {
- id = (r >> 24) & 0xff; /* Find ID for this reloc */
- r &= 0x00ffffff; /* Trim ID off here */
- }
- if (id >= MAX_SHARED_LIBS) {
- fprintf(stderr, "BINFMT_FLAT: reference 0x%x to shared library %d\n",
- (unsigned) r, id);
- goto failed;
- }
- if (curid != id) {
- if (internalp) {
- fprintf(stderr, "BINFMT_FLAT: reloc address 0x%x not "
- "in same module (%d != %d)\n",
- (unsigned) r, curid, id);
- goto failed;
- } else if (!p[id].loaded && is_error(load_flat_shared_library(id, p))) {
- fprintf(stderr, "BINFMT_FLAT: failed to load library %d\n", id);
- goto failed;
- }
- /* Check versioning information (i.e. time stamps) */
- if (p[id].build_date && p[curid].build_date
- && p[curid].build_date < p[id].build_date) {
- fprintf(stderr, "BINFMT_FLAT: library %d is younger than %d\n",
- id, curid);
- goto failed;
- }
- }
-#else
id = 0;
-#endif
start_brk = p[id].start_brk;
start_data = p[id].start_data;
@@ -425,12 +239,10 @@
if (rev == OLD_FLAT_VERSION && flat_old_ram_flag(flags))
flags = FLAT_FLAG_RAM;
-#ifndef CONFIG_BINFMT_ZFLAT
if (flags & (FLAT_FLAG_GZIP|FLAT_FLAG_GZDATA)) {
- fprintf(stderr, "Support for ZFLAT executables is not enabled\n");
+ fprintf(stderr, "ZFLAT executables are not supported\n");
return -ENOEXEC;
}
-#endif
/*
* calculate the extra space we need to map in
@@ -483,17 +295,9 @@
(int)(data_len + bss_len + stack_len), (int)datapos);
fpos = ntohl(hdr->data_start);
-#ifdef CONFIG_BINFMT_ZFLAT
- if (flags & FLAT_FLAG_GZDATA) {
- result = decompress_exec(bprm, fpos, (char *) datapos,
- data_len + (relocs * sizeof(abi_ulong)))
- } else
-#endif
- {
- result = target_pread(bprm->src.fd, datapos,
- data_len + (relocs * sizeof(abi_ulong)),
- fpos);
- }
+ result = target_pread(bprm->src.fd, datapos,
+ data_len + (relocs * sizeof(abi_ulong)),
+ fpos);
if (result < 0) {
fprintf(stderr, "Unable to read data+bss\n");
return result;
@@ -515,38 +319,12 @@
datapos = realdatastart + indx_len;
reloc = (textpos + ntohl(hdr->reloc_start) + indx_len);
-#ifdef CONFIG_BINFMT_ZFLAT
-#error code needs checking
- /*
- * load it all in and treat it like a RAM load from now on
- */
- if (flags & FLAT_FLAG_GZIP) {
- result = decompress_exec(bprm, sizeof (struct flat_hdr),
- (((char *) textpos) + sizeof (struct flat_hdr)),
- (text_len + data_len + (relocs * sizeof(unsigned long))
- - sizeof (struct flat_hdr)),
- 0);
- memmove((void *) datapos, (void *) realdatastart,
- data_len + (relocs * sizeof(unsigned long)));
- } else if (flags & FLAT_FLAG_GZDATA) {
- fpos = 0;
- result = bprm->file->f_op->read(bprm->file,
- (char *) textpos, text_len, &fpos);
- if (!is_error(result)) {
- result = decompress_exec(bprm, text_len, (char *) datapos,
- data_len + (relocs * sizeof(unsigned long)), 0);
- }
- }
- else
-#endif
- {
- result = target_pread(bprm->src.fd, textpos,
- text_len, 0);
- if (result >= 0) {
- result = target_pread(bprm->src.fd, datapos,
- data_len + (relocs * sizeof(abi_ulong)),
- ntohl(hdr->data_start));
- }
+ result = target_pread(bprm->src.fd, textpos,
+ text_len, 0);
+ if (result >= 0) {
+ result = target_pread(bprm->src.fd, datapos,
+ data_len + (relocs * sizeof(abi_ulong)),
+ ntohl(hdr->data_start));
}
if (result < 0) {
fprintf(stderr, "Unable to read code+data+bss\n");
@@ -678,44 +456,6 @@
/****************************************************************************/
-#ifdef CONFIG_BINFMT_SHARED_FLAT
-
-/*
- * Load a shared library into memory. The library gets its own data
- * segment (including bss) but not argv/argc/environ.
- */
-
-static int load_flat_shared_library(int id, struct lib_info *libs)
-{
- struct linux_binprm bprm;
- int res;
- char buf[16];
-
- /* Create the file name */
- sprintf(buf, "/lib/lib%d.so", id);
-
- /* Open the file up */
- bprm.filename = buf;
- bprm.file = open_exec(bprm.filename);
- res = PTR_ERR(bprm.file);
- if (IS_ERR(bprm.file))
- return res;
-
- res = prepare_binprm(&bprm);
-
- if (!is_error(res)) {
- res = load_flat_file(&bprm, libs, id, NULL);
- }
- if (bprm.file) {
- allow_write_access(bprm.file);
- fput(bprm.file);
- bprm.file = NULL;
- }
- return(res);
-}
-
-#endif /* CONFIG_BINFMT_SHARED_FLAT */
-
int load_flt_binary(struct linux_binprm *bprm, struct image_info *info)
{
struct lib_info libinfo[MAX_SHARED_LIBS];
@@ -793,19 +533,6 @@
*/
start_addr = libinfo[0].entry;
-#ifdef CONFIG_BINFMT_SHARED_FLAT
-#error here
- for (i = MAX_SHARED_LIBS-1; i>0; i--) {
- if (libinfo[i].loaded) {
- /* Push previous first to call address */
- --sp;
- if (put_user_ual(start_addr, sp))
- return -EFAULT;
- start_addr = libinfo[i].entry;
- }
- }
-#endif
-
/* Stash our initial stack pointer into the mm structure */
info->start_code = libinfo[0].start_code;
info->end_code = libinfo[0].start_code + libinfo[0].text_len;
diff --git a/python/qemu/machine/machine.py b/python/qemu/machine/machine.py
index 31cb9d6..f648f6a 100644
--- a/python/qemu/machine/machine.py
+++ b/python/qemu/machine/machine.py
@@ -328,6 +328,11 @@
"""Returns the list of arguments given to the QEMU binary."""
return self._args
+ @property
+ def binary(self) -> str:
+ """Returns path to the QEMU binary"""
+ return self._binary
+
def _pre_launch(self) -> None:
if self._qmp_set:
if self._monitor_address is None:
diff --git a/qapi/machine.json b/qapi/machine.json
index 2df407e..bce6e1b 100644
--- a/qapi/machine.json
+++ b/qapi/machine.json
@@ -136,6 +136,26 @@
{ 'command': 'query-cpus-fast', 'returns': [ 'CpuInfoFast' ] }
##
+# @CompatProperty:
+#
+# Property default values specific to a machine type, for use by
+# scripts/compare-machine-types.
+#
+# @qom-type: name of the QOM type to which the default applies
+#
+# @property: name of its property to which the default applies
+#
+# @value: the default value (machine-specific default can overwrite
+# the "default" default, to avoid this use -machine none)
+#
+# Since: 9.1
+##
+{ 'struct': 'CompatProperty',
+ 'data': { 'qom-type': 'str',
+ 'property': 'str',
+ 'value': 'str' } }
+
+##
# @MachineInfo:
#
# Information describing a machine.
@@ -166,6 +186,14 @@
#
# @acpi: machine type supports ACPI (since 8.0)
#
+# @compat-props: The machine type's compatibility properties. Only
+# present when query-machines argument @compat-props is true.
+# (since 9.1)
+#
+# Features:
+#
+# @unstable: Member @compat-props is experimental.
+#
# Since: 1.2
##
{ 'struct': 'MachineInfo',
@@ -173,18 +201,53 @@
'*is-default': 'bool', 'cpu-max': 'int',
'hotpluggable-cpus': 'bool', 'numa-mem-supported': 'bool',
'deprecated': 'bool', '*default-cpu-type': 'str',
- '*default-ram-id': 'str', 'acpi': 'bool' } }
+ '*default-ram-id': 'str', 'acpi': 'bool',
+ '*compat-props': { 'type': ['CompatProperty'],
+ 'features': ['unstable'] } } }
##
# @query-machines:
#
# Return a list of supported machines
#
+# @compat-props: if true, also return compatibility properties.
+# (default: false) (since 9.1)
+#
+# Features:
+#
+# @unstable: Argument @compat-props is experimental.
+#
# Returns: a list of MachineInfo
#
# Since: 1.2
+#
+# Example:
+#
+# -> { "execute": "query-machines", "arguments": { "compat-props": true } }
+# <- { "return": [
+# {
+# "hotpluggable-cpus": true,
+# "name": "pc-q35-6.2",
+# "compat-props": [
+# {
+# "qom-type": "virtio-mem",
+# "property": "unplugged-inaccessible",
+# "value": "off"
+# }
+# ],
+# "numa-mem-supported": false,
+# "default-cpu-type": "qemu64-x86_64-cpu",
+# "cpu-max": 288,
+# "deprecated": false,
+# "default-ram-id": "pc.ram"
+# },
+# ...
+# }
##
-{ 'command': 'query-machines', 'returns': ['MachineInfo'] }
+{ 'command': 'query-machines',
+ 'data': { '*compat-props': { 'type': 'bool',
+ 'features': [ 'unstable' ] } },
+ 'returns': ['MachineInfo'] }
##
# @CurrentMachineParams:
@@ -925,6 +988,9 @@
# @cluster-id: cluster number within the parent container the CPU
# belongs to (since 7.1)
#
+# @module-id: module number within the parent container the CPU belongs
+# to (since 9.1)
+#
# @core-id: core number within the parent container the CPU belongs to
#
# @thread-id: thread number within the core the CPU belongs to
@@ -942,6 +1008,7 @@
'*socket-id': 'int',
'*die-id': 'int',
'*cluster-id': 'int',
+ '*module-id': 'int',
'*core-id': 'int',
'*thread-id': 'int'
}
@@ -1633,6 +1700,8 @@
#
# @clusters: number of clusters per parent container (since 7.0)
#
+# @modules: number of modules per parent container (since 9.1)
+#
# @cores: number of cores per parent container
#
# @threads: number of threads per core
@@ -1646,6 +1715,7 @@
'*sockets': 'int',
'*dies': 'int',
'*clusters': 'int',
+ '*modules': 'int',
'*cores': 'int',
'*threads': 'int',
'*maxcpus': 'int' } }
diff --git a/qom/qom-qmp-cmds.c b/qom/qom-qmp-cmds.c
index 7c08729..e91a235 100644
--- a/qom/qom-qmp-cmds.c
+++ b/qom/qom-qmp-cmds.c
@@ -212,6 +212,7 @@
info->name = g_strdup(prop->name);
info->type = g_strdup(prop->type);
info->description = g_strdup(prop->description);
+ info->default_value = qobject_ref(prop->defval);
QAPI_LIST_PREPEND(prop_list, info);
}
diff --git a/scripts/coccinelle/reset-type.cocci b/scripts/coccinelle/reset-type.cocci
new file mode 100644
index 0000000..14abdd7
--- /dev/null
+++ b/scripts/coccinelle/reset-type.cocci
@@ -0,0 +1,133 @@
+// Convert device code using three-phase reset to add a ResetType
+// argument to implementations of ResettableHoldPhase and
+// ResettableEnterPhase methods.
+//
+// Copyright Linaro Ltd 2024
+// SPDX-License-Identifier: GPL-2.0-or-later
+//
+// for dir in include hw target; do \
+// spatch --macro-file scripts/cocci-macro-file.h \
+// --sp-file scripts/coccinelle/reset-type.cocci \
+// --keep-comments --smpl-spacing --in-place --include-headers \
+// --dir $dir; done
+//
+// This coccinelle script aims to produce a complete change that needs
+// no human interaction, so as well as the generic "update device
+// implementations of the hold and exit phase methods" it includes
+// the special-case transformations needed for the core code and for
+// one device model that does something a bit nonstandard. Those
+// special cases are at the end of the file.
+
+// Look for where we use a function as a ResettableHoldPhase method,
+// either by directly assigning it to phases.hold or by calling
+// resettable_class_set_parent_phases, and remember the function name.
+@ holdfn_assigned @
+identifier enterfn, holdfn, exitfn;
+identifier rc;
+expression e;
+@@
+ResettableClass *rc;
+...
+(
+ rc->phases.hold = holdfn;
+|
+ resettable_class_set_parent_phases(rc, enterfn, holdfn, exitfn, e);
+)
+
+// Look for the definition of the function we found in holdfn_assigned,
+// and add the new argument. If the function calls a hold function
+// itself (probably chaining to the parent class reset) then add the
+// new argument there too.
+@ holdfn_defined @
+identifier holdfn_assigned.holdfn;
+typedef Object;
+identifier obj;
+expression parent;
+@@
+-holdfn(Object *obj)
++holdfn(Object *obj, ResetType type)
+{
+ <...
+- parent.hold(obj)
++ parent.hold(obj, type)
+ ...>
+}
+
+// Similarly for ResettableExitPhase.
+@ exitfn_assigned @
+identifier enterfn, holdfn, exitfn;
+identifier rc;
+expression e;
+@@
+ResettableClass *rc;
+...
+(
+ rc->phases.exit = exitfn;
+|
+ resettable_class_set_parent_phases(rc, enterfn, holdfn, exitfn, e);
+)
+@ exitfn_defined @
+identifier exitfn_assigned.exitfn;
+typedef Object;
+identifier obj;
+expression parent;
+@@
+-exitfn(Object *obj)
++exitfn(Object *obj, ResetType type)
+{
+ <...
+- parent.exit(obj)
++ parent.exit(obj, type)
+ ...>
+}
+
+// SPECIAL CASES ONLY BELOW HERE
+// We use a python scripted constraint on the position of the match
+// to ensure that they only match in a particular function. See
+// https://public-inbox.org/git/alpine.DEB.2.21.1808240652370.2344@hadrien/
+// which recommends this as the way to do "match only in this function".
+
+// Special case: isl_pmbus_vr.c has some reset methods calling others directly
+@ isl_pmbus_vr @
+identifier obj;
+@@
+- isl_pmbus_vr_exit_reset(obj);
++ isl_pmbus_vr_exit_reset(obj, type);
+
+// Special case: device_phases_reset() needs to pass RESET_TYPE_COLD
+@ device_phases_reset_hold @
+expression obj;
+identifier rc;
+identifier phase;
+position p : script:python() { p[0].current_element == "device_phases_reset" };
+@@
+- rc->phases.phase(obj)@p
++ rc->phases.phase(obj, RESET_TYPE_COLD)
+
+// Special case: in resettable_phase_hold() and resettable_phase_exit()
+// we need to pass through the ResetType argument to the method being called
+@ resettable_phase_hold @
+expression obj;
+identifier rc;
+position p : script:python() { p[0].current_element == "resettable_phase_hold" };
+@@
+- rc->phases.hold(obj)@p
++ rc->phases.hold(obj, type)
+@ resettable_phase_exit @
+expression obj;
+identifier rc;
+position p : script:python() { p[0].current_element == "resettable_phase_exit" };
+@@
+- rc->phases.exit(obj)@p
++ rc->phases.exit(obj, type)
+// Special case: the typedefs for the methods need to declare the new argument
+@ phase_typedef_hold @
+identifier obj;
+@@
+- typedef void (*ResettableHoldPhase)(Object *obj);
++ typedef void (*ResettableHoldPhase)(Object *obj, ResetType type);
+@ phase_typedef_exit @
+identifier obj;
+@@
+- typedef void (*ResettableExitPhase)(Object *obj);
++ typedef void (*ResettableExitPhase)(Object *obj, ResetType type);
diff --git a/scripts/compare-machine-types.py b/scripts/compare-machine-types.py
new file mode 100755
index 0000000..2af3995
--- /dev/null
+++ b/scripts/compare-machine-types.py
@@ -0,0 +1,486 @@
+#!/usr/bin/env python3
+#
+# Script to compare machine type compatible properties (include/hw/boards.h).
+# compat_props are applied to the driver during initialization to change
+# default values, for instance, to maintain compatibility.
+# This script constructs table with machines and values of their compat_props
+# to compare and to find places for improvements or places with bugs. If
+# during the comparison, some machine type doesn't have a property (it is in
+# the comparison table because another machine type has it), then the
+# appropriate method will be used to obtain the default value of this driver
+# property via qmp command (e.g. query-cpu-model-expansion for x86_64-cpu).
+# These methods are defined below in qemu_property_methods.
+#
+# Copyright (c) Yandex Technologies LLC, 2023
+#
+# 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/>.
+
+import sys
+from os import path
+from argparse import ArgumentParser, RawTextHelpFormatter, Namespace
+import pandas as pd
+from contextlib import ExitStack
+from typing import Optional, List, Dict, Generator, Tuple, Union, Any, Set
+
+try:
+ qemu_dir = path.abspath(path.dirname(path.dirname(__file__)))
+ sys.path.append(path.join(qemu_dir, 'python'))
+ from qemu.machine import QEMUMachine
+except ModuleNotFoundError as exc:
+ print(f"Module '{exc.name}' not found.")
+ print("Try export PYTHONPATH=top-qemu-dir/python or run from top-qemu-dir")
+ sys.exit(1)
+
+
+default_qemu_args = '-enable-kvm -machine none'
+default_qemu_binary = 'build/qemu-system-x86_64'
+
+
+# Methods for gettig the right values of drivers properties
+#
+# Use these methods as a 'whitelist' and add entries only if necessary. It's
+# important to be stable and predictable in analysis and tests.
+# Be careful:
+# * Class must be inherited from 'QEMUObject' and used in new_driver()
+# * Class has to implement get_prop method in order to get values
+# * Specialization always wins (with the given classes for 'device' and
+# 'x86_64-cpu', method of 'x86_64-cpu' will be used for '486-x86_64-cpu')
+
+class Driver():
+ def __init__(self, vm: QEMUMachine, name: str, abstract: bool) -> None:
+ self.vm = vm
+ self.name = name
+ self.abstract = abstract
+ self.parent: Optional[Driver] = None
+ self.property_getter: Optional[Driver] = None
+
+ def get_prop(self, driver: str, prop: str) -> str:
+ if self.property_getter:
+ return self.property_getter.get_prop(driver, prop)
+ else:
+ return 'Unavailable method'
+
+ def is_child_of(self, parent: 'Driver') -> bool:
+ """Checks whether self is (recursive) child of @parent"""
+ cur_parent = self.parent
+ while cur_parent:
+ if cur_parent is parent:
+ return True
+ cur_parent = cur_parent.parent
+
+ return False
+
+ def set_implementations(self, implementations: List['Driver']) -> None:
+ self.implementations = implementations
+
+
+class QEMUObject(Driver):
+ def __init__(self, vm: QEMUMachine, name: str) -> None:
+ super().__init__(vm, name, True)
+
+ def set_implementations(self, implementations: List[Driver]) -> None:
+ self.implementations = implementations
+
+ # each implementation of the abstract driver has to use property getter
+ # of this abstract driver unless it has specialization. (e.g. having
+ # 'device' and 'x86_64-cpu', property getter of 'x86_64-cpu' will be
+ # used for '486-x86_64-cpu')
+ for impl in implementations:
+ if not impl.property_getter or\
+ self.is_child_of(impl.property_getter):
+ impl.property_getter = self
+
+
+class QEMUDevice(QEMUObject):
+ def __init__(self, vm: QEMUMachine) -> None:
+ super().__init__(vm, 'device')
+ self.cached: Dict[str, List[Dict[str, Any]]] = {}
+
+ def get_prop(self, driver: str, prop_name: str) -> str:
+ if driver not in self.cached:
+ self.cached[driver] = self.vm.cmd('device-list-properties',
+ typename=driver)
+ for prop in self.cached[driver]:
+ if prop['name'] == prop_name:
+ return str(prop.get('default-value', 'No default value'))
+
+ return 'Unknown property'
+
+
+class QEMUx86CPU(QEMUObject):
+ def __init__(self, vm: QEMUMachine) -> None:
+ super().__init__(vm, 'x86_64-cpu')
+ self.cached: Dict[str, Dict[str, Any]] = {}
+
+ def get_prop(self, driver: str, prop_name: str) -> str:
+ if not driver.endswith('-x86_64-cpu'):
+ return 'Wrong x86_64-cpu name'
+
+ # crop last 11 chars '-x86_64-cpu'
+ name = driver[:-11]
+ if name not in self.cached:
+ self.cached[name] = self.vm.cmd(
+ 'query-cpu-model-expansion', type='full',
+ model={'name': name})['model']['props']
+ return str(self.cached[name].get(prop_name, 'Unknown property'))
+
+
+# Now it's stub, because all memory_backend types don't have default values
+# but this behaviour can be changed
+class QEMUMemoryBackend(QEMUObject):
+ def __init__(self, vm: QEMUMachine) -> None:
+ super().__init__(vm, 'memory-backend')
+ self.cached: Dict[str, List[Dict[str, Any]]] = {}
+
+ def get_prop(self, driver: str, prop_name: str) -> str:
+ if driver not in self.cached:
+ self.cached[driver] = self.vm.cmd('qom-list-properties',
+ typename=driver)
+ for prop in self.cached[driver]:
+ if prop['name'] == prop_name:
+ return str(prop.get('default-value', 'No default value'))
+
+ return 'Unknown property'
+
+
+def new_driver(vm: QEMUMachine, name: str, is_abstr: bool) -> Driver:
+ if name == 'object':
+ return QEMUObject(vm, 'object')
+ elif name == 'device':
+ return QEMUDevice(vm)
+ elif name == 'x86_64-cpu':
+ return QEMUx86CPU(vm)
+ elif name == 'memory-backend':
+ return QEMUMemoryBackend(vm)
+ else:
+ return Driver(vm, name, is_abstr)
+# End of methods definition
+
+
+class VMPropertyGetter:
+ """It implements the relationship between drivers and how to get their
+ properties"""
+ def __init__(self, vm: QEMUMachine) -> None:
+ self.drivers: Dict[str, Driver] = {}
+
+ qom_all_types = vm.cmd('qom-list-types', abstract=True)
+ self.drivers = {t['name']: new_driver(vm, t['name'],
+ t.get('abstract', False))
+ for t in qom_all_types}
+
+ for t in qom_all_types:
+ drv = self.drivers[t['name']]
+ if 'parent' in t:
+ drv.parent = self.drivers[t['parent']]
+
+ for drv in self.drivers.values():
+ imps = vm.cmd('qom-list-types', implements=drv.name)
+ # only implementations inherit property getter
+ drv.set_implementations([self.drivers[imp['name']]
+ for imp in imps])
+
+ def get_prop(self, driver: str, prop: str) -> str:
+ # wrong driver name or disabled in config driver
+ try:
+ drv = self.drivers[driver]
+ except KeyError:
+ return 'Unavailable driver'
+
+ assert not drv.abstract
+
+ return drv.get_prop(driver, prop)
+
+ def get_implementations(self, driver: str) -> List[str]:
+ return [impl.name for impl in self.drivers[driver].implementations]
+
+
+class Machine:
+ """A short QEMU machine type description. It contains only processed
+ compat_props (properties of abstract classes are applied to its
+ implementations)
+ """
+ # raw_mt_dict - dict produced by `query-machines`
+ def __init__(self, raw_mt_dict: Dict[str, Any],
+ qemu_drivers: VMPropertyGetter) -> None:
+ self.name = raw_mt_dict['name']
+ self.compat_props: Dict[str, Any] = {}
+ # properties are applied sequentially and can rewrite values like in
+ # QEMU. Also it has to resolve class relationships to apply appropriate
+ # values from abstract class to all implementations
+ for prop in raw_mt_dict['compat-props']:
+ driver = prop['qom-type']
+ try:
+ # implementation adds only itself, abstract class adds
+ # lementation (abstract classes are uninterestiong)
+ impls = qemu_drivers.get_implementations(driver)
+ for impl in impls:
+ if impl not in self.compat_props:
+ self.compat_props[impl] = {}
+ self.compat_props[impl][prop['property']] = prop['value']
+ except KeyError:
+ # QEMU doesn't know this driver thus it has to be saved
+ if driver not in self.compat_props:
+ self.compat_props[driver] = {}
+ self.compat_props[driver][prop['property']] = prop['value']
+
+
+class Configuration():
+ """Class contains all necessary components to generate table and is used
+ to compare different binaries"""
+ def __init__(self, vm: QEMUMachine,
+ req_mt: List[str], all_mt: bool) -> None:
+ self._vm = vm
+ self._binary = vm.binary
+ self._qemu_args = args.qemu_args.split(' ')
+
+ self._qemu_drivers = VMPropertyGetter(vm)
+ self.req_mt = get_req_mt(self._qemu_drivers, vm, req_mt, all_mt)
+
+ def get_implementations(self, driver_name: str) -> List[str]:
+ return self._qemu_drivers.get_implementations(driver_name)
+
+ def get_table(self, req_props: List[Tuple[str, str]]) -> pd.DataFrame:
+ table: List[pd.DataFrame] = []
+ for mt in self.req_mt:
+ name = f'{self._binary}\n{mt.name}'
+ column = []
+ for driver, prop in req_props:
+ try:
+ # values from QEMU machine type definitions
+ column.append(mt.compat_props[driver][prop])
+ except KeyError:
+ # values from QEMU type definitions
+ column.append(self._qemu_drivers.get_prop(driver, prop))
+ table.append(pd.DataFrame({name: column}))
+
+ return pd.concat(table, axis=1)
+
+
+script_desc = """Script to compare machine types (their compat_props).
+
+Examples:
+* save info about all machines: ./scripts/compare-machine-types.py --all \
+--format csv --raw > table.csv
+* compare machines: ./scripts/compare-machine-types.py --mt pc-q35-2.12 \
+pc-q35-3.0
+* compare binaries and machines: ./scripts/compare-machine-types.py \
+--mt pc-q35-6.2 pc-q35-7.0 --qemu-binary build/qemu-system-x86_64 \
+build/qemu-exp
+ ╒════════════╤══════════════════════════╤════════════════════════════\
+╤════════════════════════════╤══════════════════╤══════════════════╕
+ │ Driver │ Property │ build/qemu-system-x86_64 \
+│ build/qemu-system-x86_64 │ build/qemu-exp │ build/qemu-exp │
+ │ │ │ pc-q35-6.2 \
+│ pc-q35-7.0 │ pc-q35-6.2 │ pc-q35-7.0 │
+ ╞════════════╪══════════════════════════╪════════════════════════════\
+╪════════════════════════════╪══════════════════╪══════════════════╡
+ │ PIIX4_PM │ x-not-migrate-acpi-index │ True \
+│ False │ False │ False │
+ ├────────────┼──────────────────────────┼────────────────────────────\
+┼────────────────────────────┼──────────────────┼──────────────────┤
+ │ virtio-mem │ unplugged-inaccessible │ False \
+│ auto │ False │ auto │
+ ╘════════════╧══════════════════════════╧════════════════════════════\
+╧════════════════════════════╧══════════════════╧══════════════════╛
+
+If a property from QEMU machine defintion applies to an abstract class (e.g. \
+x86_64-cpu) this script will compare all implementations of this class.
+
+"Unavailable method" - means that this script doesn't know how to get \
+default values of the driver. To add method use the construction described \
+at the top of the script.
+"Unavailable driver" - means that this script doesn't know this driver. \
+For instance, this can happen if you configure QEMU without this device or \
+if machine type definition has error.
+"No default value" - means that the appropriate method can't get the default \
+value and most likely that this property doesn't have it.
+"Unknown property" - means that the appropriate method can't find property \
+with this name."""
+
+
+def parse_args() -> Namespace:
+ parser = ArgumentParser(formatter_class=RawTextHelpFormatter,
+ description=script_desc)
+ parser.add_argument('--format', choices=['human-readable', 'json', 'csv'],
+ default='human-readable',
+ help='returns table in json format')
+ parser.add_argument('--raw', action='store_true',
+ help='prints ALL defined properties without value '
+ 'transformation. By default, only rows '
+ 'with different values will be printed and '
+ 'values will be transformed(e.g. "on" -> True)')
+ parser.add_argument('--qemu-args', default=default_qemu_args,
+ help='command line to start qemu. '
+ f'Default: "{default_qemu_args}"')
+ parser.add_argument('--qemu-binary', nargs="*", type=str,
+ default=[default_qemu_binary],
+ help='list of qemu binaries that will be compared. '
+ f'Deafult: {default_qemu_binary}')
+
+ mt_args_group = parser.add_mutually_exclusive_group()
+ mt_args_group.add_argument('--all', action='store_true',
+ help='prints all available machine types (list '
+ 'of machine types will be ignored)')
+ mt_args_group.add_argument('--mt', nargs="*", type=str,
+ help='list of Machine Types '
+ 'that will be compared')
+
+ return parser.parse_args()
+
+
+def mt_comp(mt: Machine) -> Tuple[str, int, int, int]:
+ """Function to compare and sort machine by names.
+ It returns socket_name, major version, minor version, revision"""
+ # none, microvm, x-remote and etc.
+ if '-' not in mt.name or '.' not in mt.name:
+ return mt.name, 0, 0, 0
+
+ socket, ver = mt.name.rsplit('-', 1)
+ ver_list = list(map(int, ver.split('.', 2)))
+ ver_list += [0] * (3 - len(ver_list))
+ return socket, ver_list[0], ver_list[1], ver_list[2]
+
+
+def get_mt_definitions(qemu_drivers: VMPropertyGetter,
+ vm: QEMUMachine) -> List[Machine]:
+ """Constructs list of machine definitions (primarily compat_props) via
+ info from QEMU"""
+ raw_mt_defs = vm.cmd('query-machines', compat_props=True)
+ mt_defs = []
+ for raw_mt in raw_mt_defs:
+ mt_defs.append(Machine(raw_mt, qemu_drivers))
+
+ mt_defs.sort(key=mt_comp)
+ return mt_defs
+
+
+def get_req_mt(qemu_drivers: VMPropertyGetter, vm: QEMUMachine,
+ req_mt: Optional[List[str]], all_mt: bool) -> List[Machine]:
+ """Returns list of requested by user machines"""
+ mt_defs = get_mt_definitions(qemu_drivers, vm)
+ if all_mt:
+ return mt_defs
+
+ if req_mt is None:
+ print('Enter machine types for comparision')
+ exit(0)
+
+ matched_mt = []
+ for mt in mt_defs:
+ if mt.name in req_mt:
+ matched_mt.append(mt)
+
+ return matched_mt
+
+
+def get_affected_props(configs: List[Configuration]) -> Generator[Tuple[str,
+ str],
+ None, None]:
+ """Helps to go through all affected in machine definitions drivers
+ and properties"""
+ driver_props: Dict[str, Set[Any]] = {}
+ for config in configs:
+ for mt in config.req_mt:
+ compat_props = mt.compat_props
+ for driver, prop in compat_props.items():
+ if driver not in driver_props:
+ driver_props[driver] = set()
+ driver_props[driver].update(prop.keys())
+
+ for driver, props in sorted(driver_props.items()):
+ for prop in sorted(props):
+ yield driver, prop
+
+
+def transform_value(value: str) -> Union[str, bool]:
+ true_list = ['true', 'on']
+ false_list = ['false', 'off']
+
+ out = value.lower()
+
+ if out in true_list:
+ return True
+
+ if out in false_list:
+ return False
+
+ return value
+
+
+def simplify_table(table: pd.DataFrame) -> pd.DataFrame:
+ """transforms values to make it easier to compare it and drops rows
+ with the same values for all columns"""
+
+ table = table.map(transform_value)
+
+ return table[~table.iloc[:, 3:].eq(table.iloc[:, 2], axis=0).all(axis=1)]
+
+
+# constructs table in the format:
+#
+# Driver | Property | binary1 | binary1 | ...
+# | | machine1 | machine2 | ...
+# ------------------------------------------------------ ...
+# driver1 | property1 | value1 | value2 | ...
+# driver1 | property2 | value3 | value4 | ...
+# driver2 | property3 | value5 | value6 | ...
+# ... | ... | ... | ... | ...
+#
+def fill_prop_table(configs: List[Configuration],
+ is_raw: bool) -> pd.DataFrame:
+ req_props = list(get_affected_props(configs))
+ if not req_props:
+ print('No drivers to compare. Check machine names')
+ exit(0)
+
+ driver_col, prop_col = tuple(zip(*req_props))
+ table = [pd.DataFrame({'Driver': driver_col}),
+ pd.DataFrame({'Property': prop_col})]
+
+ table.extend([config.get_table(req_props) for config in configs])
+
+ df_table = pd.concat(table, axis=1)
+
+ if is_raw:
+ return df_table
+
+ return simplify_table(df_table)
+
+
+def print_table(table: pd.DataFrame, table_format: str) -> None:
+ if table_format == 'json':
+ print(comp_table.to_json())
+ elif table_format == 'csv':
+ print(comp_table.to_csv())
+ else:
+ print(comp_table.to_markdown(index=False, stralign='center',
+ colalign=('center',), headers='keys',
+ tablefmt='fancy_grid',
+ disable_numparse=True))
+
+
+if __name__ == '__main__':
+ args = parse_args()
+ with ExitStack() as stack:
+ vms = [stack.enter_context(QEMUMachine(binary=binary, qmp_timer=15,
+ args=args.qemu_args.split(' '))) for binary in args.qemu_binary]
+
+ configurations = []
+ for vm in vms:
+ vm.launch()
+ configurations.append(Configuration(vm, args.mt, args.all))
+
+ comp_table = fill_prop_table(configurations, args.raw)
+ if not comp_table.empty:
+ print_table(comp_table, args.format)
diff --git a/system/vl.c b/system/vl.c
index c644222..7756eac 100644
--- a/system/vl.c
+++ b/system/vl.c
@@ -742,6 +742,9 @@
.name = "clusters",
.type = QEMU_OPT_NUMBER,
}, {
+ .name = "modules",
+ .type = QEMU_OPT_NUMBER,
+ }, {
.name = "cores",
.type = QEMU_OPT_NUMBER,
}, {
diff --git a/target/arm/cpu-features.h b/target/arm/cpu-features.h
index e5758d9..b300d04 100644
--- a/target/arm/cpu-features.h
+++ b/target/arm/cpu-features.h
@@ -681,6 +681,11 @@
return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, SME) != 0;
}
+static inline bool isar_feature_aa64_nmi(const ARMISARegisters *id)
+{
+ return FIELD_EX64(id->id_aa64pfr1, ID_AA64PFR1, NMI) != 0;
+}
+
static inline bool isar_feature_aa64_tgran4_lpa2(const ARMISARegisters *id)
{
return FIELD_SEX64(id->id_aa64mmfr0, ID_AA64MMFR0, TGRAN4) >= 1;
diff --git a/target/arm/cpu-qom.h b/target/arm/cpu-qom.h
index 8e03269..b497667 100644
--- a/target/arm/cpu-qom.h
+++ b/target/arm/cpu-qom.h
@@ -36,11 +36,14 @@
#define ARM_CPU_TYPE_SUFFIX "-" TYPE_ARM_CPU
#define ARM_CPU_TYPE_NAME(name) (name ARM_CPU_TYPE_SUFFIX)
-/* Meanings of the ARMCPU object's four inbound GPIO lines */
+/* Meanings of the ARMCPU object's seven inbound GPIO lines */
#define ARM_CPU_IRQ 0
#define ARM_CPU_FIQ 1
#define ARM_CPU_VIRQ 2
#define ARM_CPU_VFIQ 3
+#define ARM_CPU_NMI 4
+#define ARM_CPU_VINMI 5
+#define ARM_CPU_VFNMI 6
/* For M profile, some registers are banked secure vs non-secure;
* these are represented as a 2-element array where the first element
diff --git a/target/arm/cpu.c b/target/arm/cpu.c
index ab8d007..a152def 100644
--- a/target/arm/cpu.c
+++ b/target/arm/cpu.c
@@ -122,6 +122,13 @@
}
#endif /* CONFIG_TCG */
+/*
+ * With SCTLR_ELx.NMI == 0, IRQ with Superpriority is masked identically with
+ * IRQ without Superpriority. Moreover, if the GIC is configured so that
+ * FEAT_GICv3_NMI is only set if FEAT_NMI is set, then we won't ever see
+ * CPU_INTERRUPT_*NMI anyway. So we might as well accept NMI here
+ * unconditionally.
+ */
static bool arm_cpu_has_work(CPUState *cs)
{
ARMCPU *cpu = ARM_CPU(cs);
@@ -129,6 +136,7 @@
return (cpu->power_state != PSCI_OFF)
&& cs->interrupt_request &
(CPU_INTERRUPT_FIQ | CPU_INTERRUPT_HARD
+ | CPU_INTERRUPT_NMI | CPU_INTERRUPT_VINMI | CPU_INTERRUPT_VFNMI
| CPU_INTERRUPT_VFIQ | CPU_INTERRUPT_VIRQ | CPU_INTERRUPT_VSERR
| CPU_INTERRUPT_EXITTB);
}
@@ -212,7 +220,7 @@
assert(oldvalue == newvalue);
}
-static void arm_cpu_reset_hold(Object *obj)
+static void arm_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
ARMCPU *cpu = ARM_CPU(cs);
@@ -220,7 +228,7 @@
CPUARMState *env = &cpu->env;
if (acc->parent_phases.hold) {
- acc->parent_phases.hold(obj);
+ acc->parent_phases.hold(obj, type);
}
memset(env, 0, offsetof(CPUARMState, end_reset_fields));
@@ -668,6 +676,7 @@
CPUARMState *env = cpu_env(cs);
bool pstate_unmasked;
bool unmasked = false;
+ bool allIntMask = false;
/*
* Don't take exceptions if they target a lower EL.
@@ -678,13 +687,36 @@
return false;
}
+ if (cpu_isar_feature(aa64_nmi, env_archcpu(env)) &&
+ env->cp15.sctlr_el[target_el] & SCTLR_NMI && cur_el == target_el) {
+ allIntMask = env->pstate & PSTATE_ALLINT ||
+ ((env->cp15.sctlr_el[target_el] & SCTLR_SPINTMASK) &&
+ (env->pstate & PSTATE_SP));
+ }
+
switch (excp_idx) {
+ case EXCP_NMI:
+ pstate_unmasked = !allIntMask;
+ break;
+
+ case EXCP_VINMI:
+ if (!(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) {
+ /* VINMIs are only taken when hypervized. */
+ return false;
+ }
+ return !allIntMask;
+ case EXCP_VFNMI:
+ if (!(hcr_el2 & HCR_FMO) || (hcr_el2 & HCR_TGE)) {
+ /* VFNMIs are only taken when hypervized. */
+ return false;
+ }
+ return !allIntMask;
case EXCP_FIQ:
- pstate_unmasked = !(env->daif & PSTATE_F);
+ pstate_unmasked = (!(env->daif & PSTATE_F)) && (!allIntMask);
break;
case EXCP_IRQ:
- pstate_unmasked = !(env->daif & PSTATE_I);
+ pstate_unmasked = (!(env->daif & PSTATE_I)) && (!allIntMask);
break;
case EXCP_VFIQ:
@@ -692,13 +724,13 @@
/* VFIQs are only taken when hypervized. */
return false;
}
- return !(env->daif & PSTATE_F);
+ return !(env->daif & PSTATE_F) && (!allIntMask);
case EXCP_VIRQ:
if (!(hcr_el2 & HCR_IMO) || (hcr_el2 & HCR_TGE)) {
/* VIRQs are only taken when hypervized. */
return false;
}
- return !(env->daif & PSTATE_I);
+ return !(env->daif & PSTATE_I) && (!allIntMask);
case EXCP_VSERR:
if (!(hcr_el2 & HCR_AMO) || (hcr_el2 & HCR_TGE)) {
/* VIRQs are only taken when hypervized. */
@@ -804,6 +836,48 @@
/* The prioritization of interrupts is IMPLEMENTATION DEFINED. */
+ if (cpu_isar_feature(aa64_nmi, env_archcpu(env)) &&
+ (arm_sctlr(env, cur_el) & SCTLR_NMI)) {
+ if (interrupt_request & CPU_INTERRUPT_NMI) {
+ excp_idx = EXCP_NMI;
+ target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
+ if (arm_excp_unmasked(cs, excp_idx, target_el,
+ cur_el, secure, hcr_el2)) {
+ goto found;
+ }
+ }
+ if (interrupt_request & CPU_INTERRUPT_VINMI) {
+ excp_idx = EXCP_VINMI;
+ target_el = 1;
+ if (arm_excp_unmasked(cs, excp_idx, target_el,
+ cur_el, secure, hcr_el2)) {
+ goto found;
+ }
+ }
+ if (interrupt_request & CPU_INTERRUPT_VFNMI) {
+ excp_idx = EXCP_VFNMI;
+ target_el = 1;
+ if (arm_excp_unmasked(cs, excp_idx, target_el,
+ cur_el, secure, hcr_el2)) {
+ goto found;
+ }
+ }
+ } else {
+ /*
+ * NMI disabled: interrupts with superpriority are handled
+ * as if they didn't have it
+ */
+ if (interrupt_request & CPU_INTERRUPT_NMI) {
+ interrupt_request |= CPU_INTERRUPT_HARD;
+ }
+ if (interrupt_request & CPU_INTERRUPT_VINMI) {
+ interrupt_request |= CPU_INTERRUPT_VIRQ;
+ }
+ if (interrupt_request & CPU_INTERRUPT_VFNMI) {
+ interrupt_request |= CPU_INTERRUPT_VFIQ;
+ }
+ }
+
if (interrupt_request & CPU_INTERRUPT_FIQ) {
excp_idx = EXCP_FIQ;
target_el = arm_phys_excp_target_el(cs, excp_idx, cur_el, secure);
@@ -867,7 +941,8 @@
CPUARMState *env = &cpu->env;
CPUState *cs = CPU(cpu);
- bool new_state = (env->cp15.hcr_el2 & HCR_VI) ||
+ bool new_state = ((arm_hcr_el2_eff(env) & HCR_VI) &&
+ !(arm_hcrx_el2_eff(env) & HCRX_VINMI)) ||
(env->irq_line_state & CPU_INTERRUPT_VIRQ);
if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VIRQ) != 0)) {
@@ -888,7 +963,8 @@
CPUARMState *env = &cpu->env;
CPUState *cs = CPU(cpu);
- bool new_state = (env->cp15.hcr_el2 & HCR_VF) ||
+ bool new_state = ((arm_hcr_el2_eff(env) & HCR_VF) &&
+ !(arm_hcrx_el2_eff(env) & HCRX_VFNMI)) ||
(env->irq_line_state & CPU_INTERRUPT_VFIQ);
if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VFIQ) != 0)) {
@@ -900,6 +976,48 @@
}
}
+void arm_cpu_update_vinmi(ARMCPU *cpu)
+{
+ /*
+ * Update the interrupt level for VINMI, which is the logical OR of
+ * the HCRX_EL2.VINMI bit and the input line level from the GIC.
+ */
+ CPUARMState *env = &cpu->env;
+ CPUState *cs = CPU(cpu);
+
+ bool new_state = ((arm_hcr_el2_eff(env) & HCR_VI) &&
+ (arm_hcrx_el2_eff(env) & HCRX_VINMI)) ||
+ (env->irq_line_state & CPU_INTERRUPT_VINMI);
+
+ if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VINMI) != 0)) {
+ if (new_state) {
+ cpu_interrupt(cs, CPU_INTERRUPT_VINMI);
+ } else {
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_VINMI);
+ }
+ }
+}
+
+void arm_cpu_update_vfnmi(ARMCPU *cpu)
+{
+ /*
+ * Update the interrupt level for VFNMI, which is the HCRX_EL2.VFNMI bit.
+ */
+ CPUARMState *env = &cpu->env;
+ CPUState *cs = CPU(cpu);
+
+ bool new_state = (arm_hcr_el2_eff(env) & HCR_VF) &&
+ (arm_hcrx_el2_eff(env) & HCRX_VFNMI);
+
+ if (new_state != ((cs->interrupt_request & CPU_INTERRUPT_VFNMI) != 0)) {
+ if (new_state) {
+ cpu_interrupt(cs, CPU_INTERRUPT_VFNMI);
+ } else {
+ cpu_reset_interrupt(cs, CPU_INTERRUPT_VFNMI);
+ }
+ }
+}
+
void arm_cpu_update_vserr(ARMCPU *cpu)
{
/*
@@ -929,7 +1047,9 @@
[ARM_CPU_IRQ] = CPU_INTERRUPT_HARD,
[ARM_CPU_FIQ] = CPU_INTERRUPT_FIQ,
[ARM_CPU_VIRQ] = CPU_INTERRUPT_VIRQ,
- [ARM_CPU_VFIQ] = CPU_INTERRUPT_VFIQ
+ [ARM_CPU_VFIQ] = CPU_INTERRUPT_VFIQ,
+ [ARM_CPU_NMI] = CPU_INTERRUPT_NMI,
+ [ARM_CPU_VINMI] = CPU_INTERRUPT_VINMI,
};
if (!arm_feature(env, ARM_FEATURE_EL2) &&
@@ -955,8 +1075,12 @@
case ARM_CPU_VFIQ:
arm_cpu_update_vfiq(cpu);
break;
+ case ARM_CPU_VINMI:
+ arm_cpu_update_vinmi(cpu);
+ break;
case ARM_CPU_IRQ:
case ARM_CPU_FIQ:
+ case ARM_CPU_NMI:
if (level) {
cpu_interrupt(cs, mask[irq]);
} else {
@@ -1350,12 +1474,13 @@
#else
/* Our inbound IRQ and FIQ lines */
if (kvm_enabled()) {
- /* VIRQ and VFIQ are unused with KVM but we add them to maintain
- * the same interface as non-KVM CPUs.
+ /*
+ * VIRQ, VFIQ, NMI, VINMI are unused with KVM but we add
+ * them to maintain the same interface as non-KVM CPUs.
*/
- qdev_init_gpio_in(DEVICE(cpu), arm_cpu_kvm_set_irq, 4);
+ qdev_init_gpio_in(DEVICE(cpu), arm_cpu_kvm_set_irq, 6);
} else {
- qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 4);
+ qdev_init_gpio_in(DEVICE(cpu), arm_cpu_set_irq, 6);
}
qdev_init_gpio_out(DEVICE(cpu), cpu->gt_timer_outputs,
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index bc0c848..97997db 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -61,6 +61,9 @@
#define EXCP_DIVBYZERO 23 /* v7M DIVBYZERO UsageFault */
#define EXCP_VSERR 24
#define EXCP_GPC 25 /* v9 Granule Protection Check Fault */
+#define EXCP_NMI 26
+#define EXCP_VINMI 27
+#define EXCP_VFNMI 28
/* NB: add new EXCP_ defines to the array in arm_log_exception() too */
#define ARMV7M_EXCP_RESET 1
@@ -80,6 +83,9 @@
#define CPU_INTERRUPT_VIRQ CPU_INTERRUPT_TGT_EXT_2
#define CPU_INTERRUPT_VFIQ CPU_INTERRUPT_TGT_EXT_3
#define CPU_INTERRUPT_VSERR CPU_INTERRUPT_TGT_INT_0
+#define CPU_INTERRUPT_NMI CPU_INTERRUPT_TGT_EXT_4
+#define CPU_INTERRUPT_VINMI CPU_INTERRUPT_TGT_EXT_0
+#define CPU_INTERRUPT_VFNMI CPU_INTERRUPT_TGT_INT_1
/* The usual mapping for an AArch64 system register to its AArch32
* counterpart is for the 32 bit world to have access to the lower
@@ -1392,6 +1398,8 @@
#define CPSR_N (1U << 31)
#define CPSR_NZCV (CPSR_N | CPSR_Z | CPSR_C | CPSR_V)
#define CPSR_AIF (CPSR_A | CPSR_I | CPSR_F)
+#define ISR_FS (1U << 9)
+#define ISR_IS (1U << 10)
#define CPSR_IT (CPSR_IT_0_1 | CPSR_IT_2_7)
#define CACHED_CPSR_BITS (CPSR_T | CPSR_AIF | CPSR_GE | CPSR_IT | CPSR_Q \
@@ -1430,6 +1438,7 @@
#define PSTATE_D (1U << 9)
#define PSTATE_BTYPE (3U << 10)
#define PSTATE_SSBS (1U << 12)
+#define PSTATE_ALLINT (1U << 13)
#define PSTATE_IL (1U << 20)
#define PSTATE_SS (1U << 21)
#define PSTATE_PAN (1U << 22)
diff --git a/target/arm/helper.c b/target/arm/helper.c
index a620481..6b22482 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -2021,16 +2021,29 @@
if (cs->interrupt_request & CPU_INTERRUPT_VIRQ) {
ret |= CPSR_I;
}
+ if (cs->interrupt_request & CPU_INTERRUPT_VINMI) {
+ ret |= ISR_IS;
+ ret |= CPSR_I;
+ }
} else {
if (cs->interrupt_request & CPU_INTERRUPT_HARD) {
ret |= CPSR_I;
}
+
+ if (cs->interrupt_request & CPU_INTERRUPT_NMI) {
+ ret |= ISR_IS;
+ ret |= CPSR_I;
+ }
}
if (hcr_el2 & HCR_FMO) {
if (cs->interrupt_request & CPU_INTERRUPT_VFIQ) {
ret |= CPSR_F;
}
+ if (cs->interrupt_request & CPU_INTERRUPT_VFNMI) {
+ ret |= ISR_FS;
+ ret |= CPSR_F;
+ }
} else {
if (cs->interrupt_request & CPU_INTERRUPT_FIQ) {
ret |= CPSR_F;
@@ -6046,15 +6059,19 @@
* and the state of the input lines from the GIC. (This requires
* that we have the BQL, which is done by marking the
* reginfo structs as ARM_CP_IO.)
- * Note that if a write to HCR pends a VIRQ or VFIQ it is never
- * possible for it to be taken immediately, because VIRQ and
- * VFIQ are masked unless running at EL0 or EL1, and HCR
- * can only be written at EL2.
+ * Note that if a write to HCR pends a VIRQ or VFIQ or VINMI or
+ * VFNMI, it is never possible for it to be taken immediately
+ * because VIRQ, VFIQ, VINMI and VFNMI are masked unless running
+ * at EL0 or EL1, and HCR can only be written at EL2.
*/
g_assert(bql_locked());
arm_cpu_update_virq(cpu);
arm_cpu_update_vfiq(cpu);
arm_cpu_update_vserr(cpu);
+ if (cpu_isar_feature(aa64_nmi, cpu)) {
+ arm_cpu_update_vinmi(cpu);
+ arm_cpu_update_vfnmi(cpu);
+ }
}
static void hcr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value)
@@ -6187,15 +6204,38 @@
static void hcrx_write(CPUARMState *env, const ARMCPRegInfo *ri,
uint64_t value)
{
+ ARMCPU *cpu = env_archcpu(env);
uint64_t valid_mask = 0;
/* FEAT_MOPS adds MSCEn and MCE2 */
- if (cpu_isar_feature(aa64_mops, env_archcpu(env))) {
+ if (cpu_isar_feature(aa64_mops, cpu)) {
valid_mask |= HCRX_MSCEN | HCRX_MCE2;
}
+ /* FEAT_NMI adds TALLINT, VINMI and VFNMI */
+ if (cpu_isar_feature(aa64_nmi, cpu)) {
+ valid_mask |= HCRX_TALLINT | HCRX_VINMI | HCRX_VFNMI;
+ }
+
/* Clear RES0 bits. */
env->cp15.hcrx_el2 = value & valid_mask;
+
+ /*
+ * Updates to VINMI and VFNMI require us to update the status of
+ * virtual NMI, which are the logical OR of these bits
+ * and the state of the input lines from the GIC. (This requires
+ * that we have the BQL, which is done by marking the
+ * reginfo structs as ARM_CP_IO.)
+ * Note that if a write to HCRX pends a VINMI or VFNMI it is never
+ * possible for it to be taken immediately, because VINMI and
+ * VFNMI are masked unless running at EL0 or EL1, and HCRX
+ * can only be written at EL2.
+ */
+ if (cpu_isar_feature(aa64_nmi, cpu)) {
+ g_assert(bql_locked());
+ arm_cpu_update_vinmi(cpu);
+ arm_cpu_update_vfnmi(cpu);
+ }
}
static CPAccessResult access_hxen(CPUARMState *env, const ARMCPRegInfo *ri,
@@ -6211,6 +6251,7 @@
static const ARMCPRegInfo hcrx_el2_reginfo = {
.name = "HCRX_EL2", .state = ARM_CP_STATE_AA64,
+ .type = ARM_CP_IO,
.opc0 = 3, .opc1 = 4, .crn = 1, .crm = 2, .opc2 = 2,
.access = PL2_RW, .writefn = hcrx_write, .accessfn = access_hxen,
.nv2_redirect_offset = 0xa0,
@@ -7494,6 +7535,37 @@
.opc0 = 1, .opc1 = 6, .crn = 7, .crm = 14, .opc2 = 5,
.access = PL3_W, .type = ARM_CP_NOP },
};
+
+static void aa64_allint_write(CPUARMState *env, const ARMCPRegInfo *ri,
+ uint64_t value)
+{
+ env->pstate = (env->pstate & ~PSTATE_ALLINT) | (value & PSTATE_ALLINT);
+}
+
+static uint64_t aa64_allint_read(CPUARMState *env, const ARMCPRegInfo *ri)
+{
+ return env->pstate & PSTATE_ALLINT;
+}
+
+static CPAccessResult aa64_allint_access(CPUARMState *env,
+ const ARMCPRegInfo *ri, bool isread)
+{
+ if (!isread && arm_current_el(env) == 1 &&
+ (arm_hcrx_el2_eff(env) & HCRX_TALLINT)) {
+ return CP_ACCESS_TRAP_EL2;
+ }
+ return CP_ACCESS_OK;
+}
+
+static const ARMCPRegInfo nmi_reginfo[] = {
+ { .name = "ALLINT", .state = ARM_CP_STATE_AA64,
+ .opc0 = 3, .opc1 = 0, .opc2 = 0, .crn = 4, .crm = 3,
+ .type = ARM_CP_NO_RAW,
+ .access = PL1_RW, .accessfn = aa64_allint_access,
+ .fieldoffset = offsetof(CPUARMState, pstate),
+ .writefn = aa64_allint_write, .readfn = aa64_allint_read,
+ .resetfn = arm_cp_reset_ignore },
+};
#endif /* TARGET_AARCH64 */
static void define_pmu_regs(ARMCPU *cpu)
@@ -9888,6 +9960,10 @@
if (cpu_isar_feature(aa64_nv2, cpu)) {
define_arm_cp_regs(cpu, nv2_reginfo);
}
+
+ if (cpu_isar_feature(aa64_nmi, cpu)) {
+ define_arm_cp_regs(cpu, nmi_reginfo);
+ }
#endif
if (cpu_isar_feature(any_predinv, cpu)) {
@@ -10700,6 +10776,7 @@
hcr_el2 = arm_hcr_el2_eff(env);
switch (excp_idx) {
case EXCP_IRQ:
+ case EXCP_NMI:
scr = ((env->cp15.scr_el3 & SCR_IRQ) == SCR_IRQ);
hcr = hcr_el2 & HCR_IMO;
break;
@@ -10758,6 +10835,9 @@
[EXCP_DIVBYZERO] = "v7M DIVBYZERO UsageFault",
[EXCP_VSERR] = "Virtual SERR",
[EXCP_GPC] = "Granule Protection Check",
+ [EXCP_NMI] = "NMI",
+ [EXCP_VINMI] = "Virtual IRQ NMI",
+ [EXCP_VFNMI] = "Virtual FIQ NMI",
};
if (idx >= 0 && idx < ARRAY_SIZE(excnames)) {
@@ -11573,10 +11653,13 @@
break;
case EXCP_IRQ:
case EXCP_VIRQ:
+ case EXCP_NMI:
+ case EXCP_VINMI:
addr += 0x80;
break;
case EXCP_FIQ:
case EXCP_VFIQ:
+ case EXCP_VFNMI:
addr += 0x100;
break;
case EXCP_VSERR:
@@ -11653,6 +11736,14 @@
}
}
+ if (cpu_isar_feature(aa64_nmi, cpu)) {
+ if (!(env->cp15.sctlr_el[new_el] & SCTLR_SPINTMASK)) {
+ new_mode |= PSTATE_ALLINT;
+ } else {
+ new_mode &= ~PSTATE_ALLINT;
+ }
+ }
+
pstate_write(env, PSTATE_DAIF | new_mode);
env->aarch64 = true;
aarch64_restore_sp(env, new_el);
diff --git a/target/arm/internals.h b/target/arm/internals.h
index dd3da21..b53f5e8 100644
--- a/target/arm/internals.h
+++ b/target/arm/internals.h
@@ -1110,6 +1110,24 @@
void arm_cpu_update_vfiq(ARMCPU *cpu);
/**
+ * arm_cpu_update_vinmi: Update CPU_INTERRUPT_VINMI bit in cs->interrupt_request
+ *
+ * Update the CPU_INTERRUPT_VINMI bit in cs->interrupt_request, following
+ * a change to either the input VNMI line from the GIC or the HCRX_EL2.VINMI.
+ * Must be called with the BQL held.
+ */
+void arm_cpu_update_vinmi(ARMCPU *cpu);
+
+/**
+ * arm_cpu_update_vfnmi: Update CPU_INTERRUPT_VFNMI bit in cs->interrupt_request
+ *
+ * Update the CPU_INTERRUPT_VFNMI bit in cs->interrupt_request, following
+ * a change to the HCRX_EL2.VFNMI.
+ * Must be called with the BQL held.
+ */
+void arm_cpu_update_vfnmi(ARMCPU *cpu);
+
+/**
* arm_cpu_update_vserr: Update CPU_INTERRUPT_VSERR bit
*
* Update the CPU_INTERRUPT_VSERR bit in cs->interrupt_request,
@@ -1229,6 +1247,9 @@
if (isar_feature_aa64_mte(id)) {
valid |= PSTATE_TCO;
}
+ if (isar_feature_aa64_nmi(id)) {
+ valid |= PSTATE_ALLINT;
+ }
return valid;
}
diff --git a/target/arm/tcg/a64.decode b/target/arm/tcg/a64.decode
index 8a20dce..0e7656f 100644
--- a/target/arm/tcg/a64.decode
+++ b/target/arm/tcg/a64.decode
@@ -207,6 +207,7 @@
MSR_i_TCO 1101 0101 0000 0 011 0100 .... 100 11111 @msr_i
MSR_i_DAIFSET 1101 0101 0000 0 011 0100 .... 110 11111 @msr_i
MSR_i_DAIFCLEAR 1101 0101 0000 0 011 0100 .... 111 11111 @msr_i
+MSR_i_ALLINT 1101 0101 0000 0 001 0100 000 imm:1 000 11111
MSR_i_SVCR 1101 0101 0000 0 011 0100 0 mask:2 imm:1 011 11111
# MRS, MSR (register), SYS, SYSL. These are all essentially the
diff --git a/target/arm/tcg/cpu64.c b/target/arm/tcg/cpu64.c
index 9f7a9f3..62c4663 100644
--- a/target/arm/tcg/cpu64.c
+++ b/target/arm/tcg/cpu64.c
@@ -1175,6 +1175,7 @@
t = FIELD_DP64(t, ID_AA64PFR1, RAS_FRAC, 0); /* FEAT_RASv1p1 + FEAT_DoubleFault */
t = FIELD_DP64(t, ID_AA64PFR1, SME, 1); /* FEAT_SME */
t = FIELD_DP64(t, ID_AA64PFR1, CSV2_FRAC, 0); /* FEAT_CSV2_2 */
+ t = FIELD_DP64(t, ID_AA64PFR1, NMI, 1); /* FEAT_NMI */
cpu->isar.id_aa64pfr1 = t;
t = cpu->isar.id_aa64mmfr0;
diff --git a/target/arm/tcg/helper-a64.c b/target/arm/tcg/helper-a64.c
index ebaa7f0..0ea8668 100644
--- a/target/arm/tcg/helper-a64.c
+++ b/target/arm/tcg/helper-a64.c
@@ -66,6 +66,18 @@
update_spsel(env, imm);
}
+void HELPER(msr_set_allint_el1)(CPUARMState *env)
+{
+ /* ALLINT update to PSTATE. */
+ if (arm_hcrx_el2_eff(env) & HCRX_TALLINT) {
+ raise_exception_ra(env, EXCP_UDEF,
+ syn_aa64_sysregtrap(0, 1, 0, 4, 1, 0x1f, 0), 2,
+ GETPC());
+ }
+
+ env->pstate |= PSTATE_ALLINT;
+}
+
static void daif_check(CPUARMState *env, uint32_t op,
uint32_t imm, uintptr_t ra)
{
@@ -892,8 +904,8 @@
*/
env->pstate |= PSTATE_IL;
env->pc = new_pc;
- spsr &= PSTATE_NZCV | PSTATE_DAIF;
- spsr |= pstate_read(env) & ~(PSTATE_NZCV | PSTATE_DAIF);
+ spsr &= PSTATE_NZCV | PSTATE_DAIF | PSTATE_ALLINT;
+ spsr |= pstate_read(env) & ~(PSTATE_NZCV | PSTATE_DAIF | PSTATE_ALLINT);
pstate_write(env, spsr);
if (!arm_singlestep_active(env)) {
env->pstate &= ~PSTATE_SS;
diff --git a/target/arm/tcg/helper-a64.h b/target/arm/tcg/helper-a64.h
index 575a5da..0518165 100644
--- a/target/arm/tcg/helper-a64.h
+++ b/target/arm/tcg/helper-a64.h
@@ -22,6 +22,7 @@
DEF_HELPER_2(msr_i_spsel, void, env, i32)
DEF_HELPER_2(msr_i_daifset, void, env, i32)
DEF_HELPER_2(msr_i_daifclear, void, env, i32)
+DEF_HELPER_1(msr_set_allint_el1, void, env)
DEF_HELPER_3(vfp_cmph_a64, i64, f16, f16, ptr)
DEF_HELPER_3(vfp_cmpeh_a64, i64, f16, f16, ptr)
DEF_HELPER_3(vfp_cmps_a64, i64, f32, f32, ptr)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 2666d52..976094a 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -2036,6 +2036,25 @@
return true;
}
+static bool trans_MSR_i_ALLINT(DisasContext *s, arg_i *a)
+{
+ if (!dc_isar_feature(aa64_nmi, s) || s->current_el == 0) {
+ return false;
+ }
+
+ if (a->imm == 0) {
+ clear_pstate_bits(PSTATE_ALLINT);
+ } else if (s->current_el > 1) {
+ set_pstate_bits(PSTATE_ALLINT);
+ } else {
+ gen_helper_msr_set_allint_el1(tcg_env);
+ }
+
+ /* Exit the cpu loop to re-evaluate pending IRQs. */
+ s->base.is_jmp = DISAS_UPDATE_EXIT;
+ return true;
+}
+
static bool trans_MSR_i_SVCR(DisasContext *s, arg_MSR_i_SVCR *a)
{
if (!dc_isar_feature(aa64_sme, s) || a->mask == 0) {
diff --git a/target/avr/cpu.c b/target/avr/cpu.c
index 45ee1b5..71ce62a 100644
--- a/target/avr/cpu.c
+++ b/target/avr/cpu.c
@@ -66,7 +66,7 @@
cpu_env(cs)->pc_w = data[0];
}
-static void avr_cpu_reset_hold(Object *obj)
+static void avr_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
AVRCPU *cpu = AVR_CPU(cs);
@@ -74,7 +74,7 @@
CPUAVRState *env = &cpu->env;
if (mcc->parent_phases.hold) {
- mcc->parent_phases.hold(obj);
+ mcc->parent_phases.hold(obj, type);
}
env->pc_w = 0;
diff --git a/target/cris/cpu.c b/target/cris/cpu.c
index eb4bddc..535ec39 100644
--- a/target/cris/cpu.c
+++ b/target/cris/cpu.c
@@ -61,7 +61,7 @@
return !!(cpu_env(cs)->pregs[PR_CCS] & U_FLAG);
}
-static void cris_cpu_reset_hold(Object *obj)
+static void cris_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
CRISCPUClass *ccc = CRIS_CPU_GET_CLASS(obj);
@@ -69,7 +69,7 @@
uint32_t vr;
if (ccc->parent_phases.hold) {
- ccc->parent_phases.hold(obj);
+ ccc->parent_phases.hold(obj, type);
}
vr = env->pregs[PR_VR];
diff --git a/target/hexagon/cpu.c b/target/hexagon/cpu.c
index 3a716b9..a56bb4b 100644
--- a/target/hexagon/cpu.c
+++ b/target/hexagon/cpu.c
@@ -273,14 +273,14 @@
cpu_env(cs)->gpr[HEX_REG_PC] = data[0];
}
-static void hexagon_cpu_reset_hold(Object *obj)
+static void hexagon_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
HexagonCPUClass *mcc = HEXAGON_CPU_GET_CLASS(obj);
CPUHexagonState *env = cpu_env(cs);
if (mcc->parent_phases.hold) {
- mcc->parent_phases.hold(obj);
+ mcc->parent_phases.hold(obj, type);
}
set_default_nan_mode(1, &env->fp_status);
diff --git a/target/i386/cpu-apic.c b/target/i386/cpu-apic.c
new file mode 100644
index 0000000..d397ec94
--- /dev/null
+++ b/target/i386/cpu-apic.c
@@ -0,0 +1,112 @@
+/*
+ * QEMU x86 CPU <-> APIC
+ *
+ * Copyright (c) 2003-2004 Fabrice Bellard
+ *
+ * SPDX-License-Identifier: MIT
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/qmp/qdict.h"
+#include "qapi/error.h"
+#include "monitor/monitor.h"
+#include "monitor/hmp-target.h"
+#include "sysemu/hw_accel.h"
+#include "sysemu/kvm.h"
+#include "sysemu/xen.h"
+#include "exec/address-spaces.h"
+#include "hw/qdev-properties.h"
+#include "hw/i386/apic_internal.h"
+#include "cpu-internal.h"
+
+APICCommonClass *apic_get_class(Error **errp)
+{
+ const char *apic_type = "apic";
+
+ /* TODO: in-kernel irqchip for hvf */
+ if (kvm_enabled()) {
+ if (!kvm_irqchip_in_kernel()) {
+ error_setg(errp, "KVM does not support userspace APIC");
+ return NULL;
+ }
+ apic_type = "kvm-apic";
+ } else if (xen_enabled()) {
+ apic_type = "xen-apic";
+ } else if (whpx_apic_in_platform()) {
+ apic_type = "whpx-apic";
+ }
+
+ return APIC_COMMON_CLASS(object_class_by_name(apic_type));
+}
+
+void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
+{
+ APICCommonState *apic;
+ APICCommonClass *apic_class = apic_get_class(errp);
+
+ if (!apic_class) {
+ return;
+ }
+
+ cpu->apic_state = DEVICE(object_new_with_class(OBJECT_CLASS(apic_class)));
+ object_property_add_child(OBJECT(cpu), "lapic",
+ OBJECT(cpu->apic_state));
+ object_unref(OBJECT(cpu->apic_state));
+
+ /* TODO: convert to link<> */
+ apic = APIC_COMMON(cpu->apic_state);
+ apic->cpu = cpu;
+ apic->apicbase = APIC_DEFAULT_ADDRESS | MSR_IA32_APICBASE_ENABLE;
+
+ /*
+ * apic_common_set_id needs to check if the CPU has x2APIC
+ * feature in case APIC ID >= 255, so we need to set apic->cpu
+ * before setting APIC ID
+ */
+ qdev_prop_set_uint32(cpu->apic_state, "id", cpu->apic_id);
+}
+
+void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
+{
+ APICCommonState *apic;
+ static bool apic_mmio_map_once;
+
+ if (cpu->apic_state == NULL) {
+ return;
+ }
+ qdev_realize(DEVICE(cpu->apic_state), NULL, errp);
+
+ /* Map APIC MMIO area */
+ apic = APIC_COMMON(cpu->apic_state);
+ if (!apic_mmio_map_once) {
+ memory_region_add_subregion_overlap(get_system_memory(),
+ apic->apicbase &
+ MSR_IA32_APICBASE_BASE,
+ &apic->io_memory,
+ 0x1000);
+ apic_mmio_map_once = true;
+ }
+}
+
+void hmp_info_local_apic(Monitor *mon, const QDict *qdict)
+{
+ CPUState *cs;
+
+ if (qdict_haskey(qdict, "apic-id")) {
+ int id = qdict_get_try_int(qdict, "apic-id", 0);
+
+ cs = cpu_by_arch_id(id);
+ if (cs) {
+ cpu_synchronize_state(cs);
+ }
+ } else {
+ cs = mon_get_cpu(mon);
+ }
+
+
+ if (!cs) {
+ monitor_printf(mon, "No CPU available\n");
+ return;
+ }
+ x86_cpu_dump_local_apic_state(cs, CPU_DUMP_FPU);
+}
diff --git a/target/i386/cpu-sysemu.c b/target/i386/cpu-sysemu.c
index 3f9093d..227ac02 100644
--- a/target/i386/cpu-sysemu.c
+++ b/target/i386/cpu-sysemu.c
@@ -19,19 +19,12 @@
#include "qemu/osdep.h"
#include "cpu.h"
-#include "sysemu/kvm.h"
-#include "sysemu/xen.h"
-#include "sysemu/whpx.h"
#include "qapi/error.h"
#include "qapi/qapi-visit-run-state.h"
#include "qapi/qmp/qdict.h"
#include "qapi/qobject-input-visitor.h"
#include "qom/qom-qobject.h"
#include "qapi/qapi-commands-machine-target.h"
-#include "hw/qdev-properties.h"
-
-#include "exec/address-spaces.h"
-#include "hw/i386/apic_internal.h"
#include "cpu-internal.h"
@@ -273,75 +266,6 @@
cpu_reset(CPU(cpu));
}
-APICCommonClass *apic_get_class(Error **errp)
-{
- const char *apic_type = "apic";
-
- /* TODO: in-kernel irqchip for hvf */
- if (kvm_enabled()) {
- if (!kvm_irqchip_in_kernel()) {
- error_setg(errp, "KVM does not support userspace APIC");
- return NULL;
- }
- apic_type = "kvm-apic";
- } else if (xen_enabled()) {
- apic_type = "xen-apic";
- } else if (whpx_apic_in_platform()) {
- apic_type = "whpx-apic";
- }
-
- return APIC_COMMON_CLASS(object_class_by_name(apic_type));
-}
-
-void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
-{
- APICCommonState *apic;
- APICCommonClass *apic_class = apic_get_class(errp);
-
- if (!apic_class) {
- return;
- }
-
- cpu->apic_state = DEVICE(object_new_with_class(OBJECT_CLASS(apic_class)));
- object_property_add_child(OBJECT(cpu), "lapic",
- OBJECT(cpu->apic_state));
- object_unref(OBJECT(cpu->apic_state));
-
- /* TODO: convert to link<> */
- apic = APIC_COMMON(cpu->apic_state);
- apic->cpu = cpu;
- apic->apicbase = APIC_DEFAULT_ADDRESS | MSR_IA32_APICBASE_ENABLE;
-
- /*
- * apic_common_set_id needs to check if the CPU has x2APIC
- * feature in case APIC ID >= 255, so we need to set apic->cpu
- * before setting APIC ID
- */
- qdev_prop_set_uint32(cpu->apic_state, "id", cpu->apic_id);
-}
-
-void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
-{
- APICCommonState *apic;
- static bool apic_mmio_map_once;
-
- if (cpu->apic_state == NULL) {
- return;
- }
- qdev_realize(DEVICE(cpu->apic_state), NULL, errp);
-
- /* Map APIC MMIO area */
- apic = APIC_COMMON(cpu->apic_state);
- if (!apic_mmio_map_once) {
- memory_region_add_subregion_overlap(get_system_memory(),
- apic->apicbase &
- MSR_IA32_APICBASE_BASE,
- &apic->io_memory,
- 0x1000);
- apic_mmio_map_once = true;
- }
-}
-
GuestPanicInformation *x86_cpu_get_crash_info(CPUState *cs)
{
X86CPU *cpu = X86_CPU(cs);
@@ -385,4 +309,3 @@
errp);
qapi_free_GuestPanicInformation(panic_info);
}
-
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index fd6af0d..fa1ea37 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -6830,7 +6830,7 @@
#endif
}
-static void x86_cpu_reset_hold(Object *obj)
+static void x86_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
X86CPU *cpu = X86_CPU(cs);
@@ -6841,7 +6841,7 @@
int i;
if (xcc->parent_phases.hold) {
- xcc->parent_phases.hold(obj);
+ xcc->parent_phases.hold(obj, type);
}
memset(env, 0, offsetof(CPUX86State, end_reset_fields));
diff --git a/target/i386/meson.build b/target/i386/meson.build
index 8abce72..0751179 100644
--- a/target/i386/meson.build
+++ b/target/i386/meson.build
@@ -18,6 +18,7 @@
'arch_memory_mapping.c',
'machine.c',
'monitor.c',
+ 'cpu-apic.c',
'cpu-sysemu.c',
))
i386_system_ss.add(when: 'CONFIG_SEV', if_true: files('sev.c'), if_false: files('sev-sysemu-stub.c'))
diff --git a/target/i386/monitor.c b/target/i386/monitor.c
index 3a281da..2d766b2 100644
--- a/target/i386/monitor.c
+++ b/target/i386/monitor.c
@@ -28,8 +28,6 @@
#include "monitor/hmp-target.h"
#include "monitor/hmp.h"
#include "qapi/qmp/qdict.h"
-#include "sysemu/hw_accel.h"
-#include "sysemu/kvm.h"
#include "qapi/error.h"
#include "qapi/qapi-commands-misc-target.h"
#include "qapi/qapi-commands-misc.h"
@@ -647,26 +645,3 @@
{
return monitor_defs;
}
-
-void hmp_info_local_apic(Monitor *mon, const QDict *qdict)
-{
- CPUState *cs;
-
- if (qdict_haskey(qdict, "apic-id")) {
- int id = qdict_get_try_int(qdict, "apic-id", 0);
-
- cs = cpu_by_arch_id(id);
- if (cs) {
- cpu_synchronize_state(cs);
- }
- } else {
- cs = mon_get_cpu(mon);
- }
-
-
- if (!cs) {
- monitor_printf(mon, "No CPU available\n");
- return;
- }
- x86_cpu_dump_local_apic_state(cs, CPU_DUMP_FPU);
-}
diff --git a/target/loongarch/cpu.c b/target/loongarch/cpu.c
index 203a349..bac84dc 100644
--- a/target/loongarch/cpu.c
+++ b/target/loongarch/cpu.c
@@ -495,14 +495,14 @@
loongarch_la464_initfn(obj);
}
-static void loongarch_cpu_reset_hold(Object *obj)
+static void loongarch_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
LoongArchCPUClass *lacc = LOONGARCH_CPU_GET_CLASS(obj);
CPULoongArchState *env = cpu_env(cs);
if (lacc->parent_phases.hold) {
- lacc->parent_phases.hold(obj);
+ lacc->parent_phases.hold(obj, type);
}
env->fcsr0_mask = FCSR0_M1 | FCSR0_M2 | FCSR0_M3;
diff --git a/target/m68k/cpu.c b/target/m68k/cpu.c
index df49ff1..efd6bbd 100644
--- a/target/m68k/cpu.c
+++ b/target/m68k/cpu.c
@@ -71,7 +71,7 @@
env->features &= ~BIT_ULL(feature);
}
-static void m68k_cpu_reset_hold(Object *obj)
+static void m68k_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
M68kCPUClass *mcc = M68K_CPU_GET_CLASS(obj);
@@ -80,7 +80,7 @@
int i;
if (mcc->parent_phases.hold) {
- mcc->parent_phases.hold(obj);
+ mcc->parent_phases.hold(obj, type);
}
memset(env, 0, offsetof(CPUM68KState, end_reset_fields));
diff --git a/target/microblaze/cpu.c b/target/microblaze/cpu.c
index 96c2b71..f8dc317 100644
--- a/target/microblaze/cpu.c
+++ b/target/microblaze/cpu.c
@@ -181,7 +181,7 @@
}
#endif
-static void mb_cpu_reset_hold(Object *obj)
+static void mb_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
MicroBlazeCPU *cpu = MICROBLAZE_CPU(cs);
@@ -189,7 +189,7 @@
CPUMBState *env = &cpu->env;
if (mcc->parent_phases.hold) {
- mcc->parent_phases.hold(obj);
+ mcc->parent_phases.hold(obj, type);
}
memset(env, 0, offsetof(CPUMBState, end_reset_fields));
diff --git a/target/mips/cpu.c b/target/mips/cpu.c
index 8d8f690..bbe01d0 100644
--- a/target/mips/cpu.c
+++ b/target/mips/cpu.c
@@ -185,7 +185,7 @@
#include "cpu-defs.c.inc"
-static void mips_cpu_reset_hold(Object *obj)
+static void mips_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
MIPSCPU *cpu = MIPS_CPU(cs);
@@ -193,7 +193,7 @@
CPUMIPSState *env = &cpu->env;
if (mcc->parent_phases.hold) {
- mcc->parent_phases.hold(obj);
+ mcc->parent_phases.hold(obj, type);
}
memset(env, 0, offsetof(CPUMIPSState, end_reset_fields));
diff --git a/target/openrisc/cpu.c b/target/openrisc/cpu.c
index 33c45db..d711035 100644
--- a/target/openrisc/cpu.c
+++ b/target/openrisc/cpu.c
@@ -85,14 +85,14 @@
info->print_insn = print_insn_or1k;
}
-static void openrisc_cpu_reset_hold(Object *obj)
+static void openrisc_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
OpenRISCCPU *cpu = OPENRISC_CPU(cs);
OpenRISCCPUClass *occ = OPENRISC_CPU_GET_CLASS(obj);
if (occ->parent_phases.hold) {
- occ->parent_phases.hold(obj);
+ occ->parent_phases.hold(obj, type);
}
memset(&cpu->env, 0, offsetof(CPUOpenRISCState, end_reset_fields));
diff --git a/target/ppc/cpu_init.c b/target/ppc/cpu_init.c
index 6241de6..6d82f24 100644
--- a/target/ppc/cpu_init.c
+++ b/target/ppc/cpu_init.c
@@ -7136,7 +7136,7 @@
return ppc_env_mmu_index(cpu_env(cs), ifetch);
}
-static void ppc_cpu_reset_hold(Object *obj)
+static void ppc_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
PowerPCCPU *cpu = POWERPC_CPU(cs);
@@ -7146,7 +7146,7 @@
int i;
if (pcc->parent_phases.hold) {
- pcc->parent_phases.hold(obj);
+ pcc->parent_phases.hold(obj, type);
}
msr = (target_ulong)0;
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 36e3e5f..eb1a2e7 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -918,7 +918,7 @@
return riscv_env_mmu_index(cpu_env(cs), ifetch);
}
-static void riscv_cpu_reset_hold(Object *obj)
+static void riscv_cpu_reset_hold(Object *obj, ResetType type)
{
#ifndef CONFIG_USER_ONLY
uint8_t iprio;
@@ -930,7 +930,7 @@
CPURISCVState *env = &cpu->env;
if (mcc->parent_phases.hold) {
- mcc->parent_phases.hold(obj);
+ mcc->parent_phases.hold(obj, type);
}
#ifndef CONFIG_USER_ONLY
env->misa_mxl = mcc->misa_mxl_max;
diff --git a/target/rx/cpu.c b/target/rx/cpu.c
index da673a5..e3dfb09 100644
--- a/target/rx/cpu.c
+++ b/target/rx/cpu.c
@@ -69,7 +69,7 @@
return 0;
}
-static void rx_cpu_reset_hold(Object *obj)
+static void rx_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
RXCPUClass *rcc = RX_CPU_GET_CLASS(obj);
@@ -77,7 +77,7 @@
uint32_t *resetvec;
if (rcc->parent_phases.hold) {
- rcc->parent_phases.hold(obj);
+ rcc->parent_phases.hold(obj, type);
}
memset(env, 0, offsetof(CPURXState, end_reset_fields));
diff --git a/target/s390x/cpu_models.h b/target/s390x/cpu_models.h
index d7b8912..a89c2a1 100644
--- a/target/s390x/cpu_models.h
+++ b/target/s390x/cpu_models.h
@@ -114,23 +114,8 @@
S390CPUDef const *s390_find_cpu_def(uint16_t type, uint8_t gen, uint8_t ec_ga,
S390FeatBitmap features);
-#ifdef CONFIG_KVM
bool kvm_s390_cpu_models_supported(void);
void kvm_s390_get_host_cpu_model(S390CPUModel *model, Error **errp);
void kvm_s390_apply_cpu_model(const S390CPUModel *model, Error **errp);
-#else
-static inline void kvm_s390_get_host_cpu_model(S390CPUModel *model,
- Error **errp)
-{
-}
-static inline void kvm_s390_apply_cpu_model(const S390CPUModel *model,
- Error **errp)
-{
-}
-static inline bool kvm_s390_cpu_models_supported(void)
-{
- return false;
-}
-#endif
#endif /* TARGET_S390X_CPU_MODELS_H */
diff --git a/target/sh4/cpu.c b/target/sh4/cpu.c
index 4f5a4a3..43e35ec 100644
--- a/target/sh4/cpu.c
+++ b/target/sh4/cpu.c
@@ -103,14 +103,14 @@
}
}
-static void superh_cpu_reset_hold(Object *obj)
+static void superh_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
SuperHCPUClass *scc = SUPERH_CPU_GET_CLASS(obj);
CPUSH4State *env = cpu_env(cs);
if (scc->parent_phases.hold) {
- scc->parent_phases.hold(obj);
+ scc->parent_phases.hold(obj, type);
}
memset(env, 0, offsetof(CPUSH4State, end_reset_fields));
diff --git a/target/sparc/cpu.c b/target/sparc/cpu.c
index e820f50..485d416 100644
--- a/target/sparc/cpu.c
+++ b/target/sparc/cpu.c
@@ -29,14 +29,14 @@
//#define DEBUG_FEATURES
-static void sparc_cpu_reset_hold(Object *obj)
+static void sparc_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
SPARCCPUClass *scc = SPARC_CPU_GET_CLASS(obj);
CPUSPARCState *env = cpu_env(cs);
if (scc->parent_phases.hold) {
- scc->parent_phases.hold(obj);
+ scc->parent_phases.hold(obj, type);
}
memset(env, 0, offsetof(CPUSPARCState, end_reset_fields));
diff --git a/target/tricore/cpu.c b/target/tricore/cpu.c
index a9af73a..8f9b72c 100644
--- a/target/tricore/cpu.c
+++ b/target/tricore/cpu.c
@@ -58,13 +58,13 @@
cpu_env(cs)->PC = data[0];
}
-static void tricore_cpu_reset_hold(Object *obj)
+static void tricore_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
TriCoreCPUClass *tcc = TRICORE_CPU_GET_CLASS(obj);
if (tcc->parent_phases.hold) {
- tcc->parent_phases.hold(obj);
+ tcc->parent_phases.hold(obj, type);
}
cpu_state_reset(cpu_env(cs));
diff --git a/target/xtensa/cpu.c b/target/xtensa/cpu.c
index 875cf84..de907cf 100644
--- a/target/xtensa/cpu.c
+++ b/target/xtensa/cpu.c
@@ -93,7 +93,7 @@
}
#endif
-static void xtensa_cpu_reset_hold(Object *obj)
+static void xtensa_cpu_reset_hold(Object *obj, ResetType type)
{
CPUState *cs = CPU(obj);
XtensaCPUClass *xcc = XTENSA_CPU_GET_CLASS(obj);
@@ -102,7 +102,7 @@
XTENSA_OPTION_DFP_COPROCESSOR);
if (xcc->parent_phases.hold) {
- xcc->parent_phases.hold(obj);
+ xcc->parent_phases.hold(obj, type);
}
env->pc = env->config->exception_vector[EXC_RESET0 + env->static_vectors];
diff --git a/tests/docker/dockerfiles/alpine.docker b/tests/docker/dockerfiles/alpine.docker
index 42f6928..cd9d7af 100644
--- a/tests/docker/dockerfiles/alpine.docker
+++ b/tests/docker/dockerfiles/alpine.docker
@@ -116,7 +116,8 @@
zlib-static \
zstd \
zstd-dev && \
- apk list | sort > /packages.txt && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED && \
+ apk list --installed | sort > /packages.txt && \
mkdir -p /usr/libexec/ccache-wrappers && \
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/cc && \
diff --git a/tests/docker/dockerfiles/centos8.docker b/tests/docker/dockerfiles/centos9.docker
similarity index 82%
rename from tests/docker/dockerfiles/centos8.docker
rename to tests/docker/dockerfiles/centos9.docker
index d97c30e..6cf47ce 100644
--- a/tests/docker/dockerfiles/centos8.docker
+++ b/tests/docker/dockerfiles/centos9.docker
@@ -1,15 +1,14 @@
# THIS FILE WAS AUTO-GENERATED
#
-# $ lcitool dockerfile --layers all centos-stream-8 qemu
+# $ lcitool dockerfile --layers all centos-stream-9 qemu
#
# https://gitlab.com/libvirt/libvirt-ci
-FROM quay.io/centos/centos:stream8
+FROM quay.io/centos/centos:stream9
RUN dnf distro-sync -y && \
dnf install 'dnf-command(config-manager)' -y && \
- dnf config-manager --set-enabled -y powertools && \
- dnf install -y centos-release-advanced-virtualization && \
+ dnf config-manager --set-enabled -y crb && \
dnf install -y epel-release && \
dnf install -y epel-next-release && \
dnf install -y \
@@ -42,7 +41,6 @@
glib2-static \
glibc-langpack-en \
glibc-static \
- glusterfs-api-devel \
gnutls-devel \
gtk3-devel \
hostname \
@@ -82,6 +80,7 @@
lzo-devel \
make \
mesa-libgbm-devel \
+ meson \
mtools \
ncurses-devel \
nettle-devel \
@@ -95,25 +94,25 @@
pixman-devel \
pkgconfig \
pulseaudio-libs-devel \
- python38 \
- python38-PyYAML \
- python38-numpy \
- python38-pip \
- python38-setuptools \
- python38-wheel \
+ python3 \
+ python3-PyYAML \
+ python3-numpy \
+ python3-pillow \
+ python3-pip \
+ python3-sphinx \
+ python3-sphinx_rtd_theme \
+ python3-tomli \
rdma-core-devel \
sed \
snappy-devel \
socat \
spice-protocol \
- spice-server-devel \
swtpm \
systemd-devel \
systemtap-sdt-devel \
tar \
usbredir-devel \
util-linux \
- virglrenderer-devel \
vte291-devel \
which \
xfsprogs-devel \
@@ -123,6 +122,7 @@
zstd && \
dnf autoremove -y && \
dnf clean all -y && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED && \
rpm -qa | sort > /packages.txt && \
mkdir -p /usr/libexec/ccache-wrappers && \
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \
@@ -131,18 +131,11 @@
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc
-RUN /usr/bin/pip3.8 install \
- meson==0.63.2 \
- pillow \
- sphinx \
- sphinx-rtd-theme \
- tomli
-
ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
ENV LANG "en_US.UTF-8"
ENV MAKE "/usr/bin/make"
ENV NINJA "/usr/bin/ninja"
-ENV PYTHON "/usr/bin/python3.8"
+ENV PYTHON "/usr/bin/python3"
# As a final step configure the user (if env is defined)
ARG USER
ARG UID
diff --git a/tests/docker/dockerfiles/debian-amd64-cross.docker b/tests/docker/dockerfiles/debian-amd64-cross.docker
index 00bdc06..d0b0e97 100644
--- a/tests/docker/dockerfiles/debian-amd64-cross.docker
+++ b/tests/docker/dockerfiles/debian-amd64-cross.docker
@@ -64,7 +64,8 @@
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
- dpkg-reconfigure locales
+ dpkg-reconfigure locales && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED
ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
ENV LANG "en_US.UTF-8"
diff --git a/tests/docker/dockerfiles/debian-arm64-cross.docker b/tests/docker/dockerfiles/debian-arm64-cross.docker
index 2dae377..8cb2257 100644
--- a/tests/docker/dockerfiles/debian-arm64-cross.docker
+++ b/tests/docker/dockerfiles/debian-arm64-cross.docker
@@ -64,7 +64,8 @@
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
- dpkg-reconfigure locales
+ dpkg-reconfigure locales && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED
ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
ENV LANG "en_US.UTF-8"
diff --git a/tests/docker/dockerfiles/debian-armel-cross.docker b/tests/docker/dockerfiles/debian-armel-cross.docker
index 75342c0..e6f3741 100644
--- a/tests/docker/dockerfiles/debian-armel-cross.docker
+++ b/tests/docker/dockerfiles/debian-armel-cross.docker
@@ -65,7 +65,8 @@
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
- dpkg-reconfigure locales
+ dpkg-reconfigure locales && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED
RUN /usr/bin/pip3 install tomli
diff --git a/tests/docker/dockerfiles/debian-armhf-cross.docker b/tests/docker/dockerfiles/debian-armhf-cross.docker
index 180ed83..407a014 100644
--- a/tests/docker/dockerfiles/debian-armhf-cross.docker
+++ b/tests/docker/dockerfiles/debian-armhf-cross.docker
@@ -64,7 +64,8 @@
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
- dpkg-reconfigure locales
+ dpkg-reconfigure locales && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED
ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
ENV LANG "en_US.UTF-8"
diff --git a/tests/docker/dockerfiles/debian-i686-cross.docker b/tests/docker/dockerfiles/debian-i686-cross.docker
index 3fc4e15..bdc9566 100644
--- a/tests/docker/dockerfiles/debian-i686-cross.docker
+++ b/tests/docker/dockerfiles/debian-i686-cross.docker
@@ -65,7 +65,8 @@
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
- dpkg-reconfigure locales
+ dpkg-reconfigure locales && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED
RUN /usr/bin/pip3 install tomli
diff --git a/tests/docker/dockerfiles/debian-mips64el-cross.docker b/tests/docker/dockerfiles/debian-mips64el-cross.docker
index 17d3e01..4d995d0 100644
--- a/tests/docker/dockerfiles/debian-mips64el-cross.docker
+++ b/tests/docker/dockerfiles/debian-mips64el-cross.docker
@@ -65,7 +65,8 @@
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
- dpkg-reconfigure locales
+ dpkg-reconfigure locales && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED
RUN /usr/bin/pip3 install tomli
diff --git a/tests/docker/dockerfiles/debian-mipsel-cross.docker b/tests/docker/dockerfiles/debian-mipsel-cross.docker
index 5fcd641..0cf803b 100644
--- a/tests/docker/dockerfiles/debian-mipsel-cross.docker
+++ b/tests/docker/dockerfiles/debian-mipsel-cross.docker
@@ -65,7 +65,8 @@
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
- dpkg-reconfigure locales
+ dpkg-reconfigure locales && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED
RUN /usr/bin/pip3 install tomli
diff --git a/tests/docker/dockerfiles/debian-ppc64el-cross.docker b/tests/docker/dockerfiles/debian-ppc64el-cross.docker
index d6be2f0..6180ec0 100644
--- a/tests/docker/dockerfiles/debian-ppc64el-cross.docker
+++ b/tests/docker/dockerfiles/debian-ppc64el-cross.docker
@@ -64,7 +64,8 @@
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
- dpkg-reconfigure locales
+ dpkg-reconfigure locales && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED
ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
ENV LANG "en_US.UTF-8"
diff --git a/tests/docker/dockerfiles/debian-riscv64-cross.docker b/tests/docker/dockerfiles/debian-riscv64-cross.docker
index a26637e..591572a 100644
--- a/tests/docker/dockerfiles/debian-riscv64-cross.docker
+++ b/tests/docker/dockerfiles/debian-riscv64-cross.docker
@@ -33,7 +33,8 @@
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
- dpkg-reconfigure locales
+ dpkg-reconfigure locales && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED
ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
ENV LANG "en_US.UTF-8"
diff --git a/tests/docker/dockerfiles/debian-s390x-cross.docker b/tests/docker/dockerfiles/debian-s390x-cross.docker
index ec0041d..90c8d3c 100644
--- a/tests/docker/dockerfiles/debian-s390x-cross.docker
+++ b/tests/docker/dockerfiles/debian-s390x-cross.docker
@@ -64,7 +64,8 @@
eatmydata apt-get autoremove -y && \
eatmydata apt-get autoclean -y && \
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
- dpkg-reconfigure locales
+ dpkg-reconfigure locales && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED
ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
ENV LANG "en_US.UTF-8"
diff --git a/tests/docker/dockerfiles/debian.docker b/tests/docker/dockerfiles/debian.docker
index b5e642d..5722482 100644
--- a/tests/docker/dockerfiles/debian.docker
+++ b/tests/docker/dockerfiles/debian.docker
@@ -137,6 +137,7 @@
eatmydata apt-get autoclean -y && \
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
dpkg-reconfigure locales && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED && \
dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt && \
mkdir -p /usr/libexec/ccache-wrappers && \
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \
diff --git a/tests/docker/dockerfiles/fedora-win64-cross.docker b/tests/docker/dockerfiles/fedora-win64-cross.docker
index f8e4cb7..d1a480f 100644
--- a/tests/docker/dockerfiles/fedora-win64-cross.docker
+++ b/tests/docker/dockerfiles/fedora-win64-cross.docker
@@ -64,7 +64,8 @@
xorriso \
zstd && \
nosync dnf autoremove -y && \
- nosync dnf clean all -y
+ nosync dnf clean all -y && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED
ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
ENV LANG "en_US.UTF-8"
diff --git a/tests/docker/dockerfiles/fedora.docker b/tests/docker/dockerfiles/fedora.docker
index 9e9c71f..7e6ab03 100644
--- a/tests/docker/dockerfiles/fedora.docker
+++ b/tests/docker/dockerfiles/fedora.docker
@@ -137,6 +137,7 @@
zstd && \
nosync dnf autoremove -y && \
nosync dnf clean all -y && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED && \
rpm -qa | sort > /packages.txt && \
mkdir -p /usr/libexec/ccache-wrappers && \
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \
diff --git a/tests/docker/dockerfiles/opensuse-leap.docker b/tests/docker/dockerfiles/opensuse-leap.docker
index cf75338..c4055bd 100644
--- a/tests/docker/dockerfiles/opensuse-leap.docker
+++ b/tests/docker/dockerfiles/opensuse-leap.docker
@@ -119,6 +119,7 @@
zlib-devel-static \
zstd && \
zypper clean --all && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED && \
rpm -qa | sort > /packages.txt && \
mkdir -p /usr/libexec/ccache-wrappers && \
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \
diff --git a/tests/docker/dockerfiles/ubuntu2004.docker b/tests/docker/dockerfiles/ubuntu2004.docker
deleted file mode 100644
index d3e2120..0000000
--- a/tests/docker/dockerfiles/ubuntu2004.docker
+++ /dev/null
@@ -1,157 +0,0 @@
-# THIS FILE WAS AUTO-GENERATED
-#
-# $ lcitool dockerfile --layers all ubuntu-2004 qemu
-#
-# https://gitlab.com/libvirt/libvirt-ci
-
-FROM docker.io/library/ubuntu:20.04
-
-RUN export DEBIAN_FRONTEND=noninteractive && \
- apt-get update && \
- apt-get install -y eatmydata && \
- eatmydata apt-get dist-upgrade -y && \
- eatmydata apt-get install --no-install-recommends -y \
- bash \
- bc \
- bison \
- bsdmainutils \
- bzip2 \
- ca-certificates \
- ccache \
- clang \
- dbus \
- debianutils \
- diffutils \
- exuberant-ctags \
- findutils \
- flex \
- g++ \
- gcc \
- gcovr \
- gettext \
- git \
- hostname \
- libaio-dev \
- libasan6 \
- libasound2-dev \
- libattr1-dev \
- libbrlapi-dev \
- libbz2-dev \
- libc6-dev \
- libcacard-dev \
- libcap-ng-dev \
- libcapstone-dev \
- libcmocka-dev \
- libcurl4-gnutls-dev \
- libdaxctl-dev \
- libdrm-dev \
- libepoxy-dev \
- libfdt-dev \
- libffi-dev \
- libfuse3-dev \
- libgbm-dev \
- libgcrypt20-dev \
- libglib2.0-dev \
- libglusterfs-dev \
- libgnutls28-dev \
- libgtk-3-dev \
- libibumad-dev \
- libibverbs-dev \
- libiscsi-dev \
- libjemalloc-dev \
- libjpeg-turbo8-dev \
- libjson-c-dev \
- liblttng-ust-dev \
- liblzo2-dev \
- libncursesw5-dev \
- libnfs-dev \
- libnuma-dev \
- libpam0g-dev \
- libpcre2-dev \
- libpixman-1-dev \
- libpmem-dev \
- libpng-dev \
- libpulse-dev \
- librbd-dev \
- librdmacm-dev \
- libsasl2-dev \
- libsdl2-dev \
- libsdl2-image-dev \
- libseccomp-dev \
- libselinux1-dev \
- libslirp-dev \
- libsnappy-dev \
- libsndio-dev \
- libspice-protocol-dev \
- libspice-server-dev \
- libssh-dev \
- libsystemd-dev \
- libtasn1-6-dev \
- libubsan1 \
- libudev-dev \
- libusb-1.0-0-dev \
- libusbredirhost-dev \
- libvdeplug-dev \
- libvirglrenderer-dev \
- libvte-2.91-dev \
- libxen-dev \
- libzstd-dev \
- llvm \
- locales \
- make \
- mtools \
- multipath-tools \
- ncat \
- nettle-dev \
- ninja-build \
- openssh-client \
- pkgconf \
- python3 \
- python3-numpy \
- python3-opencv \
- python3-pillow \
- python3-pip \
- python3-setuptools \
- python3-sphinx \
- python3-sphinx-rtd-theme \
- python3-venv \
- python3-wheel \
- python3-yaml \
- rpm2cpio \
- sed \
- socat \
- sparse \
- systemtap-sdt-dev \
- tar \
- tesseract-ocr \
- tesseract-ocr-eng \
- xfslibs-dev \
- xorriso \
- zlib1g-dev \
- zstd && \
- eatmydata apt-get autoremove -y && \
- eatmydata apt-get autoclean -y && \
- sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
- dpkg-reconfigure locales && \
- dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt && \
- mkdir -p /usr/libexec/ccache-wrappers && \
- ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \
- ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/cc && \
- ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/clang && \
- ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/g++ && \
- ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/gcc
-
-RUN /usr/bin/pip3 install \
- meson==0.63.2 \
- tomli
-
-ENV CCACHE_WRAPPERSDIR "/usr/libexec/ccache-wrappers"
-ENV LANG "en_US.UTF-8"
-ENV MAKE "/usr/bin/make"
-ENV NINJA "/usr/bin/ninja"
-ENV PYTHON "/usr/bin/python3"
-# As a final step configure the user (if env is defined)
-ARG USER
-ARG UID
-RUN if [ "${USER}" ]; then \
- id ${USER} 2>/dev/null || useradd -u ${UID} -U ${USER}; fi
diff --git a/tests/docker/dockerfiles/ubuntu2204.docker b/tests/docker/dockerfiles/ubuntu2204.docker
index 2ca9cff..b8e7833 100644
--- a/tests/docker/dockerfiles/ubuntu2204.docker
+++ b/tests/docker/dockerfiles/ubuntu2204.docker
@@ -137,6 +137,7 @@
eatmydata apt-get autoclean -y && \
sed -Ei 's,^# (en_US\.UTF-8 .*)$,\1,' /etc/locale.gen && \
dpkg-reconfigure locales && \
+ rm -f /usr/lib*/python3*/EXTERNALLY-MANAGED && \
dpkg-query --showformat '${Package}_${Version}_${Architecture}\n' --show > /packages.txt && \
mkdir -p /usr/libexec/ccache-wrappers && \
ln -s /usr/bin/ccache /usr/libexec/ccache-wrappers/c++ && \
diff --git a/tests/lcitool/libvirt-ci b/tests/lcitool/libvirt-ci
index 77c8001..cec6703 160000
--- a/tests/lcitool/libvirt-ci
+++ b/tests/lcitool/libvirt-ci
@@ -1 +1 @@
-Subproject commit 77c800186f34b21be7660750577cc5582a914deb
+Subproject commit cec67039719becbfbab866f9c23574f389cf9559
diff --git a/tests/lcitool/mappings.yml b/tests/lcitool/mappings.yml
index 407c033..03b974a 100644
--- a/tests/lcitool/mappings.yml
+++ b/tests/lcitool/mappings.yml
@@ -1,66 +1,50 @@
mappings:
flake8:
- CentOSStream8:
OpenSUSELeap15:
meson:
- CentOSStream8:
OpenSUSELeap15:
python3:
- CentOSStream8: python38
OpenSUSELeap15: python311-base
python3-PyYAML:
- CentOSStream8: python38-PyYAML
OpenSUSELeap15:
python3-devel:
- CentOSStream8: python38-devel
OpenSUSELeap15: python311-devel
python3-docutils:
- CentOSStream8:
OpenSUSELeap15:
python3-numpy:
- CentOSStream8: python38-numpy
OpenSUSELeap15:
python3-opencv:
- CentOSStream8:
OpenSUSELeap15:
python3-pillow:
- CentOSStream8:
OpenSUSELeap15:
python3-pip:
- CentOSStream8: python38-pip
OpenSUSELeap15: python311-pip
python3-pillow:
- CentOSStream8:
OpenSUSELeap15:
python3-selinux:
- CentOSStream8:
OpenSUSELeap15:
python3-setuptools:
- CentOSStream8: python38-setuptools
OpenSUSELeap15: python311-setuptools
python3-sphinx:
- CentOSStream8:
OpenSUSELeap15:
python3-sphinx-rtd-theme:
- CentOSStream8:
OpenSUSELeap15:
python3-sqlite3:
- CentOSStream8: python38
OpenSUSELeap15: python311
python3-tomli:
@@ -69,15 +53,11 @@
Fedora:
Debian12:
OpenSUSELeap15:
- # Not available for Python 3.8
- CentOSStream8:
python3-venv:
- CentOSStream8: python38
OpenSUSELeap15: python311-base
python3-wheel:
- CentOSStream8: python38-wheel
OpenSUSELeap15: python311-pip
pypi_mappings:
diff --git a/tests/lcitool/refresh b/tests/lcitool/refresh
index fe7692c..24a735a 100755
--- a/tests/lcitool/refresh
+++ b/tests/lcitool/refresh
@@ -125,12 +125,11 @@
# Standard native builds
#
generate_dockerfile("alpine", "alpine-318")
- generate_dockerfile("centos8", "centos-stream-8")
+ generate_dockerfile("centos9", "centos-stream-9")
generate_dockerfile("debian", "debian-12",
trailer="".join(debian12_extras))
generate_dockerfile("fedora", "fedora-38")
generate_dockerfile("opensuse-leap", "opensuse-leap-15")
- generate_dockerfile("ubuntu2004", "ubuntu-2004")
generate_dockerfile("ubuntu2204", "ubuntu-2204")
#
diff --git a/tests/qtest/aspeed_fsi-test.c b/tests/qtest/aspeed_fsi-test.c
index b3020dd..f5ab269 100644
--- a/tests/qtest/aspeed_fsi-test.c
+++ b/tests/qtest/aspeed_fsi-test.c
@@ -63,22 +63,22 @@
/* Unselect FSI1 */
aspeed_fsi_writel(s, ASPEED_FSI_OPB1_BUS_SELECT, 0x0);
curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB1_BUS_SELECT);
- g_assert_cmpuint(curval, ==, 0x0);
+ g_assert_cmphex(curval, ==, 0x0);
/* Select FSI0 */
aspeed_fsi_writel(s, ASPEED_FSI_OPB0_BUS_SELECT, 0x1);
curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB0_BUS_SELECT);
- g_assert_cmpuint(curval, ==, 0x1);
+ g_assert_cmphex(curval, ==, 0x1);
} else if (base_addr == AST2600_OPB_FSI1_BASE_ADDR) {
/* Unselect FSI0 */
aspeed_fsi_writel(s, ASPEED_FSI_OPB0_BUS_SELECT, 0x0);
curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB0_BUS_SELECT);
- g_assert_cmpuint(curval, ==, 0x0);
+ g_assert_cmphex(curval, ==, 0x0);
/* Select FSI1 */
aspeed_fsi_writel(s, ASPEED_FSI_OPB1_BUS_SELECT, 0x1);
curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB1_BUS_SELECT);
- g_assert_cmpuint(curval, ==, 0x1);
+ g_assert_cmphex(curval, ==, 0x1);
} else {
g_assert_not_reached();
}
@@ -145,11 +145,11 @@
aspeed_fsi_writel(s, ASPEED_FSI_ENGINER_TRIGGER, 0x1);
curval = aspeed_fsi_readl(s, ASPEED_FSI_INTRRUPT_STATUS);
- g_assert_cmpuint(curval, ==, 0x10000);
+ g_assert_cmphex(curval, ==, 0x10000);
curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB0_BUS_STATUS);
- g_assert_cmpuint(curval, ==, 0x0);
+ g_assert_cmphex(curval, ==, 0x0);
curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB0_READ_DATA);
- g_assert_cmpuint(curval, ==, 0x152d02c0);
+ g_assert_cmphex(curval, ==, 0x152d02c0);
}
static void test_fsi1_getcfam_addr0(const void *data)
@@ -168,11 +168,11 @@
aspeed_fsi_writel(s, ASPEED_FSI_ENGINER_TRIGGER, 0x1);
curval = aspeed_fsi_readl(s, ASPEED_FSI_INTRRUPT_STATUS);
- g_assert_cmpuint(curval, ==, 0x20000);
+ g_assert_cmphex(curval, ==, 0x20000);
curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB1_BUS_STATUS);
- g_assert_cmpuint(curval, ==, 0x0);
+ g_assert_cmphex(curval, ==, 0x0);
curval = aspeed_fsi_readl(s, ASPEED_FSI_OPB1_READ_DATA);
- g_assert_cmpuint(curval, ==, 0x152d02c0);
+ g_assert_cmphex(curval, ==, 0x152d02c0);
}
int main(int argc, char **argv)
diff --git a/tests/qtest/cmsdk-apb-dualtimer-test.c b/tests/qtest/cmsdk-apb-dualtimer-test.c
index ad6a758..3b89bed 100644
--- a/tests/qtest/cmsdk-apb-dualtimer-test.c
+++ b/tests/qtest/cmsdk-apb-dualtimer-test.c
@@ -69,7 +69,7 @@
* tick VALUE should have wrapped round to 0xffff.
*/
clock_step(40);
- g_assert_cmpuint(readl(TIMER_BASE + TIMER1VALUE), ==, 0xffff);
+ g_assert_cmphex(readl(TIMER_BASE + TIMER1VALUE), ==, 0xffff);
/* Check that any write to INTCLR clears interrupt */
writel(TIMER_BASE + TIMER1INTCLR, 1);
diff --git a/tests/qtest/cmsdk-apb-watchdog-test.c b/tests/qtest/cmsdk-apb-watchdog-test.c
index 2710cb1..00b5dbb 100644
--- a/tests/qtest/cmsdk-apb-watchdog-test.c
+++ b/tests/qtest/cmsdk-apb-watchdog-test.c
@@ -88,7 +88,7 @@
/* Rewrite RCC.SYSDIV from 16 to 8, so the clock is now 40ns per tick */
rcc = readl(SSYS_BASE + RCC);
- g_assert_cmpuint(extract32(rcc, SYSDIV_SHIFT, SYSDIV_LENGTH), ==, 0xf);
+ g_assert_cmphex(extract32(rcc, SYSDIV_SHIFT, SYSDIV_LENGTH), ==, 0xf);
rcc = deposit32(rcc, SYSDIV_SHIFT, SYSDIV_LENGTH, 7);
writel(SSYS_BASE + RCC, rcc);
diff --git a/tests/qtest/erst-test.c b/tests/qtest/erst-test.c
index c45bee7..36bbe12 100644
--- a/tests/qtest/erst-test.c
+++ b/tests/qtest/erst-test.c
@@ -109,7 +109,7 @@
g_assert_cmpuint(s->reg_barsize, ==, 16);
s->mem_bar = qpci_iomap(s->dev, 1, &s->mem_barsize);
- g_assert_cmpuint(s->mem_barsize, ==, 0x2000);
+ g_assert_cmphex(s->mem_barsize, ==, 0x2000);
qpci_device_enable(s->dev);
}
diff --git a/tests/qtest/fuzz/qos_fuzz.c b/tests/qtest/fuzz/qos_fuzz.c
index e403d37..b71e945 100644
--- a/tests/qtest/fuzz/qos_fuzz.c
+++ b/tests/qtest/fuzz/qos_fuzz.c
@@ -46,7 +46,7 @@
MachineInfoList *mach_info;
ObjectTypeInfoList *type_info;
- mach_info = qmp_query_machines(&error_abort);
+ mach_info = qmp_query_machines(false, false, &error_abort);
machines_apply_to_node(mach_info);
qapi_free_MachineInfoList(mach_info);
diff --git a/tests/qtest/ivshmem-test.c b/tests/qtest/ivshmem-test.c
index 9bf8e78..fb45fde 100644
--- a/tests/qtest/ivshmem-test.c
+++ b/tests/qtest/ivshmem-test.c
@@ -158,7 +158,7 @@
/* trigger interrupt via registers */
out_reg(s, INTRMASK, 0xffffffff);
- g_assert_cmpuint(in_reg(s, INTRMASK), ==, 0xffffffff);
+ g_assert_cmphex(in_reg(s, INTRMASK), ==, 0xffffffff);
out_reg(s, INTRSTATUS, 1);
/* check interrupt status */
g_assert_cmpuint(in_reg(s, INTRSTATUS), ==, 1);
@@ -211,11 +211,11 @@
memset(tmpshmem, 0x42, TMPSHMSIZE);
read_mem(s1, 0, data, TMPSHMSIZE);
for (i = 0; i < TMPSHMSIZE; i++) {
- g_assert_cmpuint(data[i], ==, 0x42);
+ g_assert_cmphex(data[i], ==, 0x42);
}
read_mem(s2, 0, data, TMPSHMSIZE);
for (i = 0; i < TMPSHMSIZE; i++) {
- g_assert_cmpuint(data[i], ==, 0x42);
+ g_assert_cmphex(data[i], ==, 0x42);
}
/* guest 1 write, guest 2 read */
@@ -224,7 +224,7 @@
memset(data, 0, TMPSHMSIZE);
read_mem(s2, 0, data, TMPSHMSIZE);
for (i = 0; i < TMPSHMSIZE; i++) {
- g_assert_cmpuint(data[i], ==, 0x43);
+ g_assert_cmphex(data[i], ==, 0x43);
}
/* guest 2 write, guest 1 read */
@@ -233,7 +233,7 @@
memset(data, 0, TMPSHMSIZE);
read_mem(s1, 0, data, TMPSHMSIZE);
for (i = 0; i < TMPSHMSIZE; i++) {
- g_assert_cmpuint(data[i], ==, 0x44);
+ g_assert_cmphex(data[i], ==, 0x44);
}
cleanup_vm(s1);
diff --git a/tests/qtest/libqos/ahci.c b/tests/qtest/libqos/ahci.c
index 6d59c75..34a75b7 100644
--- a/tests/qtest/libqos/ahci.c
+++ b/tests/qtest/libqos/ahci.c
@@ -1046,7 +1046,7 @@
case CMD_ATAPI_REQUEST_SENSE:
case CMD_ATAPI_TEST_UNIT_READY:
case CMD_ATAPI_START_STOP_UNIT:
- g_assert_cmpuint(lba, ==, 0x00);
+ g_assert_cmphex(lba, ==, 0x00);
break;
default:
/* SCSI doesn't have uniform packet formats,
@@ -1109,7 +1109,7 @@
break;
case CMD_ATAPI_READ_CD:
/* 24bit BE store */
- g_assert_cmpuint(nsectors, <, 1ULL << 24);
+ g_assert_cmphex(nsectors, <, 1ULL << 24);
tmp = nsectors;
cbd[6] = (tmp & 0xFF0000) >> 16;
cbd[7] = (tmp & 0xFF00) >> 8;
diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
index 36c5c13..b128fa5 100644
--- a/tests/qtest/meson.build
+++ b/tests/qtest/meson.build
@@ -7,6 +7,7 @@
'npcm7xx_pwm-test': 300,
'npcm7xx_watchdog_timer-test': 120,
'qom-test' : 900,
+ 'stm32l4x5_usart-test' : 600,
'test-hmp' : 240,
'pxe-test': 610,
'prom-env-test': 360,
@@ -205,7 +206,8 @@
['stm32l4x5_exti-test',
'stm32l4x5_syscfg-test',
'stm32l4x5_rcc-test',
- 'stm32l4x5_gpio-test']
+ 'stm32l4x5_gpio-test',
+ 'stm32l4x5_usart-test']
qtests_arm = \
(config_all_devices.has_key('CONFIG_MPS2') ? ['sse-timer-test'] : []) + \
diff --git a/tests/qtest/microbit-test.c b/tests/qtest/microbit-test.c
index 72190d3..505c831 100644
--- a/tests/qtest/microbit-test.c
+++ b/tests/qtest/microbit-test.c
@@ -143,14 +143,14 @@
/* MMA8653 magnetometer detection */
val = i2c_read_byte(qts, 0x3A, 0x0D);
- g_assert_cmpuint(val, ==, 0x5A);
+ g_assert_cmphex(val, ==, 0x5A);
val = i2c_read_byte(qts, 0x3A, 0x0D);
- g_assert_cmpuint(val, ==, 0x5A);
+ g_assert_cmphex(val, ==, 0x5A);
/* LSM303 accelerometer detection */
val = i2c_read_byte(qts, 0x3C, 0x4F);
- g_assert_cmpuint(val, ==, 0x40);
+ g_assert_cmphex(val, ==, 0x40);
qtest_writel(qts, NRF51_TWI_BASE + NRF51_TWI_REG_ENABLE, 0);
@@ -171,7 +171,7 @@
/* Check memory */
for (i = 0; i < size / 4; i++) {
- g_assert_cmpuint(qtest_readl(qts, base + i * 4), ==, 0xFFFFFFFF);
+ g_assert_cmphex(qtest_readl(qts, base + i * 4), ==, 0xFFFFFFFF);
}
/* Fill memory */
@@ -191,7 +191,7 @@
/* Test always ready */
value = qtest_readl(qts, NRF51_NVMC_BASE + NRF51_NVMC_READY);
- g_assert_cmpuint(value & 0x01, ==, 0x01);
+ g_assert_cmphex(value & 0x01, ==, 0x01);
/* Test write-read config register */
qtest_writel(qts, NRF51_NVMC_BASE + NRF51_NVMC_CONFIG, 0x03);
@@ -302,19 +302,19 @@
g_assert_cmpuint(actual, ==, expected);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START)
& 0x01;
- g_assert_cmpuint(actual, ==, 0x01);
+ g_assert_cmphex(actual, ==, 0x01);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
- g_assert_cmpuint(actual, ==, 0x01);
+ g_assert_cmphex(actual, ==, 0x01);
/* Check clear via DIRCLR */
qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_DIRCLR, 0x80000001);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR);
- g_assert_cmpuint(actual, ==, 0x00000000);
+ g_assert_cmphex(actual, ==, 0x00000000);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START)
& 0x01;
- g_assert_cmpuint(actual, ==, 0x00);
+ g_assert_cmphex(actual, ==, 0x00);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
- g_assert_cmpuint(actual, ==, 0x00);
+ g_assert_cmphex(actual, ==, 0x00);
/* Check set via DIR */
expected = 0x80000001;
@@ -323,9 +323,9 @@
g_assert_cmpuint(actual, ==, expected);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START)
& 0x01;
- g_assert_cmpuint(actual, ==, 0x01);
+ g_assert_cmphex(actual, ==, 0x01);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_END) & 0x01;
- g_assert_cmpuint(actual, ==, 0x01);
+ g_assert_cmphex(actual, ==, 0x01);
/* Reset DIR */
qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_DIR, 0x00000000);
@@ -334,33 +334,33 @@
qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x00);
qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
- g_assert_cmpuint(actual, ==, 0x00);
+ g_assert_cmphex(actual, ==, 0x00);
qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
- g_assert_cmpuint(actual, ==, 0x01);
+ g_assert_cmphex(actual, ==, 0x01);
qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 0, -1);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
- g_assert_cmpuint(actual, ==, 0x01);
+ g_assert_cmphex(actual, ==, 0x01);
qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
/* Check pull-up working */
qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 0, 0);
qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
- g_assert_cmpuint(actual, ==, 0x00);
+ g_assert_cmphex(actual, ==, 0x00);
qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b1110);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
- g_assert_cmpuint(actual, ==, 0x01);
+ g_assert_cmphex(actual, ==, 0x01);
qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
/* Check pull-down working */
qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 0, 1);
qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0000);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
- g_assert_cmpuint(actual, ==, 0x01);
+ g_assert_cmphex(actual, ==, 0x01);
qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b0110);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
- g_assert_cmpuint(actual, ==, 0x00);
+ g_assert_cmphex(actual, ==, 0x00);
qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0x02);
qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", 0, -1);
@@ -376,11 +376,11 @@
qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_CNF_START, 0b01);
qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTSET, 0x01);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
- g_assert_cmpuint(actual, ==, 0x01);
+ g_assert_cmphex(actual, ==, 0x01);
qtest_writel(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_OUTCLR, 0x01);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN) & 0x01;
- g_assert_cmpuint(actual, ==, 0x00);
+ g_assert_cmphex(actual, ==, 0x00);
/*
* Check short-circuit - generates an guest_error which must be checked
@@ -410,7 +410,7 @@
/* Set pin high */
qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", i, 1);
uint32_t actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN);
- g_assert_cmpuint(actual, ==, 1 << i);
+ g_assert_cmphex(actual, ==, 1 << i);
/* Check that DETECT is high */
g_assert_true(qtest_get_irq(qts, 0));
@@ -418,7 +418,7 @@
/* Set pin low, check that DETECT goes low. */
qtest_set_irq_in(qts, "/machine/nrf51", "unnamed-gpio-in", i, 0);
actual = qtest_readl(qts, NRF51_GPIO_BASE + NRF51_GPIO_REG_IN);
- g_assert_cmpuint(actual, ==, 0x0);
+ g_assert_cmphex(actual, ==, 0x0);
g_assert_false(qtest_get_irq(qts, 0));
}
diff --git a/tests/qtest/sse-timer-test.c b/tests/qtest/sse-timer-test.c
index a65d754..fd5635d 100644
--- a/tests/qtest/sse-timer-test.c
+++ b/tests/qtest/sse-timer-test.c
@@ -181,12 +181,12 @@
writel(TIMER_BASE + CNTP_AIVAL_CTL, 0);
clock_step_ticks(0x42ULL << 32);
g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_LO), ==, 4400);
- g_assert_cmpuint(readl(TIMER_BASE + CNTPCT_HI), ==, 0x42);
+ g_assert_cmphex(readl(TIMER_BASE + CNTPCT_HI), ==, 0x42);
/* Turn on the autoinc again to check AIVAL_HI */
writel(TIMER_BASE + CNTP_AIVAL_CTL, 1);
g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_LO), ==, 4600);
- g_assert_cmpuint(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0x42);
+ g_assert_cmphex(readl(TIMER_BASE + CNTP_AIVAL_HI), ==, 0x42);
}
static void test_timer_scale_change(void)
diff --git a/tests/qtest/stm32l4x5_exti-test.c b/tests/qtest/stm32l4x5_exti-test.c
index 81830be..7092860 100644
--- a/tests/qtest/stm32l4x5_exti-test.c
+++ b/tests/qtest/stm32l4x5_exti-test.c
@@ -70,44 +70,44 @@
/* Test that non-reserved bits in xMR and xTSR can be set and cleared */
exti_writel(EXTI_IMR1, 0xFFFFFFFF);
- g_assert_cmpuint(exti_readl(EXTI_IMR1), ==, 0xFFFFFFFF);
+ g_assert_cmphex(exti_readl(EXTI_IMR1), ==, 0xFFFFFFFF);
exti_writel(EXTI_IMR1, 0x00000000);
- g_assert_cmpuint(exti_readl(EXTI_IMR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_IMR1), ==, 0x00000000);
exti_writel(EXTI_EMR1, 0xFFFFFFFF);
- g_assert_cmpuint(exti_readl(EXTI_EMR1), ==, 0xFFFFFFFF);
+ g_assert_cmphex(exti_readl(EXTI_EMR1), ==, 0xFFFFFFFF);
exti_writel(EXTI_EMR1, 0x00000000);
- g_assert_cmpuint(exti_readl(EXTI_EMR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_EMR1), ==, 0x00000000);
exti_writel(EXTI_RTSR1, 0xFFFFFFFF);
- g_assert_cmpuint(exti_readl(EXTI_RTSR1), ==, 0x007DFFFF);
+ g_assert_cmphex(exti_readl(EXTI_RTSR1), ==, 0x007DFFFF);
exti_writel(EXTI_RTSR1, 0x00000000);
- g_assert_cmpuint(exti_readl(EXTI_RTSR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_RTSR1), ==, 0x00000000);
exti_writel(EXTI_FTSR1, 0xFFFFFFFF);
- g_assert_cmpuint(exti_readl(EXTI_FTSR1), ==, 0x007DFFFF);
+ g_assert_cmphex(exti_readl(EXTI_FTSR1), ==, 0x007DFFFF);
exti_writel(EXTI_FTSR1, 0x00000000);
- g_assert_cmpuint(exti_readl(EXTI_FTSR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_FTSR1), ==, 0x00000000);
exti_writel(EXTI_IMR2, 0xFFFFFFFF);
- g_assert_cmpuint(exti_readl(EXTI_IMR2), ==, 0x000000FF);
+ g_assert_cmphex(exti_readl(EXTI_IMR2), ==, 0x000000FF);
exti_writel(EXTI_IMR2, 0x00000000);
- g_assert_cmpuint(exti_readl(EXTI_IMR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_IMR2), ==, 0x00000000);
exti_writel(EXTI_EMR2, 0xFFFFFFFF);
- g_assert_cmpuint(exti_readl(EXTI_EMR2), ==, 0x000000FF);
+ g_assert_cmphex(exti_readl(EXTI_EMR2), ==, 0x000000FF);
exti_writel(EXTI_EMR2, 0x00000000);
- g_assert_cmpuint(exti_readl(EXTI_EMR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_EMR2), ==, 0x00000000);
exti_writel(EXTI_RTSR2, 0xFFFFFFFF);
- g_assert_cmpuint(exti_readl(EXTI_RTSR2), ==, 0x00000078);
+ g_assert_cmphex(exti_readl(EXTI_RTSR2), ==, 0x00000078);
exti_writel(EXTI_RTSR2, 0x00000000);
- g_assert_cmpuint(exti_readl(EXTI_RTSR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_RTSR2), ==, 0x00000000);
exti_writel(EXTI_FTSR2, 0xFFFFFFFF);
- g_assert_cmpuint(exti_readl(EXTI_FTSR2), ==, 0x00000078);
+ g_assert_cmphex(exti_readl(EXTI_FTSR2), ==, 0x00000078);
exti_writel(EXTI_FTSR2, 0x00000000);
- g_assert_cmpuint(exti_readl(EXTI_FTSR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_FTSR2), ==, 0x00000000);
}
static void test_direct_lines_write(void)
@@ -115,28 +115,28 @@
/* Test that direct lines reserved bits are not written to */
exti_writel(EXTI_RTSR1, 0xFF820000);
- g_assert_cmpuint(exti_readl(EXTI_RTSR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_RTSR1), ==, 0x00000000);
exti_writel(EXTI_FTSR1, 0xFF820000);
- g_assert_cmpuint(exti_readl(EXTI_FTSR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_FTSR1), ==, 0x00000000);
exti_writel(EXTI_SWIER1, 0xFF820000);
- g_assert_cmpuint(exti_readl(EXTI_SWIER1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_SWIER1), ==, 0x00000000);
exti_writel(EXTI_PR1, 0xFF820000);
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
exti_writel(EXTI_RTSR2, 0x00000087);
- g_assert_cmpuint(exti_readl(EXTI_RTSR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_RTSR2), ==, 0x00000000);
exti_writel(EXTI_FTSR2, 0x00000087);
- g_assert_cmpuint(exti_readl(EXTI_FTSR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_FTSR2), ==, 0x00000000);
exti_writel(EXTI_SWIER2, 0x00000087);
- g_assert_cmpuint(exti_readl(EXTI_SWIER2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_SWIER2), ==, 0x00000000);
exti_writel(EXTI_PR2, 0x00000087);
- g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
}
static void test_reserved_bits_write(void)
@@ -144,22 +144,22 @@
/* Test that reserved bits stay are not written to */
exti_writel(EXTI_IMR2, 0xFFFFFF00);
- g_assert_cmpuint(exti_readl(EXTI_IMR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_IMR2), ==, 0x00000000);
exti_writel(EXTI_EMR2, 0xFFFFFF00);
- g_assert_cmpuint(exti_readl(EXTI_EMR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_EMR2), ==, 0x00000000);
exti_writel(EXTI_RTSR2, 0xFFFFFF00);
- g_assert_cmpuint(exti_readl(EXTI_RTSR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_RTSR2), ==, 0x00000000);
exti_writel(EXTI_FTSR2, 0xFFFFFF00);
- g_assert_cmpuint(exti_readl(EXTI_FTSR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_FTSR2), ==, 0x00000000);
exti_writel(EXTI_SWIER2, 0xFFFFFF00);
- g_assert_cmpuint(exti_readl(EXTI_SWIER2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_SWIER2), ==, 0x00000000);
exti_writel(EXTI_PR2, 0xFFFFFF00);
- g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
}
static void test_software_interrupt(void)
@@ -180,7 +180,7 @@
enable_nvic_irq(EXTI0_IRQ);
/* Check that there are no interrupts already pending in PR */
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
/* Check that this specific interrupt isn't pending in NVIC */
g_assert_false(check_nvic_pending(EXTI0_IRQ));
@@ -191,9 +191,9 @@
exti_writel(EXTI_SWIER1, 0x00000001);
/* Check that the write in SWIER was effective */
- g_assert_cmpuint(exti_readl(EXTI_SWIER1), ==, 0x00000001);
+ g_assert_cmphex(exti_readl(EXTI_SWIER1), ==, 0x00000001);
/* Check that the corresponding pending bit in PR is set */
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000001);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000001);
/* Check that the corresponding interrupt is pending in the NVIC */
g_assert_true(check_nvic_pending(EXTI0_IRQ));
@@ -201,9 +201,9 @@
exti_writel(EXTI_PR1, 0x00000001);
/* Check that the write in PR was effective */
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
/* Check that the corresponding bit in SWIER was cleared */
- g_assert_cmpuint(exti_readl(EXTI_SWIER1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_SWIER1), ==, 0x00000000);
/* Check that the interrupt is still pending in the NVIC */
g_assert_true(check_nvic_pending(EXTI0_IRQ));
@@ -214,7 +214,7 @@
enable_nvic_irq(EXTI35_IRQ);
/* Check that there are no interrupts already pending */
- g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
g_assert_false(check_nvic_pending(EXTI35_IRQ));
/* Enable interrupt line EXTI0 */
@@ -224,9 +224,9 @@
exti_writel(EXTI_SWIER2, 0x00000008);
/* Check that the write in SWIER was effective */
- g_assert_cmpuint(exti_readl(EXTI_SWIER2), ==, 0x00000008);
+ g_assert_cmphex(exti_readl(EXTI_SWIER2), ==, 0x00000008);
/* Check that the corresponding pending bit in PR is set */
- g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000008);
+ g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000008);
/* Check that the corresponding interrupt is pending in the NVIC */
g_assert_true(check_nvic_pending(EXTI35_IRQ));
@@ -234,9 +234,9 @@
exti_writel(EXTI_PR2, 0x00000008);
/* Check that the write in PR was effective */
- g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
/* Check that the corresponding bit in SWIER was cleared */
- g_assert_cmpuint(exti_readl(EXTI_SWIER2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_SWIER2), ==, 0x00000000);
/* Check that the interrupt is still pending in the NVIC */
g_assert_true(check_nvic_pending(EXTI35_IRQ));
@@ -259,16 +259,16 @@
/* Test that an irq is raised on rising edge only */
exti_set_irq(0, 0);
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
g_assert_false(check_nvic_pending(EXTI0_IRQ));
exti_set_irq(0, 1);
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000001);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000001);
g_assert_true(check_nvic_pending(EXTI0_IRQ));
/* Clean the test */
exti_writel(EXTI_PR1, 0x00000001);
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
unpend_nvic_irq(EXTI0_IRQ);
g_assert_false(check_nvic_pending(EXTI0_IRQ));
@@ -280,16 +280,16 @@
/* Test that an irq is raised on falling edge only */
exti_set_irq(0, 1);
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
g_assert_false(check_nvic_pending(EXTI0_IRQ));
exti_set_irq(0, 0);
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000001);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000001);
g_assert_true(check_nvic_pending(EXTI0_IRQ));
/* Clean the test */
exti_writel(EXTI_PR1, 0x00000001);
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
unpend_nvic_irq(EXTI0_IRQ);
g_assert_false(check_nvic_pending(EXTI0_IRQ));
@@ -300,23 +300,23 @@
/* Test that an irq is raised on rising edge */
exti_set_irq(0, 1);
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000001);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000001);
g_assert_true(check_nvic_pending(EXTI0_IRQ));
/* Clean the test */
exti_writel(EXTI_PR1, 0x00000001);
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
unpend_nvic_irq(EXTI0_IRQ);
g_assert_false(check_nvic_pending(EXTI0_IRQ));
/* Test that an irq is raised on falling edge */
exti_set_irq(0, 0);
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000001);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000001);
g_assert_true(check_nvic_pending(EXTI0_IRQ));
/* Clean the test */
exti_writel(EXTI_PR1, 0x00000001);
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
unpend_nvic_irq(EXTI0_IRQ);
g_assert_false(check_nvic_pending(EXTI0_IRQ));
@@ -327,11 +327,11 @@
/* Test that no irq is raised */
exti_set_irq(0, 1);
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
g_assert_false(check_nvic_pending(EXTI0_IRQ));
exti_set_irq(0, 0);
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
g_assert_false(check_nvic_pending(EXTI0_IRQ));
}
@@ -350,7 +350,7 @@
enable_nvic_irq(EXTI0_IRQ);
/* Check that there are no interrupts already pending in PR */
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
/* Check that this specific interrupt isn't pending in NVIC */
g_assert_false(check_nvic_pending(EXTI0_IRQ));
@@ -361,9 +361,9 @@
exti_writel(EXTI_SWIER1, 0x00000001);
/* Check that the write in SWIER was effective */
- g_assert_cmpuint(exti_readl(EXTI_SWIER1), ==, 0x00000001);
+ g_assert_cmphex(exti_readl(EXTI_SWIER1), ==, 0x00000001);
/* Check that the pending bit in PR wasn't set */
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
/* Check that the interrupt isn't pending in NVIC */
g_assert_false(check_nvic_pending(EXTI0_IRQ));
@@ -371,7 +371,7 @@
exti_writel(EXTI_IMR1, 0x00000001);
/* Check that the pending bit in PR wasn't set */
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
/* Check that the interrupt isn't pending in NVIC */
g_assert_false(check_nvic_pending(EXTI0_IRQ));
@@ -382,7 +382,7 @@
enable_nvic_irq(EXTI35_IRQ);
/* Check that there are no interrupts already pending in PR */
- g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
/* Check that this specific interrupt isn't pending in NVIC */
g_assert_false(check_nvic_pending(EXTI35_IRQ));
@@ -393,9 +393,9 @@
exti_writel(EXTI_SWIER2, 0x00000008);
/* Check that the write in SWIER was effective */
- g_assert_cmpuint(exti_readl(EXTI_SWIER2), ==, 0x00000008);
+ g_assert_cmphex(exti_readl(EXTI_SWIER2), ==, 0x00000008);
/* Check that the pending bit in PR wasn't set */
- g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
/* Check that the interrupt isn't pending in NVIC */
g_assert_false(check_nvic_pending(EXTI35_IRQ));
@@ -403,7 +403,7 @@
exti_writel(EXTI_IMR2, 0x00000008);
/* Check that the pending bit in PR wasn't set */
- g_assert_cmpuint(exti_readl(EXTI_PR2), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR2), ==, 0x00000000);
/* Check that the interrupt isn't pending in NVIC */
g_assert_false(check_nvic_pending(EXTI35_IRQ));
}
@@ -423,7 +423,7 @@
enable_nvic_irq(EXTI1_IRQ);
/* Check that there are no interrupts already pending in PR */
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
/* Check that this specific interrupt isn't pending in NVIC */
g_assert_false(check_nvic_pending(EXTI1_IRQ));
@@ -437,7 +437,7 @@
exti_set_irq(1, 1);
/* Check that the pending bit in PR wasn't set */
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
/* Check that the interrupt isn't pending in NVIC */
g_assert_false(check_nvic_pending(EXTI1_IRQ));
@@ -445,7 +445,7 @@
exti_writel(EXTI_IMR1, 0x00000002);
/* Check that the pending bit in PR wasn't set */
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
/* Check that the interrupt isn't pending in NVIC */
g_assert_false(check_nvic_pending(EXTI1_IRQ));
}
@@ -469,7 +469,7 @@
enable_nvic_irq(EXTI1_IRQ);
/* Check that there are no interrupts already pending in PR */
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
/* Check that this specific interrupt isn't pending in NVIC */
g_assert_false(check_nvic_pending(EXTI1_IRQ));
@@ -483,7 +483,7 @@
exti_set_irq(1, 1);
/* Check that the pending bit in PR was set */
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000002);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000002);
/* Check that the interrupt is pending in NVIC */
g_assert_true(check_nvic_pending(EXTI1_IRQ));
@@ -491,7 +491,7 @@
exti_writel(EXTI_PR1, 0x00000002);
/* Check that the write in PR was effective */
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
/* Check that the interrupt is still pending in the NVIC */
g_assert_true(check_nvic_pending(EXTI1_IRQ));
@@ -509,7 +509,7 @@
*/
enable_nvic_irq(EXTI5_9_IRQ);
/* Check that there are no interrupts already pending in PR */
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
/* Check that this specific interrupt isn't pending in NVIC */
g_assert_false(check_nvic_pending(EXTI5_9_IRQ));
@@ -522,11 +522,11 @@
/* Raise GPIO line i, check that the interrupt is pending */
for (unsigned i = 5; i < 10; i++) {
exti_set_irq(i, 1);
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 1 << i);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 1 << i);
g_assert_true(check_nvic_pending(EXTI5_9_IRQ));
exti_writel(EXTI_PR1, 1 << i);
- g_assert_cmpuint(exti_readl(EXTI_PR1), ==, 0x00000000);
+ g_assert_cmphex(exti_readl(EXTI_PR1), ==, 0x00000000);
g_assert_true(check_nvic_pending(EXTI5_9_IRQ));
unpend_nvic_irq(EXTI5_9_IRQ);
diff --git a/tests/qtest/stm32l4x5_syscfg-test.c b/tests/qtest/stm32l4x5_syscfg-test.c
index ed48017..59bac82 100644
--- a/tests/qtest/stm32l4x5_syscfg-test.c
+++ b/tests/qtest/stm32l4x5_syscfg-test.c
@@ -54,27 +54,27 @@
/*
* Test that registers are initialized at the correct values
*/
- g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x7C000001);
+ g_assert_cmphex(syscfg_readl(SYSCFG_CFGR1), ==, 0x7C000001);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR1), ==, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR2), ==, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR3), ==, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR4), ==, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_SCSR), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_SCSR), ==, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR2), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_CFGR2), ==, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_SWPR), ==, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_SKR), ==, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR2), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_SWPR2), ==, 0x00000000);
}
static void test_reserved_bits(void)
@@ -87,25 +87,25 @@
* register is still at reset value
*/
syscfg_writel(SYSCFG_MEMRMP, 0xFFFFFEF8);
- g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000000);
syscfg_writel(SYSCFG_CFGR1, 0x7F00FEFF);
- g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x7C000001);
+ g_assert_cmphex(syscfg_readl(SYSCFG_CFGR1), ==, 0x7C000001);
syscfg_writel(SYSCFG_EXTICR1, 0xFFFF0000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR1), ==, 0x00000000);
syscfg_writel(SYSCFG_EXTICR2, 0xFFFF0000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR2), ==, 0x00000000);
syscfg_writel(SYSCFG_EXTICR3, 0xFFFF0000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR3), ==, 0x00000000);
syscfg_writel(SYSCFG_EXTICR4, 0xFFFF0000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR4), ==, 0x00000000);
syscfg_writel(SYSCFG_SKR, 0xFFFFFF00);
- g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_SKR), ==, 0x00000000);
}
static void test_set_and_clear(void)
@@ -114,40 +114,40 @@
* Test that regular bits can be set and cleared
*/
syscfg_writel(SYSCFG_MEMRMP, 0x00000107);
- g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000107);
+ g_assert_cmphex(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000107);
syscfg_writel(SYSCFG_MEMRMP, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_MEMRMP), ==, 0x00000000);
/* cfgr1 bit 0 is clear only so we keep it set */
syscfg_writel(SYSCFG_CFGR1, 0xFCFF0101);
- g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0xFCFF0101);
+ g_assert_cmphex(syscfg_readl(SYSCFG_CFGR1), ==, 0xFCFF0101);
syscfg_writel(SYSCFG_CFGR1, 0x00000001);
- g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x00000001);
+ g_assert_cmphex(syscfg_readl(SYSCFG_CFGR1), ==, 0x00000001);
syscfg_writel(SYSCFG_EXTICR1, 0x0000FFFF);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x0000FFFF);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR1), ==, 0x0000FFFF);
syscfg_writel(SYSCFG_EXTICR1, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR1), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR1), ==, 0x00000000);
syscfg_writel(SYSCFG_EXTICR2, 0x0000FFFF);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x0000FFFF);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR2), ==, 0x0000FFFF);
syscfg_writel(SYSCFG_EXTICR2, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR2), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR2), ==, 0x00000000);
syscfg_writel(SYSCFG_EXTICR3, 0x0000FFFF);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x0000FFFF);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR3), ==, 0x0000FFFF);
syscfg_writel(SYSCFG_EXTICR3, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR3), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR3), ==, 0x00000000);
syscfg_writel(SYSCFG_EXTICR4, 0x0000FFFF);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x0000FFFF);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR4), ==, 0x0000FFFF);
syscfg_writel(SYSCFG_EXTICR4, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_EXTICR4), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_EXTICR4), ==, 0x00000000);
syscfg_writel(SYSCFG_SKR, 0x000000FF);
- g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x000000FF);
+ g_assert_cmphex(syscfg_readl(SYSCFG_SKR), ==, 0x000000FF);
syscfg_writel(SYSCFG_SKR, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_SKR), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_SKR), ==, 0x00000000);
}
static void test_clear_by_writing_1(void)
@@ -156,7 +156,7 @@
* Test that writing '1' doesn't set the bit
*/
syscfg_writel(SYSCFG_CFGR2, 0x00000100);
- g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR2), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_CFGR2), ==, 0x00000000);
}
static void test_set_only_bits(void)
@@ -166,15 +166,15 @@
*/
syscfg_writel(SYSCFG_CFGR2, 0x0000000F);
syscfg_writel(SYSCFG_CFGR2, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR2), ==, 0x0000000F);
+ g_assert_cmphex(syscfg_readl(SYSCFG_CFGR2), ==, 0x0000000F);
syscfg_writel(SYSCFG_SWPR, 0xFFFFFFFF);
syscfg_writel(SYSCFG_SWPR, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR), ==, 0xFFFFFFFF);
+ g_assert_cmphex(syscfg_readl(SYSCFG_SWPR), ==, 0xFFFFFFFF);
syscfg_writel(SYSCFG_SWPR2, 0xFFFFFFFF);
syscfg_writel(SYSCFG_SWPR2, 0x00000000);
- g_assert_cmpuint(syscfg_readl(SYSCFG_SWPR2), ==, 0xFFFFFFFF);
+ g_assert_cmphex(syscfg_readl(SYSCFG_SWPR2), ==, 0xFFFFFFFF);
system_reset();
}
@@ -186,7 +186,7 @@
*/
syscfg_writel(SYSCFG_CFGR1, 0x00000000);
syscfg_writel(SYSCFG_CFGR1, 0x00000001);
- g_assert_cmpuint(syscfg_readl(SYSCFG_CFGR1), ==, 0x00000000);
+ g_assert_cmphex(syscfg_readl(SYSCFG_CFGR1), ==, 0x00000000);
system_reset();
}
diff --git a/tests/qtest/stm32l4x5_usart-test.c b/tests/qtest/stm32l4x5_usart-test.c
new file mode 100644
index 0000000..8902518
--- /dev/null
+++ b/tests/qtest/stm32l4x5_usart-test.c
@@ -0,0 +1,315 @@
+/*
+ * QTest testcase for STML4X5_USART
+ *
+ * Copyright (c) 2023 Arnaud Minier <arnaud.minier@telecom-paris.fr>
+ * Copyright (c) 2023 Inès Varhol <ines.varhol@telecom-paris.fr>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "libqtest.h"
+#include "hw/misc/stm32l4x5_rcc_internals.h"
+#include "hw/registerfields.h"
+
+#define RCC_BASE_ADDR 0x40021000
+/* Use USART 1 ADDR, assume the others work the same */
+#define USART1_BASE_ADDR 0x40013800
+
+/* See stm32l4x5_usart for definitions */
+REG32(CR1, 0x00)
+ FIELD(CR1, M1, 28, 1)
+ FIELD(CR1, OVER8, 15, 1)
+ FIELD(CR1, M0, 12, 1)
+ FIELD(CR1, PCE, 10, 1)
+ FIELD(CR1, TXEIE, 7, 1)
+ FIELD(CR1, RXNEIE, 5, 1)
+ FIELD(CR1, TE, 3, 1)
+ FIELD(CR1, RE, 2, 1)
+ FIELD(CR1, UE, 0, 1)
+REG32(CR2, 0x04)
+REG32(CR3, 0x08)
+ FIELD(CR3, OVRDIS, 12, 1)
+REG32(BRR, 0x0C)
+REG32(GTPR, 0x10)
+REG32(RTOR, 0x14)
+REG32(RQR, 0x18)
+REG32(ISR, 0x1C)
+ FIELD(ISR, TXE, 7, 1)
+ FIELD(ISR, RXNE, 5, 1)
+ FIELD(ISR, ORE, 3, 1)
+REG32(ICR, 0x20)
+REG32(RDR, 0x24)
+REG32(TDR, 0x28)
+
+#define NVIC_ISPR1 0XE000E204
+#define NVIC_ICPR1 0xE000E284
+#define USART1_IRQ 37
+
+static bool check_nvic_pending(QTestState *qts, unsigned int n)
+{
+ /* No USART interrupts are less than 32 */
+ assert(n > 32);
+ n -= 32;
+ return qtest_readl(qts, NVIC_ISPR1) & (1 << n);
+}
+
+static bool clear_nvic_pending(QTestState *qts, unsigned int n)
+{
+ /* No USART interrupts are less than 32 */
+ assert(n > 32);
+ n -= 32;
+ qtest_writel(qts, NVIC_ICPR1, (1 << n));
+ return true;
+}
+
+/*
+ * Wait indefinitely for the flag to be updated.
+ * If this is run on a slow CI runner,
+ * the meson harness will timeout after 10 minutes for us.
+ */
+static bool usart_wait_for_flag(QTestState *qts, uint32_t event_addr,
+ uint32_t flag)
+{
+ while (true) {
+ if ((qtest_readl(qts, event_addr) & flag)) {
+ return true;
+ }
+ g_usleep(1000);
+ }
+
+ return false;
+}
+
+static void usart_receive_string(QTestState *qts, int sock_fd, const char *in,
+ char *out)
+{
+ int i, in_len = strlen(in);
+
+ g_assert_true(send(sock_fd, in, in_len, 0) == in_len);
+ for (i = 0; i < in_len; i++) {
+ g_assert_true(usart_wait_for_flag(qts,
+ USART1_BASE_ADDR + A_ISR, R_ISR_RXNE_MASK));
+ out[i] = qtest_readl(qts, USART1_BASE_ADDR + A_RDR);
+ }
+ out[i] = '\0';
+}
+
+static void usart_send_string(QTestState *qts, const char *in)
+{
+ int i, in_len = strlen(in);
+
+ for (i = 0; i < in_len; i++) {
+ qtest_writel(qts, USART1_BASE_ADDR + A_TDR, in[i]);
+ g_assert_true(usart_wait_for_flag(qts,
+ USART1_BASE_ADDR + A_ISR, R_ISR_TXE_MASK));
+ }
+}
+
+/* Init the RCC clocks to run at 80 MHz */
+static void init_clocks(QTestState *qts)
+{
+ uint32_t value;
+
+ /* MSIRANGE can be set only when MSI is OFF or READY */
+ qtest_writel(qts, (RCC_BASE_ADDR + A_CR), R_CR_MSION_MASK);
+
+ /* Clocking from MSI, in case MSI was not the default source */
+ qtest_writel(qts, (RCC_BASE_ADDR + A_CFGR), 0);
+
+ /*
+ * Update PLL and set MSI as the source clock.
+ * PLLM = 1 --> 000
+ * PLLN = 40 --> 40
+ * PPLLR = 2 --> 00
+ * PLLDIV = unused, PLLP = unused (SAI3), PLLQ = unused (48M1)
+ * SRC = MSI --> 01
+ */
+ qtest_writel(qts, (RCC_BASE_ADDR + A_PLLCFGR), R_PLLCFGR_PLLREN_MASK |
+ (40 << R_PLLCFGR_PLLN_SHIFT) |
+ (0b01 << R_PLLCFGR_PLLSRC_SHIFT));
+
+ /* PLL activation */
+
+ value = qtest_readl(qts, (RCC_BASE_ADDR + A_CR));
+ qtest_writel(qts, (RCC_BASE_ADDR + A_CR), value | R_CR_PLLON_MASK);
+
+ /* RCC_CFGR is OK by defaut */
+ qtest_writel(qts, (RCC_BASE_ADDR + A_CFGR), 0);
+
+ /* CCIPR : no periph clock by default */
+ qtest_writel(qts, (RCC_BASE_ADDR + A_CCIPR), 0);
+
+ /* Switches on the PLL clock source */
+ value = qtest_readl(qts, (RCC_BASE_ADDR + A_CFGR));
+ qtest_writel(qts, (RCC_BASE_ADDR + A_CFGR), (value & ~R_CFGR_SW_MASK) |
+ (0b11 << R_CFGR_SW_SHIFT));
+
+ /* Enable SYSCFG clock enabled */
+ qtest_writel(qts, (RCC_BASE_ADDR + A_APB2ENR), R_APB2ENR_SYSCFGEN_MASK);
+
+ /* Enable the IO port B clock (See p.252) */
+ qtest_writel(qts, (RCC_BASE_ADDR + A_AHB2ENR), R_AHB2ENR_GPIOBEN_MASK);
+
+ /* Enable the clock for USART1 (cf p.259) */
+ /* We rewrite SYSCFGEN to not disable it */
+ qtest_writel(qts, (RCC_BASE_ADDR + A_APB2ENR),
+ R_APB2ENR_SYSCFGEN_MASK | R_APB2ENR_USART1EN_MASK);
+
+ /* TODO: Enable usart via gpio */
+
+ /* Set PCLK as the clock for USART1(cf p.272) i.e. reset both bits */
+ qtest_writel(qts, (RCC_BASE_ADDR + A_CCIPR), 0);
+
+ /* Reset USART1 (see p.249) */
+ qtest_writel(qts, (RCC_BASE_ADDR + A_APB2RSTR), 1 << 14);
+ qtest_writel(qts, (RCC_BASE_ADDR + A_APB2RSTR), 0);
+}
+
+static void init_uart(QTestState *qts)
+{
+ uint32_t cr1;
+
+ init_clocks(qts);
+
+ /*
+ * For 115200 bauds, see p.1349.
+ * The clock has a frequency of 80Mhz,
+ * for 115200, we have to put a divider of 695 = 0x2B7.
+ */
+ qtest_writel(qts, (USART1_BASE_ADDR + A_BRR), 0x2B7);
+
+ /*
+ * Set the oversampling by 16,
+ * disable the parity control and
+ * set the word length to 8. (cf p.1377)
+ */
+ cr1 = qtest_readl(qts, (USART1_BASE_ADDR + A_CR1));
+ cr1 &= ~(R_CR1_M1_MASK | R_CR1_M0_MASK | R_CR1_OVER8_MASK | R_CR1_PCE_MASK);
+ qtest_writel(qts, (USART1_BASE_ADDR + A_CR1), cr1);
+
+ /* Enable the transmitter, the receiver and the USART. */
+ qtest_writel(qts, (USART1_BASE_ADDR + A_CR1),
+ R_CR1_UE_MASK | R_CR1_RE_MASK | R_CR1_TE_MASK);
+}
+
+static void test_write_read(void)
+{
+ QTestState *qts = qtest_init("-M b-l475e-iot01a");
+
+ /* Test that we can write and retrieve a value from the device */
+ qtest_writel(qts, USART1_BASE_ADDR + A_TDR, 0xFFFFFFFF);
+ const uint32_t tdr = qtest_readl(qts, USART1_BASE_ADDR + A_TDR);
+ g_assert_cmpuint(tdr, ==, 0x000001FF);
+}
+
+static void test_receive_char(void)
+{
+ int sock_fd;
+ uint32_t cr1;
+ QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
+
+ init_uart(qts);
+
+ /* Try without initializing IRQ */
+ g_assert_true(send(sock_fd, "a", 1, 0) == 1);
+ usart_wait_for_flag(qts, USART1_BASE_ADDR + A_ISR, R_ISR_RXNE_MASK);
+ g_assert_cmphex(qtest_readl(qts, USART1_BASE_ADDR + A_RDR), ==, 'a');
+ g_assert_false(check_nvic_pending(qts, USART1_IRQ));
+
+ /* Now with the IRQ */
+ cr1 = qtest_readl(qts, (USART1_BASE_ADDR + A_CR1));
+ cr1 |= R_CR1_RXNEIE_MASK;
+ qtest_writel(qts, USART1_BASE_ADDR + A_CR1, cr1);
+ g_assert_true(send(sock_fd, "b", 1, 0) == 1);
+ usart_wait_for_flag(qts, USART1_BASE_ADDR + A_ISR, R_ISR_RXNE_MASK);
+ g_assert_cmphex(qtest_readl(qts, USART1_BASE_ADDR + A_RDR), ==, 'b');
+ g_assert_true(check_nvic_pending(qts, USART1_IRQ));
+ clear_nvic_pending(qts, USART1_IRQ);
+
+ close(sock_fd);
+
+ qtest_quit(qts);
+}
+
+static void test_send_char(void)
+{
+ int sock_fd;
+ char s[1];
+ uint32_t cr1;
+ QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
+
+ init_uart(qts);
+
+ /* Try without initializing IRQ */
+ qtest_writel(qts, USART1_BASE_ADDR + A_TDR, 'c');
+ g_assert_true(recv(sock_fd, s, 1, 0) == 1);
+ g_assert_cmphex(s[0], ==, 'c');
+ g_assert_false(check_nvic_pending(qts, USART1_IRQ));
+
+ /* Now with the IRQ */
+ cr1 = qtest_readl(qts, (USART1_BASE_ADDR + A_CR1));
+ cr1 |= R_CR1_TXEIE_MASK;
+ qtest_writel(qts, USART1_BASE_ADDR + A_CR1, cr1);
+ qtest_writel(qts, USART1_BASE_ADDR + A_TDR, 'd');
+ g_assert_true(recv(sock_fd, s, 1, 0) == 1);
+ g_assert_cmphex(s[0], ==, 'd');
+ g_assert_true(check_nvic_pending(qts, USART1_IRQ));
+ clear_nvic_pending(qts, USART1_IRQ);
+
+ close(sock_fd);
+
+ qtest_quit(qts);
+}
+
+static void test_receive_str(void)
+{
+ int sock_fd;
+ char s[10];
+ QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
+
+ init_uart(qts);
+
+ usart_receive_string(qts, sock_fd, "hello", s);
+ g_assert_true(memcmp(s, "hello", 5) == 0);
+
+ close(sock_fd);
+
+ qtest_quit(qts);
+}
+
+static void test_send_str(void)
+{
+ int sock_fd;
+ char s[10];
+ QTestState *qts = qtest_init_with_serial("-M b-l475e-iot01a", &sock_fd);
+
+ init_uart(qts);
+
+ usart_send_string(qts, "world");
+ g_assert_true(recv(sock_fd, s, 10, 0) == 5);
+ g_assert_true(memcmp(s, "world", 5) == 0);
+
+ close(sock_fd);
+
+ qtest_quit(qts);
+}
+
+int main(int argc, char **argv)
+{
+ int ret;
+
+ g_test_init(&argc, &argv, NULL);
+ g_test_set_nonfatal_assertions();
+
+ qtest_add_func("stm32l4x5/usart/write_read", test_write_read);
+ qtest_add_func("stm32l4x5/usart/receive_char", test_receive_char);
+ qtest_add_func("stm32l4x5/usart/send_char", test_send_char);
+ qtest_add_func("stm32l4x5/usart/receive_str", test_receive_str);
+ qtest_add_func("stm32l4x5/usart/send_str", test_send_str);
+ ret = g_test_run();
+
+ return ret;
+}
+
diff --git a/tests/unit/test-nested-aio-poll.c b/tests/unit/test-nested-aio-poll.c
index db33742..d8fd92c 100644
--- a/tests/unit/test-nested-aio-poll.c
+++ b/tests/unit/test-nested-aio-poll.c
@@ -30,19 +30,16 @@
static void io_read(EventNotifier *notifier)
{
- fprintf(stderr, "%s %p\n", __func__, notifier);
event_notifier_test_and_clear(notifier);
}
static bool io_poll_true(void *opaque)
{
- fprintf(stderr, "%s %p\n", __func__, opaque);
return true;
}
static bool io_poll_false(void *opaque)
{
- fprintf(stderr, "%s %p\n", __func__, opaque);
return false;
}
@@ -50,8 +47,6 @@
{
TestData *td = container_of(notifier, TestData, poll_notifier);
- fprintf(stderr, "> %s\n", __func__);
-
g_assert(!td->nested);
td->nested = true;
@@ -62,8 +57,6 @@
g_assert(aio_poll(td->ctx, true));
td->nested = false;
-
- fprintf(stderr, "< %s\n", __func__);
}
/* dummy_notifier never triggers */
diff --git a/tests/vm/centos b/tests/vm/centos
index 097a9ca..d25c8f8 100755
--- a/tests/vm/centos
+++ b/tests/vm/centos
@@ -26,8 +26,8 @@
export SRC_ARCHIVE=/dev/vdb;
sudo chmod a+r $SRC_ARCHIVE;
tar -xf $SRC_ARCHIVE;
- make docker-test-block@centos8 {verbose} J={jobs} NETWORK=1;
- make docker-test-quick@centos8 {verbose} J={jobs} NETWORK=1;
+ make docker-test-block@centos9 {verbose} J={jobs} NETWORK=1;
+ make docker-test-quick@centos9 {verbose} J={jobs} NETWORK=1;
"""
def build_image(self, img):
diff --git a/tests/vm/openbsd b/tests/vm/openbsd
index 85c9863..5e646f7 100755
--- a/tests/vm/openbsd
+++ b/tests/vm/openbsd
@@ -22,8 +22,8 @@
name = "openbsd"
arch = "x86_64"
- link = "https://cdn.openbsd.org/pub/OpenBSD/7.4/amd64/install74.iso"
- csum = "a1001736ed9fe2307965b5fcdb426ae11f9b80d26eb21e404a705144a0a224a0"
+ link = "https://cdn.openbsd.org/pub/OpenBSD/7.5/amd64/install75.iso"
+ csum = "034435c6e27405d5a7fafb058162943c194eb793dafdc412c08d49bb56b3892a"
size = "20G"
pkgs = [
# tools
@@ -124,7 +124,7 @@
self.console_wait_send("Allow root ssh login", "yes\n")
self.console_wait_send("timezone", "UTC\n")
self.console_wait_send("root disk", "\n")
- self.console_wait_send("Encrypt the root disk with a passphrase", "no\n")
+ self.console_wait_send("Encrypt the root disk with a (p)assphrase", "no\n")
self.console_wait_send("(W)hole disk", "\n")
self.console_wait_send("(A)uto layout", "c\n")