hw/intc/arm_gicv3_its: Implement a minimalist reset
At the moment the ITS is not properly reset and this causes various bugs on save/restore. We implement a minimalist reset through individual register writes but for kernel versions before v4.15 this fails voiding the vITS cache. We cannot claim we have a comprehensive reset (hence the error message) but that's better than nothing. Signed-off-by: Eric Auger <eric.auger@redhat.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1511883692-11511-3-git-send-email-eric.auger@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
7e7244796b
commit
c9aedf8ca4
@ -28,6 +28,16 @@
|
||||
|
||||
#define TYPE_KVM_ARM_ITS "arm-its-kvm"
|
||||
#define KVM_ARM_ITS(obj) OBJECT_CHECK(GICv3ITSState, (obj), TYPE_KVM_ARM_ITS)
|
||||
#define KVM_ARM_ITS_CLASS(klass) \
|
||||
OBJECT_CLASS_CHECK(KVMARMITSClass, (klass), TYPE_KVM_ARM_ITS)
|
||||
#define KVM_ARM_ITS_GET_CLASS(obj) \
|
||||
OBJECT_GET_CLASS(KVMARMITSClass, (obj), TYPE_KVM_ARM_ITS)
|
||||
|
||||
typedef struct KVMARMITSClass {
|
||||
GICv3ITSCommonClass parent_class;
|
||||
void (*parent_reset)(DeviceState *dev);
|
||||
} KVMARMITSClass;
|
||||
|
||||
|
||||
static int kvm_its_send_msi(GICv3ITSState *s, uint32_t value, uint16_t devid)
|
||||
{
|
||||
@ -186,6 +196,34 @@ static void kvm_arm_its_post_load(GICv3ITSState *s)
|
||||
GITS_CTLR, &s->ctlr, true, &error_abort);
|
||||
}
|
||||
|
||||
static void kvm_arm_its_reset(DeviceState *dev)
|
||||
{
|
||||
GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
|
||||
KVMARMITSClass *c = KVM_ARM_ITS_GET_CLASS(s);
|
||||
int i;
|
||||
|
||||
c->parent_reset(dev);
|
||||
|
||||
error_report("ITS KVM: full reset is not supported by QEMU");
|
||||
|
||||
if (!kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
|
||||
GITS_CTLR)) {
|
||||
return;
|
||||
}
|
||||
|
||||
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
|
||||
GITS_CTLR, &s->ctlr, true, &error_abort);
|
||||
|
||||
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
|
||||
GITS_CBASER, &s->cbaser, true, &error_abort);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_ITS_REGS,
|
||||
GITS_BASER + i * 8, &s->baser[i], true,
|
||||
&error_abort);
|
||||
}
|
||||
}
|
||||
|
||||
static Property kvm_arm_its_props[] = {
|
||||
DEFINE_PROP_LINK("parent-gicv3", GICv3ITSState, gicv3, "kvm-arm-gicv3",
|
||||
GICv3State *),
|
||||
@ -196,12 +234,15 @@ static void kvm_arm_its_class_init(ObjectClass *klass, void *data)
|
||||
{
|
||||
DeviceClass *dc = DEVICE_CLASS(klass);
|
||||
GICv3ITSCommonClass *icc = ARM_GICV3_ITS_COMMON_CLASS(klass);
|
||||
KVMARMITSClass *ic = KVM_ARM_ITS_CLASS(klass);
|
||||
|
||||
dc->realize = kvm_arm_its_realize;
|
||||
dc->props = kvm_arm_its_props;
|
||||
ic->parent_reset = dc->reset;
|
||||
icc->send_msi = kvm_its_send_msi;
|
||||
icc->pre_save = kvm_arm_its_pre_save;
|
||||
icc->post_load = kvm_arm_its_post_load;
|
||||
dc->reset = kvm_arm_its_reset;
|
||||
}
|
||||
|
||||
static const TypeInfo kvm_arm_its_info = {
|
||||
@ -209,6 +250,7 @@ static const TypeInfo kvm_arm_its_info = {
|
||||
.parent = TYPE_ARM_GICV3_ITS_COMMON,
|
||||
.instance_size = sizeof(GICv3ITSState),
|
||||
.class_init = kvm_arm_its_class_init,
|
||||
.class_size = sizeof(KVMARMITSClass),
|
||||
};
|
||||
|
||||
static void kvm_arm_its_register_types(void)
|
||||
|
Loading…
Reference in New Issue
Block a user