Message ID | 20170403202829.7278-26-andre.przywara@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
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.przywara@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,
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) +{ + 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; + its->baser_dev = GITS_BASER_TYPE_DEVICE << GITS_BASER_TYPE_SHIFT; + its->baser_dev |= (7ULL << GITS_BASER_ENTRY_SIZE_SHIFT) | base_attr; + its->baser_coll = GITS_BASER_TYPE_COLLECTION << GITS_BASER_TYPE_SHIFT; + its->baser_coll |= (1ULL << GITS_BASER_ENTRY_SIZE_SHIFT) | base_attr; + 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; + + list_for_each_entry(hw_its, &host_its_list, entry) + { + /* + * 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. + */ + vgic_v3_its_init_virtual(d, hw_its->addr, hw_its->devid_bits, 20); + + 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
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.przywara@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(+)