Commit c9aedf8c authored by Eric Auger's avatar Eric Auger Committed by Peter Maydell
Browse files

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: default avatarEric Auger <eric.auger@redhat.com>
Reviewed-by: default avatarPeter Maydell <peter.maydell@linaro.org>
Message-id: 1511883692-11511-3-git-send-email-eric.auger@redhat.com
Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parent 7e724479
Loading
Loading
Loading
Loading
+42 −0
Original line number Diff line number Diff line
@@ -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)