Commit 5ae47f7aec for qemu.org

commit 5ae47f7aece19c5a6efbf99d000f389278e93c1d
Author: Jinjie Ruan <ruanjinjie@huawei.com>
Date:   Fri Apr 19 14:33:06 2024 +0100

    hw/arm/virt: Enable NMI support in the GIC if the CPU has FEAT_NMI

    If the CPU implements FEAT_NMI, then turn on the NMI support in the
    GICv3 too.  It's permitted to have a configuration with FEAT_NMI in
    the CPU (and thus NMI support in the CPU interfaces too) but no NMI
    support in the distributor and redistributor, but this isn't a very
    useful setup as it's close to having no NMI support at all.

    We don't need to gate the enabling of NMI in the GIC behind a
    machine version property, because none of our current CPUs
    implement FEAT_NMI, and '-cpu max' is not something we maintain
    migration compatibility across versions for. So we can always
    enable the GIC NMI support when the CPU has it.

    Neither hvf nor KVM support NMI in the GIC yet, so we don't enable
    it unless we're using TCG.

    Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
    Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
    Message-id: 20240407081733.3231820-25-ruanjinjie@huawei.com
    [PMM: Update comment and commit message]
    Suggested-by: Peter Maydell <peter.maydell@linaro.org>
    Signed-off-by: Peter Maydell <peter.maydell@linaro.org>

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index c4b03b09c2..3c93c0c0a6 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -729,6 +729,20 @@ static void create_v2m(VirtMachineState *vms)
     vms->msi_controller = VIRT_MSI_CTRL_GICV2M;
 }

+/*
+ * If the CPU has FEAT_NMI, then turn on the NMI support in the GICv3 too.
+ * It's permitted to have a configuration with NMI in the CPU (and thus the
+ * GICv3 CPU interface) but not in the distributor/redistributors, but it's
+ * not very useful.
+ */
+static bool gicv3_nmi_present(VirtMachineState *vms)
+{
+    ARMCPU *cpu = ARM_CPU(qemu_get_cpu(0));
+
+    return tcg_enabled() && cpu_isar_feature(aa64_nmi, cpu) &&
+           (vms->gic_version != VIRT_GIC_VERSION_2);
+}
+
 static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
 {
     MachineState *ms = MACHINE(vms);
@@ -802,6 +816,11 @@ static void create_gic(VirtMachineState *vms, MemoryRegion *mem)
                               vms->virt);
         }
     }
+
+    if (gicv3_nmi_present(vms)) {
+        qdev_prop_set_bit(vms->gic, "has-nmi", true);
+    }
+
     gicbusdev = SYS_BUS_DEVICE(vms->gic);
     sysbus_realize_and_unref(gicbusdev, &error_fatal);
     sysbus_mmio_map(gicbusdev, 0, vms->memmap[VIRT_GIC_DIST].base);