diff mbox series

[RFC] xen_arm: its: Introduce arm_gicv3_its_xen

Message ID c7a180a5874f036c246fc39f921eefafecbc8c76.1702994649.git.mykyta_poturai@epam.com
State New
Headers show
Series [RFC] xen_arm: its: Introduce arm_gicv3_its_xen | expand

Commit Message

Mykyta Poturai Dec. 19, 2023, 2:09 p.m. UTC
Introduce the Xen variant of Arm ITS. It is hooked into the mmio
subsystem and recieves MSI messages. Upon receiving the MSI messages it
gets transfered to the Xen hypervisor with the new device model call for
further processing.

This change will allow for virtio-pci backends to send MSI interrupts
to the Xen guests.

Change marked as RFC to get some feedback on the approach while the
relevant Xen changes are being reviewed.

Link to relevant Xen changes:
https://patchwork.kernel.org/project/xen-devel/patch/6a631756a126e73390f95b9e86c69e3286c92f59.1702991909.git.mykyta_poturai@epam.com

Signed-off-by: Mykyta Poturai <mykyta_poturai@epam.com>
---
 hw/arm/xen_arm.c            |   6 ++
 hw/intc/Kconfig             |   5 ++
 hw/intc/arm_gicv3_its_xen.c | 115 ++++++++++++++++++++++++++++++++++++
 hw/intc/meson.build         |   1 +
 4 files changed, 127 insertions(+)
 create mode 100644 hw/intc/arm_gicv3_its_xen.c
diff mbox series

Patch

