So far the ivshmem code assumed to run only on x86. In order to prepare
it for reuse on other architectures (ARM, ARM64), factor out the bits
and pieces that are arch-specific and implement them for x86.

Signed-off-by: Jan Kiszka <[email protected]>
---
 hypervisor/arch/x86/Kbuild                |  2 +-
 hypervisor/arch/x86/include/asm/ivshmem.h | 22 +++++++++
 hypervisor/arch/x86/ivshmem.c             | 71 +++++++++++++++++++++++++++
 hypervisor/arch/x86/vtd.c                 |  2 +-
 hypervisor/include/jailhouse/ivshmem.h    | 20 +++++++-
 hypervisor/ivshmem.c                      | 80 +++++--------------------------
 hypervisor/pci.c                          |  2 +-
 7 files changed, 127 insertions(+), 72 deletions(-)
 create mode 100644 hypervisor/arch/x86/include/asm/ivshmem.h
 create mode 100644 hypervisor/arch/x86/ivshmem.c

diff --git a/hypervisor/arch/x86/Kbuild b/hypervisor/arch/x86/Kbuild
index 4157fcd..8fe595f 100644
--- a/hypervisor/arch/x86/Kbuild
+++ b/hypervisor/arch/x86/Kbuild
@@ -15,7 +15,7 @@
 BUILT_IN_OBJECTS := built-in-amd.o built-in-intel.o
 COMMON_OBJECTS := apic.o dbg-write.o entry.o setup.o control.o mmio.o iommu.o \
                  paging.o ../../pci.o pci.o ioapic.o i8042.o vcpu.o \
-                 uart.o vga.o ../../ivshmem.o
+                 uart.o vga.o ../../ivshmem.o ivshmem.o
 
 always := $(BUILT_IN_OBJECTS)
 
diff --git a/hypervisor/arch/x86/include/asm/ivshmem.h 
b/hypervisor/arch/x86/include/asm/ivshmem.h
new file mode 100644
index 0000000..081d4a2
--- /dev/null
+++ b/hypervisor/arch/x86/include/asm/ivshmem.h
@@ -0,0 +1,22 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) Siemens AG, 2016
+ *
+ * Authors:
+ *  Jan Kiszka <[email protected]>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#ifndef _JAILHOUSE_ASM_IVSHMEM_H
+#define _JAILHOUSE_ASM_IVSHMEM_H
+
+#include <asm/apic.h>
+
+struct arch_pci_ivshmem {
+       struct apic_irq_message irq_msg;
+};
+
+#endif /* !_JAILHOUSE_ASM_IVSHMEM_H */
diff --git a/hypervisor/arch/x86/ivshmem.c b/hypervisor/arch/x86/ivshmem.c
new file mode 100644
index 0000000..49f74e7
--- /dev/null
+++ b/hypervisor/arch/x86/ivshmem.c
@@ -0,0 +1,71 @@
+/*
+ * Jailhouse, a Linux-based partitioning hypervisor
+ *
+ * Copyright (c) Siemens AG, 2014-2016
+ *
+ * Author:
+ *  Henning Schild <[email protected]>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include <jailhouse/cell.h>
+#include <jailhouse/ivshmem.h>
+#include <jailhouse/pci.h>
+#include <jailhouse/printk.h>
+#include <asm/pci.h>
+
+void arch_ivshmem_write_doorbell(struct ivshmem_endpoint *ive)
+{
+       struct ivshmem_endpoint *remote = ive->remote;
+       struct apic_irq_message irq_msg;
+
+       if (!remote)
+               return;
+
+       /* get a copy of the struct before using it, the read barrier makes
+        * sure the copy is consistent */
+       irq_msg = remote->arch.irq_msg;
+       memory_load_barrier();
+       if (irq_msg.valid)
+               apic_send_irq(irq_msg);
+}
+
+int arch_ivshmem_update_msix(struct pci_device *device)
+{
+       struct ivshmem_endpoint *ive = device->ivshmem_endpoint;
+       union x86_msi_vector msi = {
+               .raw.address = device->msix_vectors[0].address,
+               .raw.data = device->msix_vectors[0].data,
+       };
+       struct apic_irq_message irq_msg;
+
+       /* before doing anything mark the cached irq_msg as invalid,
+        * on success it will be valid on return. */
+       ive->arch.irq_msg.valid = 0;
+       memory_barrier();
+
+       if (ivshmem_is_msix_masked(ive))
+               return 0;
+
+       irq_msg = x86_pci_translate_msi(device, 0, 0, msi);
+       if (!irq_msg.valid)
+               return 0;
+
+       if (!apic_filter_irq_dest(device->cell, &irq_msg)) {
+               panic_printk("FATAL: ivshmem MSI-X target outside of "
+                            "cell \"%s\" device %02x:%02x.%x\n",
+                            device->cell->config->name,
+                            PCI_BDF_PARAMS(device->info->bdf));
+               return -EPERM;
+       }
+       /* now copy the whole struct into our cache and mark the cache
+        * valid at the end */
+       irq_msg.valid = 0;
+       ive->arch.irq_msg = irq_msg;
+       memory_barrier();
+       ive->arch.irq_msg.valid = 1;
+
+       return 0;
+}
diff --git a/hypervisor/arch/x86/vtd.c b/hypervisor/arch/x86/vtd.c
index a1b2add..39e0d89 100644
--- a/hypervisor/arch/x86/vtd.c
+++ b/hypervisor/arch/x86/vtd.c
@@ -393,7 +393,7 @@ static int vtd_emulate_inv_int(unsigned int unit_no, 
unsigned int index)
 
        device = pci_get_assigned_device(&root_cell, irte_usage->device_id);
        if (device && device->info->type == JAILHOUSE_PCI_TYPE_IVSHMEM)
