mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:46:10 +00:00
hw/intc: arm_gicv3_hvf: save/restore Apple GIC state
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> Reviewed-by: Manos Pitsidianakis <manos.pitsidianakis@linaro.org> Message-id: 20260429190532.26538-3-mohamed@unpredictable.fr Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
committed by
Peter Maydell
parent
e244989abb
commit
48396ad6ce
@@ -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
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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"
|
||||
@@ -37,8 +38,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 parent_obj;
|
||||
uint32_t size;
|
||||
void *state;
|
||||
} HVFGICv3State;
|
||||
|
||||
DECLARE_OBJ_CHECKERS(HVFGICv3State, HVFARMGICv3Class,
|
||||
HVF_GICV3, TYPE_HVF_GICV3);
|
||||
|
||||
/*
|
||||
@@ -668,7 +674,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;
|
||||
|
||||
@@ -715,6 +721,86 @@ 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_malloc0(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 void hvf_gic_opaque_state_free(void *opaque)
|
||||
{
|
||||
HVFGICv3State *gic = opaque;
|
||||
free(gic->state);
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -734,7 +820,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),
|
||||
};
|
||||
|
||||
25
hw/intc/arm_gicv3_hvf_stub.c
Normal file
25
hw/intc/arm_gicv3_hvf_stub.c
Normal file
@@ -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,
|
||||
};
|
||||
@@ -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'))
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user