From: Mohamed Mediouni <mohamed@unpredictable.fr>
To: qemu-devel@nongnu.org
Cc: "Marcel Apfelbaum" <marcel.apfelbaum@gmail.com>,
"Yanan Wang" <wangyanan55@huawei.com>,
"Zhao Liu" <zhao1.liu@intel.com>,
qemu-arm@nongnu.org, "Peter Maydell" <peter.maydell@linaro.org>,
"Roman Bolshakov" <rbolshakov@ddn.com>,
"Alexander Graf" <agraf@csgraf.de>,
"Philippe Mathieu-Daudé" <philmd@linaro.org>,
"Paolo Bonzini" <pbonzini@redhat.com>,
"Eduardo Habkost" <eduardo@habkost.net>,
"Phil Dennis-Jordan" <phil@philjordan.eu>,
"Mohamed Mediouni" <mohamed@unpredictable.fr>
Subject: [PATCH v20 02/15] hw/intc: arm_gicv3_hvf: save/restore Apple GIC state
Date: Mon, 16 Mar 2026 14:06:29 +0100 [thread overview]
Message-ID: <20260316130642.13246-3-mohamed@unpredictable.fr> (raw)
In-Reply-To: <20260316130642.13246-1-mohamed@unpredictable.fr>
On HVF, some of the GIC state is in an opaque Apple-provided structure.
Save/restore that state to be able to save/restore VMs that use the hardware GIC.
Signed-off-by: Mohamed Mediouni <mohamed@unpredictable.fr>
Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
---
hw/intc/arm_gicv3_common.c | 1 +
hw/intc/arm_gicv3_hvf.c | 95 ++++++++++++++++++++++++++++--
hw/intc/arm_gicv3_hvf_stub.c | 25 ++++++++
hw/intc/meson.build | 1 +
include/hw/intc/arm_gicv3_common.h | 3 +
5 files changed, 121 insertions(+), 4 deletions(-)
create mode 100644 hw/intc/arm_gicv3_hvf_stub.c
diff --git a/hw/intc/arm_gicv3_common.c b/hw/intc/arm_gicv3_common.c
index 9200671c7a..9c3fb2f4bf 100644
--- a/hw/intc/arm_gicv3_common.c
+++ b/hw/intc/arm_gicv3_common.c
@@ -305,6 +305,7 @@ static const VMStateDescription vmstate_gicv3 = {
.subsections = (const VMStateDescription * const []) {
&vmstate_gicv3_gicd_no_migration_shift_bug,
&vmstate_gicv3_gicd_nmi,
+ &vmstate_gicv3_hvf,
NULL
}
};
diff --git a/hw/intc/arm_gicv3_hvf.c b/hw/intc/arm_gicv3_hvf.c
index 55171a796b..18e5b3fe68 100644
--- a/hw/intc/arm_gicv3_hvf.c
+++ b/hw/intc/arm_gicv3_hvf.c
@@ -13,6 +13,7 @@
#include "qemu/error-report.h"
#include "qemu/module.h"
#include "system/runstate.h"
+#include "migration/vmstate.h"
#include "system/hvf.h"
#include "system/hvf_int.h"
#include "hvf_arm.h"
@@ -34,8 +35,13 @@ struct HVFARMGICv3Class {
typedef struct HVFARMGICv3Class HVFARMGICv3Class;
-/* This is reusing the GICv3State typedef from ARM_GICV3_ITS_COMMON */
-DECLARE_OBJ_CHECKERS(GICv3State, HVFARMGICv3Class,
+typedef struct HVFGICv3State {
+ GICv3State gicv3_state;
+ uint32_t size;
+ void *state;
+} HVFGICv3State;
+
+DECLARE_OBJ_CHECKERS(HVFGICv3State, HVFARMGICv3Class,
HVF_GICV3, TYPE_HVF_GICV3);
/*
@@ -660,7 +666,7 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = {
static void hvf_gicv3_realize(DeviceState *dev, Error **errp)
{
ERRP_GUARD();
- GICv3State *s = HVF_GICV3(dev);
+ GICv3State *s = (GICv3State *)HVF_GICV3(dev);
HVFARMGICv3Class *kgc = HVF_GICV3_GET_CLASS(s);
int i;
@@ -707,6 +713,87 @@ static void hvf_gicv3_realize(DeviceState *dev, Error **errp)
}
}
+/*
+ * HVF doesn't have a way to save the RDIST pending tables
+ * to guest memory, only to an opaque data structure.
+ */
+static bool gicv3_is_hvf(void *opaque)
+{
+ return hvf_enabled() && hvf_irqchip_in_kernel();
+}
+
+static int hvf_gic_opaque_state_save(void *opaque)
+{
+ HVFGICv3State *gic = opaque;
+ hv_gic_state_t gic_state;
+ hv_return_t err;
+ size_t size;
+
+ gic_state = hv_gic_state_create();
+ if (gic_state == NULL) {
+ error_report("hvf: vgic: failed to create hv_gic_state_create.");
+ return 1;
+ }
+ err = hv_gic_state_get_size(gic_state, &size);
+ gic->size = size;
+ if (err != HV_SUCCESS) {
+ error_report("hvf: vgic: failed to get GIC state size.");
+ os_release(gic_state);
+ return 1;
+ }
+ gic->state = g_malloc(gic->size);
+ err = hv_gic_state_get_data(gic_state, gic->state);
+ if (err != HV_SUCCESS) {
+ error_report("hvf: vgic: failed to get GIC state.");
+ os_release(gic_state);
+ return 1;
+ }
+
+ os_release(gic_state);
+ return 0;
+}
+
+static int hvf_gic_opaque_state_free(void *opaque)
+{
+ HVFGICv3State *gic = opaque;
+ free(gic->state);
+ return 0;
+}
+
+static int hvf_gic_opaque_state_restore(void *opaque, int version_id)
+{
+ HVFGICv3State *gic = opaque;
+ hv_return_t err;
+ if (!gic->size) {
+ return 0;
+ }
+ err = hv_gic_set_state(gic->state, gic->size);
+ if (err != HV_SUCCESS) {
+ error_report("hvf: vgic: failed to restore GIC state.");
+ return 1;
+ }
+ return 0;
+}
+
+const VMStateDescription vmstate_gicv3_hvf = {
+ .name = "arm_gicv3/hvf_gic_state",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = gicv3_is_hvf,
+ .pre_save = hvf_gic_opaque_state_save,
+ .post_save = hvf_gic_opaque_state_free,
+ .post_load = hvf_gic_opaque_state_restore,
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .fields = (const VMStateField[]) {
+ VMSTATE_UINT32(size, HVFGICv3State),
+ VMSTATE_VBUFFER_ALLOC_UINT32(state,
+ HVFGICv3State, 0, 0,
+ size),
+ VMSTATE_END_OF_LIST()
+ },
+};
+
static void hvf_gicv3_class_init(ObjectClass *klass, const void *data)
{
DeviceClass *dc = DEVICE_CLASS(klass);
@@ -726,7 +813,7 @@ static void hvf_gicv3_class_init(ObjectClass *klass, const void *data)
static const TypeInfo hvf_arm_gicv3_info = {
.name = TYPE_HVF_GICV3,
.parent = TYPE_ARM_GICV3_COMMON,
- .instance_size = sizeof(GICv3State),
+ .instance_size = sizeof(HVFGICv3State),
.class_init = hvf_gicv3_class_init,
.class_size = sizeof(HVFARMGICv3Class),
};
diff --git a/hw/intc/arm_gicv3_hvf_stub.c b/hw/intc/arm_gicv3_hvf_stub.c
new file mode 100644
index 0000000000..a587332c7c
--- /dev/null
+++ b/hw/intc/arm_gicv3_hvf_stub.c
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * ARM Generic Interrupt Controller using HVF platform support stub
+ *
+ * Copyright (c) 2026 Mohamed Mediouni
+ *
+ */
+#include "qemu/osdep.h"
+#include "hw/intc/arm_gicv3_common.h"
+#include "migration/vmstate.h"
+#include "qemu/typedefs.h"
+
+static bool needed_never(void *opaque)
+{
+ return false;
+}
+
+const VMStateDescription vmstate_gicv3_hvf = {
+ .name = "arm_gicv3/hvf_gic_state",
+ .version_id = 1,
+ .minimum_version_id = 1,
+ .needed = needed_never,
+ .version_id = 1,
+ .minimum_version_id = 1,
+};
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index b7baf8a0f6..c6de2d9d00 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -43,6 +43,7 @@ arm_common_ss.add(when: 'CONFIG_ARM_GICV3', if_true: files('arm_gicv3_cpuif.c'))
specific_ss.add(when: 'CONFIG_ARM_GIC_KVM', if_true: files('arm_gic_kvm.c'))
specific_ss.add(when: ['CONFIG_WHPX', 'TARGET_AARCH64'], if_true: files('arm_gicv3_whpx.c'))
specific_ss.add(when: ['CONFIG_HVF', 'CONFIG_ARM_GICV3'], if_true: files('arm_gicv3_hvf.c'))
+specific_ss.add(when: ['CONFIG_HVF', 'CONFIG_ARM_GICV3'], if_false: files('arm_gicv3_hvf_stub.c'))
specific_ss.add(when: ['CONFIG_ARM_GIC_KVM', 'TARGET_AARCH64'], if_true: files('arm_gicv3_kvm.c', 'arm_gicv3_its_kvm.c'))
arm_common_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_nvic.c'))
specific_ss.add(when: 'CONFIG_GRLIB', if_true: files('grlib_irqmp.c'))
diff --git a/include/hw/intc/arm_gicv3_common.h b/include/hw/intc/arm_gicv3_common.h
index 9adcab0a0c..03ab3e8f2f 100644
--- a/include/hw/intc/arm_gicv3_common.h
+++ b/include/hw/intc/arm_gicv3_common.h
@@ -339,4 +339,7 @@ void gicv3_init_irqs_and_mmio(GICv3State *s, qemu_irq_handler handler,
*/
const char *gicv3_class_name(void);
+/* HVF vGIC-specific state: stubbed out on a build with HVF disabled */
+extern const VMStateDescription vmstate_gicv3_hvf;
+
#endif
--
2.50.1 (Apple Git-155)
next prev parent reply other threads:[~2026-03-16 13:07 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-16 13:06 [PATCH v20 00/15] HVF: Add support for platform vGIC and nested virtualisation Mohamed Mediouni
2026-03-16 13:06 ` [PATCH v20 01/15] hw/intc: Add hvf vGIC interrupt controller support Mohamed Mediouni
2026-04-24 6:38 ` Manos Pitsidianakis
2026-03-16 13:06 ` Mohamed Mediouni [this message]
2026-04-24 6:56 ` [PATCH v20 02/15] hw/intc: arm_gicv3_hvf: save/restore Apple GIC state Manos Pitsidianakis
2026-04-24 7:29 ` Philippe Mathieu-Daudé
2026-03-16 13:06 ` [PATCH v20 03/15] accel, hw/arm, include/system/hvf: infrastructure changes for HVF vGIC Mohamed Mediouni
2026-04-23 16:10 ` Philippe Mathieu-Daudé
2026-04-23 17:01 ` Mohamed Mediouni
2026-03-16 13:06 ` [PATCH v20 04/15] target/arm: hvf: instantiate GIC early Mohamed Mediouni
2026-03-16 13:06 ` [PATCH v20 05/15] hw/arm, target/arm: nested virtualisation on HVF Mohamed Mediouni
2026-04-24 7:07 ` Manos Pitsidianakis
2026-03-16 13:06 ` [PATCH v20 06/15] hvf: only call hvf_sync_vtimer() when running without the platform vGIC Mohamed Mediouni
2026-03-16 13:06 ` [PATCH v20 07/15] hvf: gate ARM_FEATURE_PMU register emulation when using the Apple vGIC Mohamed Mediouni
2026-04-24 7:15 ` Manos Pitsidianakis
2026-03-16 13:06 ` [PATCH v20 08/15] hvf: arm: allow exposing minimal PMU when running with nested virt on Mohamed Mediouni
2026-04-23 16:03 ` Philippe Mathieu-Daudé
2026-03-16 13:06 ` [PATCH v20 09/15] target/arm: hvf: add asserts for code paths not leveraged when using the vGIC Mohamed Mediouni
2026-03-16 13:06 ` [PATCH v20 10/15] hvf: sync registers used at EL2 Mohamed Mediouni
2026-03-16 13:06 ` [PATCH v20 11/15] target/arm: hvf: pass through CNTHCTL_EL2 and MDCCINT_EL1 Mohamed Mediouni
2026-03-16 13:06 ` [PATCH v20 12/15] hvf: arm: disable SME when nested virt is active Mohamed Mediouni
2026-03-16 13:06 ` [PATCH v20 13/15] hvf: arm: physical timer emulation Mohamed Mediouni
2026-04-23 16:07 ` Philippe Mathieu-Daudé
2026-03-16 13:06 ` [PATCH v20 14/15] hvf: enable nested virtualisation support Mohamed Mediouni
2026-04-24 7:11 ` Manos Pitsidianakis
2026-03-16 13:06 ` [PATCH v20 15/15] hvf: arm: enable vGIC by default for virt-11.1 and later Mohamed Mediouni
2026-04-24 7:13 ` Manos Pitsidianakis
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260316130642.13246-3-mohamed@unpredictable.fr \
--to=mohamed@unpredictable.fr \
--cc=agraf@csgraf.de \
--cc=eduardo@habkost.net \
--cc=marcel.apfelbaum@gmail.com \
--cc=pbonzini@redhat.com \
--cc=peter.maydell@linaro.org \
--cc=phil@philjordan.eu \
--cc=philmd@linaro.org \
--cc=qemu-arm@nongnu.org \
--cc=qemu-devel@nongnu.org \
--cc=rbolshakov@ddn.com \
--cc=wangyanan55@huawei.com \
--cc=zhao1.liu@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.