-               return ivshmem_update_msix(device);
+               return arch_ivshmem_update_msix(device);
 
        irq_msg = iommu_get_remapped_root_int(unit_no, irte_usage->device_id,
                                              irte_usage->vector, index);
diff --git a/hypervisor/include/jailhouse/ivshmem.h 
b/hypervisor/include/jailhouse/ivshmem.h
index 5c3c415..c0fd520 100644
--- a/hypervisor/include/jailhouse/ivshmem.h
+++ b/hypervisor/include/jailhouse/ivshmem.h
@@ -15,7 +15,7 @@
 #define _JAILHOUSE_IVSHMEM_H
 
 #include <jailhouse/pci.h>
-#include <asm/apic.h>
+#include <asm/ivshmem.h>
 
 #define IVSHMEM_CFG_MSIX_CAP   0x50
 #define IVSHMEM_CFG_SIZE       (IVSHMEM_CFG_MSIX_CAP + 12)
@@ -33,7 +33,7 @@ struct ivshmem_endpoint {
        u64 bar4_address;
        struct pci_device *device;
        struct ivshmem_endpoint *remote;
-       struct apic_irq_message irq_msg;
+       struct arch_pci_ivshmem arch;
 };
 
 int ivshmem_init(struct cell *cell, struct pci_device *device);
