[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH v3 07/18] xen/arm: ITS: implement hw_irq_controller for LPIs
From: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx> Implements hw_irq_controller api's required to handle LPI's Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx> --- xen/arch/arm/gic-v3-its.c | 39 +++++++++++++++++++++++++++++++++++++++ xen/arch/arm/gic-v3.c | 26 +++++++++++++++++++------- xen/arch/arm/irq.c | 16 ++++++++++++++++ xen/include/asm-arm/gic-its.h | 10 ++++++++++ xen/include/asm-arm/gic.h | 4 ++++ xen/include/asm-arm/irq.h | 4 +++- 6 files changed, 91 insertions(+), 8 deletions(-) diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c index 349d0bb..535fc53 100644 --- a/xen/arch/arm/gic-v3-its.c +++ b/xen/arch/arm/gic-v3-its.c @@ -508,6 +508,45 @@ static void its_send_invall(struct its_node *its, struct its_collection *col) its_send_single_command(its, its_build_invall_cmd, &desc); } +void lpi_set_config(struct irq_desc *desc, int enable) +{ + struct its_collection *col; + struct its_device *its_dev = get_irq_device(desc); + u8 *cfg; + u32 virq = irq_to_virq(desc); + + ASSERT(virq < its_dev->nr_lpis); + + cfg = gic_rdists->prop_page + desc->irq - NR_GIC_LPI; + if ( enable ) + *cfg |= LPI_PROP_ENABLED; + else + *cfg &= ~LPI_PROP_ENABLED; + + /* + * Make the above write visible to the redistributors. + * And yes, we're flushing exactly: One. Single. Byte. + * Humpf... + */ + if ( gic_rdists->flags & RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING ) + clean_and_invalidate_dcache_va_range(cfg, sizeof(*cfg)); + else + dsb(ishst); + + /* Get collection id for this event id */ + col = &its_dev->its->collections[virq % num_online_cpus()]; + its_send_inv(its_dev, col, virq); +} + +void its_set_affinity(struct irq_desc *desc, int cpu) +{ + struct its_device *its_dev = get_irq_device(desc); + struct its_collection *target_col; + + /* Physical collection id */ + target_col = &its_dev->its->collections[cpu]; + its_send_movi(its_dev, target_col, irq_to_virq(desc)); +} /* * How we allocate LPIs: * diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c index b5c59f6..556b291 100644 --- a/xen/arch/arm/gic-v3.c +++ b/xen/arch/arm/gic-v3.c @@ -40,6 +40,7 @@ #include <asm/device.h> #include <asm/gic.h> #include <asm/gic_v3_defs.h> +#include <asm/gic-its.h> #include <asm/cpufeature.h> struct rdist_region { @@ -427,12 +428,18 @@ static void gicv3_poke_irq(struct irq_desc *irqd, u32 offset) static void gicv3_unmask_irq(struct irq_desc *irqd) { - gicv3_poke_irq(irqd, GICD_ISENABLER); + if ( is_lpi(irqd->irq) ) + lpi_set_config(irqd, 1); + else + gicv3_poke_irq(irqd, GICD_ISENABLER); } static void gicv3_mask_irq(struct irq_desc *irqd) { - gicv3_poke_irq(irqd, GICD_ICENABLER); + if ( is_lpi(irqd->irq) ) + lpi_set_config(irqd, 0); + else + gicv3_poke_irq(irqd, GICD_ICENABLER); } static void gicv3_eoi_irq(struct irq_desc *irqd) @@ -1095,13 +1102,18 @@ static void gicv3_irq_set_affinity(struct irq_desc *desc, const cpumask_t *mask) spin_lock(&gicv3.lock); cpu = gicv3_get_cpu_from_mask(mask); - affinity = gicv3_mpidr_to_affinity(cpu); - /* Make sure we don't broadcast the interrupt */ - affinity &= ~GICD_IROUTER_SPI_MODE_ANY; - if ( desc->irq >= NR_GIC_LOCAL_IRQS ) - writeq_relaxed(affinity, (GICD + GICD_IROUTER + desc->irq * 8)); + if ( is_lpi(desc->irq) ) + its_set_affinity(desc, cpu); + else + { + affinity = gicv3_mpidr_to_affinity(cpu); + /* Make sure we don't broadcast the interrupt */ + affinity &= ~GICD_IROUTER_SPI_MODE_ANY; + if ( desc->irq >= NR_GIC_LOCAL_IRQS ) + writeq_relaxed(affinity, (GICD + GICD_IROUTER + desc->irq * 8)); + } spin_unlock(&gicv3.lock); } diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c index 2dd43ee..9dbdf7d 100644 --- a/xen/arch/arm/irq.c +++ b/xen/arch/arm/irq.c @@ -36,6 +36,7 @@ struct irq_guest { struct domain *d; unsigned int virq; + struct its_device *dev; }; static void ack_none(struct irq_desc *irq) @@ -143,6 +144,21 @@ static inline struct domain *irq_get_domain(struct irq_desc *desc) return irq_get_guest_info(desc)->d; } +unsigned int irq_to_virq(struct irq_desc *desc) +{ + return irq_get_guest_info(desc)->virq; +} + +struct its_device *get_irq_device(struct irq_desc *desc) +{ + return irq_get_guest_info(desc)->dev; +} + +void set_irq_device(struct irq_desc *desc, struct its_device *dev) +{ + irq_get_guest_info(desc)->dev = dev; +} + void irq_set_affinity(struct irq_desc *desc, const cpumask_t *cpu_mask) { if ( desc != NULL ) diff --git a/xen/include/asm-arm/gic-its.h b/xen/include/asm-arm/gic-its.h index 59a6490..a47cf26 100644 --- a/xen/include/asm-arm/gic-its.h +++ b/xen/include/asm-arm/gic-its.h @@ -205,6 +205,16 @@ static inline uint8_t its_decode_cmd(its_cmd_block *cmd) return cmd->raw_cmd[0] & 0xff; } +static inline uint32_t its_decode_devid(struct domain *d, its_cmd_block *cmd) +{ + /* TODO: Use pci helper function to get physical id */ + return (cmd->raw_cmd[0] >> 32); +} + +void its_set_affinity(struct irq_desc *desc, int cpu); +void lpi_set_config(struct irq_desc *desc, int enable); +uint32_t its_get_nr_events(void); + #endif /* __ASM_ARM_GIC_ITS_H__ */ /* diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h index e9d5f36..0209cc5 100644 --- a/xen/include/asm-arm/gic.h +++ b/xen/include/asm-arm/gic.h @@ -20,6 +20,9 @@ #define NR_GIC_LOCAL_IRQS NR_LOCAL_IRQS #define NR_GIC_SGI 16 +#define NR_GIC_LPI 8192 +#define MAX_LPI (8192 + 4096) +#define MAX_NR_LPIS 4096 #define MAX_RDIST_COUNT 4 #define GICD_CTLR (0x000) @@ -163,6 +166,7 @@ #define DT_MATCH_GIC_V3 DT_MATCH_COMPATIBLE("arm,gic-v3") #define DT_MATCH_GIC_ITS DT_MATCH_COMPATIBLE("arm,gic-v3-its") +#define is_lpi(lpi) (lpi >= NR_GIC_LPI && lpi < MAX_LPI) /* * GICv3 registers that needs to be saved/restored */ diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h index 34b492b..3b29182 100644 --- a/xen/include/asm-arm/irq.h +++ b/xen/include/asm-arm/irq.h @@ -50,7 +50,9 @@ void arch_move_irqs(struct vcpu *v); /* Set IRQ type for an SPI */ int irq_set_spi_type(unsigned int spi, unsigned int type); - +unsigned int irq_to_virq(struct irq_desc *desc); +struct its_device *get_irq_device(struct irq_desc *desc); +void set_irq_device(struct irq_desc *desc, struct its_device *dev); int platform_get_irq(const struct dt_device_node *device, int index); void irq_set_affinity(struct irq_desc *desc, const cpumask_t *cpu_mask); -- 1.7.9.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |