Hi Andre,
On 03/04/17 21:28, Andre Przywara wrote:
For each hardware ITS create and initialize a virtual ITS for Dom0.
We use the same memory mapped address to keep the doorbell working.
Signed-off-by: Andre Przywara <andre.przyw...@arm.com>
---
xen/arch/arm/vgic-v3-its.c | 32 ++++++++++++++++++++++++++++++++
xen/arch/arm/vgic-v3.c | 17 +++++++++++++++++
xen/include/asm-arm/domain.h | 1 +
xen/include/asm-arm/gic_v3_its.h | 16 ++++++++++++++++
4 files changed, 66 insertions(+)
diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index 35a0730..dfb6eb3 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -1080,6 +1080,38 @@ static const struct mmio_handler_ops
vgic_its_mmio_handler = {
.write = vgic_v3_its_mmio_write,
};
+int vgic_v3_its_init_virtual(struct domain *d, paddr_t guest_addr,
+ unsigned int devid_bits, unsigned int intid_bits)
*All* initialization functions should have a counterpart in the same
patch to free the memory.
+{
+ struct virt_its *its;
+ uint64_t base_attr;
+
+ its = xzalloc(struct virt_its);
+ if ( ! its )
+ return -ENOMEM;
+
+ base_attr = GIC_BASER_InnerShareable << GITS_BASER_SHAREABILITY_SHIFT;
+ base_attr |= GIC_BASER_CACHE_SameAsInner <<
GITS_BASER_OUTER_CACHEABILITY_SHIFT;
+ base_attr |= GIC_BASER_CACHE_RaWaWb << GITS_BASER_INNER_CACHEABILITY_SHIFT;
+
+ its->cbaser = base_attr;
+ base_attr |= 0ULL << GITS_BASER_PAGE_SIZE_SHIFT;
Please explain the 0ULL.
+ its->baser_dev = GITS_BASER_TYPE_DEVICE << GITS_BASER_TYPE_SHIFT;
+ its->baser_dev |= (7ULL << GITS_BASER_ENTRY_SIZE_SHIFT) | base_attr;
Please explain 7ULL. I suspect you can use a sizeof of the device structure.
+ its->baser_coll = GITS_BASER_TYPE_COLLECTION << GITS_BASER_TYPE_SHIFT;
+ its->baser_coll |= (1ULL << GITS_BASER_ENTRY_SIZE_SHIFT) | base_attr;
Please explain 1ULL. I suspect you can use a sizeof of the collection
structure.
+ its->d = d;
+ its->doorbell_address = guest_addr + ITS_DOORBELL_OFFSET;
+ its->devid_bits = devid_bits;
+ its->intid_bits = intid_bits;
+ spin_lock_init(&its->vcmd_lock);
+ spin_lock_init(&its->its_lock);
+
+ register_mmio_handler(d, &vgic_its_mmio_handler, guest_addr, SZ_64K, its);
+
+ return 0;
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index ebcfc16..3fc309e 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -30,6 +30,7 @@
#include <asm/current.h>
#include <asm/mmio.h>
#include <asm/gic_v3_defs.h>
+#include <asm/gic_v3_its.h>
#include <asm/vgic.h>
#include <asm/vgic-emul.h>
#include <asm/vreg.h>
@@ -1582,6 +1583,7 @@ static int vgic_v3_domain_init(struct domain *d)
*/
if ( is_hardware_domain(d) )
{
+ struct host_its *hw_its;
unsigned int first_cpu = 0;
d->arch.vgic.dbase = vgic_v3_hw.dbase;
@@ -1607,6 +1609,21 @@ static int vgic_v3_domain_init(struct domain *d)
first_cpu += size / d->arch.vgic.rdist_stride;
}
+ d->arch.vgic.nr_regions = vgic_v3_hw.nr_rdist_regions;
Why did you add that?
+
+ list_for_each_entry(hw_its, &host_its_list, entry)
This could be done in vgic-v3-its.c. Also, I would prefer to see
something similar to vgic_v3_setup_hw for ITS to make the code agnostic.
+ {
+ /*
Coding style.
+ * For each host ITS create a virtual ITS using the same
+ * base and thus doorbell address.
+ * Use the same number of device ID bits as the host, and
+ * allow 20 bits for the interrupt ID.
Why only 20? This sounds like a made up number that will not fit some
platform... For the hardware domain you should the same value as used
for the host ITS.
+ */
+ vgic_v3_its_init_virtual(d, hw_its->addr, hw_its->devid_bits, 20);
Please check the return value.
+
+ d->arch.vgic.has_its = true;
+ }
+
}
else
{
diff --git a/xen/include/asm-arm/domain.h b/xen/include/asm-arm/domain.h
index f460457..6a60630 100644
--- a/xen/include/asm-arm/domain.h
+++ b/xen/include/asm-arm/domain.h
@@ -115,6 +115,7 @@ struct arch_domain
spinlock_t its_devices_lock; /* Protects the its_devices tree */
struct radix_tree_root pend_lpi_tree; /* Stores struct pending_irq's */
rwlock_t pend_lpi_tree_lock; /* Protects the pend_lpi_tree */
+ bool has_its;
#endif
} vgic;
diff --git a/xen/include/asm-arm/gic_v3_its.h b/xen/include/asm-arm/gic_v3_its.h
index 3b5f898..fb05311 100644
--- a/xen/include/asm-arm/gic_v3_its.h
+++ b/xen/include/asm-arm/gic_v3_its.h
@@ -154,6 +154,14 @@ uint64_t gicv3_get_redist_address(unsigned int cpu, bool
use_pta);
int gicv3_its_setup_collection(unsigned int cpu);
/*
+ * Create and register a virtual ITS at the given guest address.
+ * If a host ITS is specified, a hardware domain can reach out to that host
+ * ITS to deal with devices and LPI mappings and can enable/disable LPIs.
+ */
+int vgic_v3_its_init_virtual(struct domain *d, paddr_t guest_addr,
+ unsigned int devid_bits, unsigned int intid_bits);
+
+/*
* Map a device on the host by allocating an ITT on the host (ITS).
* "nr_event" specifies how many events (interrupts) this device will need.
* Setting "valid" to false deallocates the device.
@@ -219,6 +227,14 @@ static inline void gicv3_its_unmap_all_devices(struct
domain *d)
{
}
+static inline int vgic_v3_its_init_virtual(struct domain *d,
+ paddr_t guest_addr,
+ unsigned int devid_bits,
+ unsigned int intid_bits)
+{
+ return 0;
+}
+
#endif /* CONFIG_HAS_ITS */
#endif
Cheers,
--
Julien Grall
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel