|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC PATCH v2 19/22] xen/arm: its: Support ITS interrupt handling
From: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx>
Add support for handling ITS(LPI) interrupts.
The LPI interrupts are handled by physical ITS
driver.
nested LPI interrupt handling is not tested and
enabled.
Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx>
---
v2: - Removed interrupt handler in ITS driver and
reused existing interrupt handling for LPIs.
---
xen/arch/arm/gic-v3.c | 8 ++++++--
xen/arch/arm/gic.c | 37 +++++++++++++++++++++++++++++++++++--
xen/arch/arm/irq.c | 10 +++++++---
xen/arch/arm/vgic-v3-its.c | 10 ++++++++++
xen/arch/arm/vgic.c | 14 ++++++++++----
xen/include/asm-arm/gic-its.h | 2 ++
xen/include/asm-arm/gic.h | 3 ++-
xen/include/asm-arm/irq.h | 1 +
8 files changed, 73 insertions(+), 12 deletions(-)
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 1b3ecd7..ffdaecf 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -869,9 +869,13 @@ static void gicv3_update_lr(int lr, const struct
pending_irq *p,
val = (((uint64_t)state & 0x3) << GICH_LR_STATE_SHIFT) | grp;
val |= ((uint64_t)p->priority & 0xff) << GICH_LR_PRIORITY_SHIFT;
- val |= ((uint64_t)p->irq & GICH_LR_VIRTUAL_MASK) << GICH_LR_VIRTUAL_SHIFT;
- if ( p->desc != NULL )
+ if ( is_lpi(p->irq) )
+ val |= ((uint64_t)p->desc->arch.virq & GICH_LR_VIRTUAL_MASK) <<
GICH_LR_VIRTUAL_SHIFT;
+ else
+ val |= ((uint64_t)p->irq & GICH_LR_VIRTUAL_MASK) <<
GICH_LR_VIRTUAL_SHIFT;
+
+ if ( p->desc != NULL && !(is_lpi(p->irq)) )
val |= GICH_LR_HW | (((uint64_t)p->desc->irq & GICH_LR_PHYSICAL_MASK)
<< GICH_LR_PHYSICAL_SHIFT);
diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
index 390c8b0..6ac1f18 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -34,6 +34,7 @@
#include <asm/io.h>
#include <asm/gic.h>
#include <asm/vgic.h>
+#include <asm/gic-its.h>
static void gic_restore_pending_irqs(struct vcpu *v);
@@ -123,6 +124,20 @@ void gic_route_irq_to_xen(struct irq_desc *desc, const
cpumask_t *cpu_mask,
gic_set_irq_properties(desc, cpu_mask, priority);
}
+void gic_route_lpi_to_guest(struct domain *d, struct irq_desc *desc,
+ const cpumask_t *cpu_mask, unsigned int priority)
+{
+ struct pending_irq *p;
+ ASSERT(spin_is_locked(&desc->lock));
+
+ desc->handler = gic_hw_ops->gic_guest_irq_type;
+ set_bit(_IRQ_GUEST, &desc->status);
+
+ /* TODO: do not assume delivery to vcpu0 */
+ p = irq_to_pending(d->vcpu[0], desc->irq);
+ p->desc = desc;
+}
+
/* Program the GIC to route an interrupt to a guest
* - desc.lock must be held
*/
@@ -330,20 +345,33 @@ static void gic_update_one_lr(struct vcpu *v, int i)
struct pending_irq *p;
int irq;
struct gic_lr lr_val;
+ uint32_t pirq;
ASSERT(spin_is_locked(&v->arch.vgic.lock));
ASSERT(!local_irq_is_enabled());
gic_hw_ops->read_lr(i, &lr_val);
irq = lr_val.virq;
- p = irq_to_pending(v, irq);
+
+ if ( is_lpi(irq) )
+ {
+ // Fetch corresponding plpi for vlpi
+ if ( vgic_its_get_pid(v, irq, &pirq) )
+ BUG();
+ p = irq_to_pending(v, pirq);
+ irq = pirq;
+ }
+ else
+ {
+ p = irq_to_pending(v, irq);
+ }
if ( lr_val.state & GICH_LR_ACTIVE )
{
set_bit(GIC_IRQ_GUEST_ACTIVE, &p->status);
if ( test_bit(GIC_IRQ_GUEST_ENABLED, &p->status) &&
test_and_clear_bit(GIC_IRQ_GUEST_QUEUED, &p->status) )
{
- if ( p->desc == NULL )
+ if ( p->desc == NULL || is_lpi(irq) )
{
lr_val.state |= GICH_LR_PENDING;
gic_hw_ops->write_lr(i, &lr_val);
@@ -569,6 +597,11 @@ void gic_interrupt(struct cpu_user_regs *regs, int is_fiq)
do {
/* Reading IRQ will ACK it */
irq = gic_hw_ops->read_irq();
+ if ( is_lpi(irq) ) {
+ // TODO: Enable irqs?
+ do_IRQ(regs, irq, is_fiq);
+ continue;
+ }
if ( likely(irq >= 16 && irq < 1021) )
{
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
index 0d3bf9a..9257a23 100644
--- a/xen/arch/arm/irq.c
+++ b/xen/arch/arm/irq.c
@@ -284,7 +284,7 @@ void __cpuinit init_secondary_IRQ(void)
BUG_ON(init_local_irq_data() < 0);
}
-static inline struct domain *irq_get_domain(struct irq_desc *desc)
+struct domain *irq_get_domain(struct irq_desc *desc)
{
ASSERT(spin_is_locked(&desc->lock));
@@ -611,9 +611,13 @@ int route_irq_to_guest(struct domain *d, unsigned int irq,
retval = __setup_irq(desc, 0, action);
if ( retval )
goto out;
+ if ( irq >= NR_LOCAL_IRQS && irq < NR_IRQS)
+ gic_route_irq_to_guest(d, desc, cpumask_of(smp_processor_id()),
+ GIC_PRI_IRQ);
+ else
+ gic_route_lpi_to_guest(d, desc, cpumask_of(smp_processor_id()),
+ GIC_PRI_IRQ);
- gic_route_irq_to_guest(d, desc, cpumask_of(smp_processor_id()),
- GIC_PRI_IRQ);
spin_unlock_irqrestore(&desc->lock, flags);
return 0;
diff --git a/xen/arch/arm/vgic-v3-its.c b/xen/arch/arm/vgic-v3-its.c
index 1447e91..360be0d 100644
--- a/xen/arch/arm/vgic-v3-its.c
+++ b/xen/arch/arm/vgic-v3-its.c
@@ -896,6 +896,16 @@ int vgic_its_get_pid(struct vcpu *v, uint32_t vlpi,
uint32_t *plpi)
return 1;
}
+uint8_t vgic_its_get_priority(struct vcpu *v, uint32_t pid)
+{
+ uint8_t priority;
+
+ priority = readb_relaxed(v->domain->arch.lpi_conf->prop_page + pid);
+ priority &= 0xfc;
+
+ return priority;
+}
+
static int vgic_v3_gits_lpi_mmio_read(struct vcpu *v, mmio_info_t *info)
{
uint32_t offset;
diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index 6fc8df1..580105f 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -399,14 +399,20 @@ void vgic_clear_pending_irqs(struct vcpu *v)
void vgic_vcpu_inject_irq(struct vcpu *v, unsigned int irq)
{
uint8_t priority;
- struct vgic_irq_rank *rank = vgic_rank_irq(v, irq);
+ struct vgic_irq_rank *rank;
struct pending_irq *iter, *n = irq_to_pending(v, irq);
unsigned long flags;
bool_t running;
- vgic_lock_rank(v, rank, flags);
- priority = v->domain->arch.vgic.handler->get_irq_priority(v, irq);
- vgic_unlock_rank(v, rank, flags);
+ if ( irq < NR_GIC_LPI )
+ {
+ rank = vgic_rank_irq(v, irq);
+ vgic_lock_rank(v, rank, flags);
+ priority = v->domain->arch.vgic.handler->get_irq_priority(v, irq);
+ vgic_unlock_rank(v, rank, flags);
+ }
+ else
+ priority = vgic_its_get_priority(v, irq);
spin_lock_irqsave(&v->arch.vgic.lock, flags);
diff --git a/xen/include/asm-arm/gic-its.h b/xen/include/asm-arm/gic-its.h
index af28d66..dc1b98c 100644
--- a/xen/include/asm-arm/gic-its.h
+++ b/xen/include/asm-arm/gic-its.h
@@ -232,6 +232,8 @@ uint32_t its_get_pta_type(void);
uint32_t its_get_nr_its(void);
struct its_node * its_get_phys_node(uint32_t dev_id);
int vgic_its_unmap_lpi_prop(struct vcpu *v);
+int vgic_its_get_pid(struct vcpu *v, uint32_t vlpi, uint32_t *plpi);
+uint8_t vgic_its_get_priority(struct vcpu *v, uint32_t pid);
#endif /* __ASM_ARM_GIC_ITS_H__ */
/*
diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
index b4f4904..f816664 100644
--- a/xen/include/asm-arm/gic.h
+++ b/xen/include/asm-arm/gic.h
@@ -214,7 +214,6 @@ enum gic_version {
};
extern enum gic_version gic_hw_version(void);
-
/* Program the GIC to route an interrupt */
extern void gic_route_irq_to_xen(struct irq_desc *desc, const cpumask_t
*cpu_mask,
unsigned int priority);
@@ -345,6 +344,8 @@ struct gic_hw_operations {
void register_gic_ops(const struct gic_hw_operations *ops);
int gic_make_node(const struct domain *d,const struct dt_device_node *node,
void *fdt);
+void gic_route_lpi_to_guest(struct domain *d, struct irq_desc *desc,
+ const cpumask_t *cpu_mask, unsigned int priority);
#endif /* __ASSEMBLY__ */
#endif
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
index 8568b96..35a74aa 100644
--- a/xen/include/asm-arm/irq.h
+++ b/xen/include/asm-arm/irq.h
@@ -54,6 +54,7 @@ int irq_set_spi_type(unsigned int spi, unsigned int type);
int irq_set_desc_data(unsigned int irq, struct its_device *d);
struct its_device *irq_get_desc_data(struct irq_desc *d);
int platform_get_irq(const struct dt_device_node *device, int index);
+struct domain *irq_get_domain(struct irq_desc *desc);
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 |