@@ -44,5 +44,21 @@ enum pci_access ivshmem_pci_cfg_write(struct pci_device 
*device,
 enum pci_access ivshmem_pci_cfg_read(struct pci_device *device, u16 address,
                                     u32 *value);
 
+bool ivshmem_is_msix_masked(struct ivshmem_endpoint *ive);
+
+/**
+ * Handle write to doorbell register.
+ * @param ive          Ivshmem endpoint the write was performed on.
+ */
+void arch_ivshmem_write_doorbell(struct ivshmem_endpoint *ive);
+
+/**
+ * Update cached MSI-X state (if any) of the given ivshmem device.
+ * @param device       The device to be updated.
+ *
+ * @return 0 on success, negative error code otherwise.
+ */
+int arch_ivshmem_update_msix(struct pci_device *device);
+
 /** @} IVSHMEM */
 #endif /* !_JAILHOUSE_IVSHMEM_H */
diff --git a/hypervisor/ivshmem.c b/hypervisor/ivshmem.c
index cd4b6c1..6f628a7 100644
--- a/hypervisor/ivshmem.c
+++ b/hypervisor/ivshmem.c
@@ -26,7 +26,7 @@
 #include <jailhouse/string.h>
 #include <jailhouse/utils.h>
 #include <jailhouse/processor.h>
-#include <asm/pci.h>
+#include <asm/percpu.h>
 
 #define VIRTIO_VENDOR_ID       0x1af4
 #define IVSHMEM_DEVICE_ID      0x1110
@@ -67,22 +67,6 @@ static const u32 default_cspace[IVSHMEM_CFG_SIZE / 
sizeof(u32)] = {
        [(IVSHMEM_CFG_MSIX_CAP + 0x8)/4] = 0x10 * IVSHMEM_MSIX_VECTORS | 4,
 };
 
-static void ivshmem_write_doorbell(struct ivshmem_endpoint *ive)
-{
-       struct ivshmem_endpoint *remote = ive->remote;
-       struct apic_irq_message irq_msg;
-
-       if (!remote)
-               return;
-
-       /* get a copy of the struct before using it, the read barrier makes
-        * sure the copy is consistent */
-       irq_msg = remote->irq_msg;
-       memory_load_barrier();
-       if (irq_msg.valid)
-               apic_send_irq(irq_msg);
-}
-
 static enum mmio_result ivshmem_register_mmio(void *arg,
                                              struct mmio_access *mmio)
 {
@@ -96,7 +80,7 @@ static enum mmio_result ivshmem_register_mmio(void *arg,
 
        if (mmio->address == IVSHMEM_REG_DBELL) {
                if (mmio->is_write)
-                       ivshmem_write_doorbell(ive);
+                       arch_ivshmem_write_doorbell(ive);
                else
                        mmio->value = 0;
                return MMIO_HANDLED;
@@ -106,7 +90,7 @@ static enum mmio_result ivshmem_register_mmio(void *arg,
                if (mmio->is_write) {
                        ive->state = mmio->value;
                        memory_barrier();
-                       ivshmem_write_doorbell(ive);
+                       arch_ivshmem_write_doorbell(ive);
                } else {
                        mmio->value = ive->state;
                }
@@ -126,7 +110,13 @@ static enum mmio_result ivshmem_register_mmio(void *arg,
        return MMIO_ERROR;
 }
 
-static bool ivshmem_is_msix_masked(struct ivshmem_endpoint *ive)
+/**
+ * Check if MSI-X doorbell interrupt is masked.
+ * @param ive          Ivshmem endpoint the mask should be checked for.
+ *
+ * @return True if MSI-X interrupt is masked.
+ */
+bool ivshmem_is_msix_masked(struct ivshmem_endpoint *ive)
 {
        union pci_msix_registers c;
 
@@ -146,50 +136,6 @@ static bool ivshmem_is_msix_masked(struct ivshmem_endpoint 
*ive)
        return false;
 }
 
-/**
- * Update cached MSI-X state of the given ivshmem device.
- * @param device       The device to be updated.
- *
- * @return 0 on success, negative error code otherwise.
- */
-int ivshmem_update_msix(struct pci_device *device)
-{
-       struct ivshmem_endpoint *ive = device->ivshmem_endpoint;
-       union x86_msi_vector msi = {
-               .raw.address = device->msix_vectors[0].address,
-               .raw.data = device->msix_vectors[0].data,
-       };
-       struct apic_irq_message irq_msg;
-
-       /* before doing anything mark the cached irq_msg as invalid,
-        * on success it will be valid on return. */
-       ive->irq_msg.valid = 0;
-       memory_barrier();
-
-       if (ivshmem_is_msix_masked(ive))
-               return 0;
-
-       irq_msg = x86_pci_translate_msi(device, 0, 0, msi);
-       if (!irq_msg.valid)
-               return 0;
-
-       if (!apic_filter_irq_dest(ive->device->cell, &irq_msg)) {
-               panic_printk("FATAL: ivshmem MSI-X target outside of "
-                            "cell \"%s\" device %02x:%02x.%x\n",
-                            device->cell->config->name,
-                            PCI_BDF_PARAMS(device->info->bdf));
-               return -EPERM;
-       }
-       /* now copy the whole struct into our cache and mark the cache
-        * valid at the end */
-       irq_msg.valid = 0;
-       ive->irq_msg = irq_msg;
-       memory_barrier();
-       ive->irq_msg.valid = 1;
-
-       return 0;
-}
-
 static enum mmio_result ivshmem_msix_mmio(void *arg, struct mmio_access *mmio)
 {
        struct ivshmem_endpoint *ive = arg;
@@ -210,7 +156,7 @@ static enum mmio_result ivshmem_msix_mmio(void *arg, struct 
mmio_access *mmio)
        } else {
                if (mmio->is_write) {
                        msix_table[mmio->address / 4] = mmio->value;
-                       if (ivshmem_update_msix(ive->device))
+                       if (arch_ivshmem_update_msix(ive->device))
                                return MMIO_ERROR;
                } else {
                        mmio->value = msix_table[mmio->address / 4];
@@ -236,7 +182,7 @@ static int ivshmem_write_command(struct ivshmem_endpoint 
*ive, u16 val)
 
        if ((val & PCI_CMD_MASTER) != (*cmd & PCI_CMD_MASTER)) {
                *cmd = (*cmd & ~PCI_CMD_MASTER) | (val & PCI_CMD_MASTER);
-               err = ivshmem_update_msix(device);
+               err = arch_ivshmem_update_msix(device);
                if (err)
                        return err;
        }
@@ -274,7 +220,7 @@ static int ivshmem_write_msix_control(struct 
ivshmem_endpoint *ive, u32 val)
        newval.fmask = p->fmask;
        if (ive->cspace[IVSHMEM_CFG_MSIX_CAP/4] != newval.raw) {
                ive->cspace[IVSHMEM_CFG_MSIX_CAP/4] = newval.raw;
-               return ivshmem_update_msix(ive->device);
+               return arch_ivshmem_update_msix(ive->device);
        }
        return 0;
 }
diff --git a/hypervisor/pci.c b/hypervisor/pci.c
index 4a652e8..3806073 100644
--- a/hypervisor/pci.c
+++ b/hypervisor/pci.c
@@ -776,7 +776,7 @@ void pci_config_commit(struct cell *cell_added_removed)
                                        goto error;
                        }
                        if (device->info->type == JAILHOUSE_PCI_TYPE_IVSHMEM) {
-                               err = ivshmem_update_msix(device);
+                               err = arch_ivshmem_update_msix(device);
                                if (err) {
                                        cap = NULL;
                                        goto error;
-- 
2.1.4

-- 
You received this message because you are subscribed to the Google Groups 
"Jailhouse" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to