From 81165ace09e10cf550ebdf2b88241a8b0d405196 Mon Sep 17 00:00:00 2001 From: Auger Eric Date: Fri, 16 Jun 2017 15:17:55 +0200 Subject: [PATCH 4/5] hw/intc/arm_gicv3_kvm: Implement pending table save RH-Author: Auger Eric Message-id: <1497626276-18221-5-git-send-email-eric.auger@redhat.com> Patchwork-id: 75637 O-Subject: [Pegas-1.0 qemu-kvm PATCH v2 4/5] hw/intc/arm_gicv3_kvm: Implement pending table save Bugzilla: 1462061 RH-Acked-by: Laurent Vivier RH-Acked-by: Peter Xu RH-Acked-by: Miroslav Rezanina This patch adds the flush of the LPI pending bits into the redistributor pending tables. This happens on VM stop. There is no explicit restore as the tables are implicitly sync'ed on ITS table restore and on LPI enable at redistributor level. Signed-off-by: Eric Auger Message-id: 1497023553-18411-4-git-send-email-eric.auger@redhat.com Reviewed-by: Peter Maydell Signed-off-by: Peter Maydell (cherry picked from commit d5aa0c229ab5d46c1a4ff497553671cd46486749) Signed-off-by: Eric Auger Signed-off-by: Miroslav Rezanina --- hw/intc/arm_gicv3_kvm.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/hw/intc/arm_gicv3_kvm.c b/hw/intc/arm_gicv3_kvm.c index 824475f..2df4870 100644 --- a/hw/intc/arm_gicv3_kvm.c +++ b/hw/intc/arm_gicv3_kvm.c @@ -25,6 +25,7 @@ #include "hw/sysbus.h" #include "qemu/error-report.h" #include "sysemu/kvm.h" +#include "sysemu/sysemu.h" #include "kvm_arm.h" #include "gicv3_internal.h" #include "vgic_common.h" @@ -680,6 +681,35 @@ static const ARMCPRegInfo gicv3_cpuif_reginfo[] = { REGINFO_SENTINEL }; +/** + * vm_change_state_handler - VM change state callback aiming at flushing + * RDIST pending tables into guest RAM + * + * The tables get flushed to guest RAM whenever the VM gets stopped. + */ +static void vm_change_state_handler(void *opaque, int running, + RunState state) +{ + GICv3State *s = (GICv3State *)opaque; + Error *err = NULL; + int ret; + + if (running) { + return; + } + + ret = kvm_device_access(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, + KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES, + NULL, true, &err); + if (err) { + error_report_err(err); + } + if (ret < 0 && ret != -EFAULT) { + abort(); + } +} + + static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) { GICv3State *s = KVM_ARM_GICV3(dev); @@ -751,6 +781,10 @@ static void kvm_arm_gicv3_realize(DeviceState *dev, Error **errp) return; } } + if (kvm_device_check_attr(s->dev_fd, KVM_DEV_ARM_VGIC_GRP_CTRL, + KVM_DEV_ARM_VGIC_SAVE_PENDING_TABLES)) { + qemu_add_vm_change_state_handler(vm_change_state_handler, s); + } } static void kvm_arm_gicv3_class_init(ObjectClass *klass, void *data) -- 1.8.3.1