diff --git a/hw/arm/xen_arm.c b/hw/arm/xen_arm.c
index 684973328a..ff7397edca 100644
--- a/hw/arm/xen_arm.c
+++ b/hw/arm/xen_arm.c
@@ -374,6 +374,7 @@  static void xen_enable_tpm(void)
 static void xen_arm_init(MachineState *machine)
 {
     XenArmState *xam = XEN_ARM(machine);
+    DeviceState *dev;
     int rc;
 
     if (!xen_enabled()) {
@@ -405,6 +406,11 @@  static void xen_arm_init(MachineState *machine)
 
     xen_enable_tpm();
 
+    dev = qdev_new("arm-its-xen");
+
+    sysbus_realize_and_unref(SYS_BUS_DEVICE(dev), &error_fatal);
+    sysbus_mmio_map(SYS_BUS_DEVICE(dev), 0, GUEST_GICV3_ITS_BASE);
+    msi_nonbroken = true;
     return;
 }
 
diff --git a/hw/intc/Kconfig b/hw/intc/Kconfig
index a7cf301eab..5bc0f5ec18 100644
--- a/hw/intc/Kconfig
+++ b/hw/intc/Kconfig
@@ -35,6 +35,11 @@  config ARM_GIC_KVM
     default y
     depends on ARM_GIC && KVM
 
+config ARM_GIC_XEN
+    bool
+    default y
+    depends on ARM_GIC && XEN
+
 config XICS
     bool
 
diff --git a/hw/intc/arm_gicv3_its_xen.c b/hw/intc/arm_gicv3_its_xen.c
new file mode 100644
index 0000000000..e05b761802
--- /dev/null
+++ b/hw/intc/arm_gicv3_its_xen.c
@@ -0,0 +1,115 @@ 
+/*
+ * Xen-based ITS implementation for a GICv3-based system
+ *
+ * Copyright (c) 2015 Samsung Electronics Co., Ltd.
+ * Written by Pavel Fedin <p.fedin@samsung.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "qemu/module.h"
+#include "hw/intc/arm_gicv3_its_common.h"
+#include "hw/xen/xen-hvm-common.h"
+#include "hw/qdev-properties.h"
+#include "sysemu/runstate.h"
+#include "migration/blocker.h"
+#include "qom/object.h"
+#include "hw/pci/msi.h"
+#include "qemu/log.h"
+
+#define TYPE_XEN_ARM_ITS "arm-its-xen"
+
+static MemTxResult gicv3_its_trans_read(void *opaque, hwaddr offset,
+                                        uint64_t *data, unsigned size,
+                                        MemTxAttrs attrs)
+{
+    printf("ITS read at offset 0x%"PRIx64"\n", offset);
+    *data = 0;
+    return MEMTX_OK;
+}
+
+static MemTxResult gicv3_its_trans_write(void *opaque, hwaddr offset,
+                                         uint64_t value, unsigned size,
+                                         MemTxAttrs attrs)
+{
+    if (offset == 0x0040 && ((size == 2) || (size == 4))) {
+        GICv3ITSState *s = ARM_GICV3_ITS_COMMON(opaque);
+        GICv3ITSCommonClass *c = ARM_GICV3_ITS_COMMON_GET_CLASS(s);
+        int ret = c->send_msi(s, le64_to_cpu(value), attrs.requester_id);
+
+        if (ret < 0) {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "ITS: Error sending MSI: %s\n", strerror(-ret));
+        }
+    } else {
+            qemu_log_mask(LOG_GUEST_ERROR,
+                          "ITS: Error sending MSI: %s\n", strerror(EINVAL));
+    }
+    return MEMTX_OK;
+}
+static const MemoryRegionOps gicv3_its_trans_ops = {
+    .read_with_attrs = gicv3_its_trans_read,
+    .write_with_attrs = gicv3_its_trans_write,
+    .endianness = DEVICE_NATIVE_ENDIAN,
+};
+
+static int xen_its_send_msi(GICv3ITSState *s, uint32_t value, uint16_t devid)
+{
+    xendevicemodel_arm_inject_msi(xen_dmod, xen_domid, s->gits_translater_gpa, value, devid);
+    return 0;
+}
+
+static void xen_arm_its_realize(DeviceState *dev, Error **errp)
+{
+    GICv3ITSState *s = ARM_GICV3_ITS_COMMON(dev);
+    SysBusDevice *sbd = SYS_BUS_DEVICE(s);
+
+    memory_region_init_io(&s->iomem_its_translation, OBJECT(s),
+                            &gicv3_its_trans_ops, s,
+                          "translation", ITS_TRANS_SIZE);
+
+    memory_region_init(&s->iomem_main, OBJECT(s), "gicv3_its", ITS_SIZE);
+    memory_region_add_subregion(&s->iomem_main, ITS_CONTROL_SIZE,
+                                &s->iomem_its_translation);
+    sysbus_init_mmio(sbd, &s->iomem_main);
+
+    printf("init mmio done\n");
+    msi_nonbroken = true;
+    return;
+}
+
+static void xen_arm_its_class_init(ObjectClass *klass, void *data)
+{
+    DeviceClass *dc = DEVICE_CLASS(klass);
+    GICv3ITSCommonClass *icc = ARM_GICV3_ITS_COMMON_CLASS(klass);
+
+    dc->realize = xen_arm_its_realize;
+    icc->send_msi = xen_its_send_msi;
+}
+
+static const TypeInfo xen_arm_its_info = {
+    .name = TYPE_XEN_ARM_ITS,
+    .parent = TYPE_ARM_GICV3_ITS_COMMON,
+    .instance_size = sizeof(GICv3ITSState),
+    .class_init = xen_arm_its_class_init,
+};
+
+static void xen_arm_its_register_types(void)
+{
+    type_register_static(&xen_arm_its_info);
+}
+
+type_init(xen_arm_its_register_types)
diff --git a/hw/intc/meson.build b/hw/intc/meson.build
index d6d012fb26..7c32c2886e 100644
--- a/hw/intc/meson.build
+++ b/hw/intc/meson.build
@@ -31,6 +31,7 @@  specific_ss.add(when: 'CONFIG_ARM_GIC', if_true: files('arm_gicv3_cpuif_common.c
 specific_ss.add(when: 'CONFIG_ARM_GICV3_TCG', 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_ARM_GIC_KVM', 'TARGET_AARCH64'], if_true: files('arm_gicv3_kvm.c', 'arm_gicv3_its_kvm.c'))
+specific_ss.add(when: 'CONFIG_ARM_GIC_XEN', if_true: files('arm_gicv3_its_xen.c'))
 specific_ss.add(when: 'CONFIG_ARM_V7M', if_true: files('armv7m_nvic.c'))
 specific_ss.add(when: 'CONFIG_ASPEED_SOC', if_true: files('aspeed_vic.c'))
 specific_ss.add(when: 'CONFIG_EXYNOS4', if_true: files('exynos4210_gic.c', 'exynos4210_combiner.c'))