[Xen-devel] [RFC PATCH 17/19] xen/arm: its: Support ITS interrupt handling

2015-03-02 Thread vijay . kilari
From: Vijaya Kumar K 

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 
---
 xen/arch/arm/gic-v3-its.c  |   31 +++
 xen/arch/arm/gic-v3.c  |8 ++--
 xen/arch/arm/gic.c |   38 --
 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.h  |3 +++
 xen/include/asm-arm/irq.h  |1 +
 8 files changed, 104 insertions(+), 11 deletions(-)

diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
index b2c3320..7adbee4 100644
--- a/xen/arch/arm/gic-v3-its.c
+++ b/xen/arch/arm/gic-v3-its.c
@@ -344,6 +344,37 @@ static const struct gic_its_hw_operations gic_its_ops = {
 .gic_guest_lpi_type  = &gic_guest_its_type,
 };
 
+void its_handle_lpi(uint32_t irqnr, struct cpu_user_regs *regs)
+{
+struct domain *d;
+struct irq_desc *desc = irq_to_desc(irqnr);
+
+irq_enter();
+spin_lock(&desc->lock);
+
+if ( !desc->action )
+{
+printk("UNKNOWN LPI without handler\n");
+goto err;
+}
+
+if ( desc->status & IRQ_GUEST )
+{
+d = irq_get_domain(desc);
+
+desc->handler->end(desc);
+
+desc->status |= IRQ_INPROGRESS;
+desc->arch.eoi_cpu = smp_processor_id();
+
+/* XXX: inject irq into all guest vcpus */
+vgic_vcpu_inject_irq(d->vcpu[0], irqnr);
+}
+err:
+spin_unlock(&desc->lock);
+irq_exit();
+}
+
 static u64 its_cmd_ptr_to_offset(struct its_node *its,
  struct its_cmd_block *ptr)
 {
diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
index 02e71dd..b654535 100644
--- a/xen/arch/arm/gic-v3.c
+++ b/xen/arch/arm/gic-v3.c
@@ -848,9 +848,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->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 fb77387..c4d352a 100644
--- a/xen/arch/arm/gic.c
+++ b/xen/arch/arm/gic.c
@@ -34,6 +34,7 @@
 #include 
 #include 
 #include 
+#include 
 
 static void gic_restore_pending_irqs(struct vcpu *v);
 
@@ -134,6 +135,21 @@ 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_its_hw_ops->gic_guest_lpi_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
  */
@@ -341,20 +357,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);
@@ -580,6 +609,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?
+its_handle_lpi(irq, regs);
+continue;
+}
 
 i

Re: [Xen-devel] [RFC PATCH 17/19] xen/arm: its: Support ITS interrupt handling

2015-03-03 Thread Stefano Stabellini
On Mon, 2 Mar 2015, vijay.kil...@gmail.com wrote:
> From: Vijaya Kumar K 
> 
> 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 
> ---
>  xen/arch/arm/gic-v3-its.c  |   31 +++
>  xen/arch/arm/gic-v3.c  |8 ++--
>  xen/arch/arm/gic.c |   38 --
>  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.h  |3 +++
>  xen/include/asm-arm/irq.h  |1 +
>  8 files changed, 104 insertions(+), 11 deletions(-)
> 
> diff --git a/xen/arch/arm/gic-v3-its.c b/xen/arch/arm/gic-v3-its.c
> index b2c3320..7adbee4 100644
> --- a/xen/arch/arm/gic-v3-its.c
> +++ b/xen/arch/arm/gic-v3-its.c
> @@ -344,6 +344,37 @@ static const struct gic_its_hw_operations gic_its_ops = {
>  .gic_guest_lpi_type  = &gic_guest_its_type,
>  };
>  
> +void its_handle_lpi(uint32_t irqnr, struct cpu_user_regs *regs)
> +{
> +struct domain *d;
> +struct irq_desc *desc = irq_to_desc(irqnr);
> +
> +irq_enter();
> +spin_lock(&desc->lock);
> +
> +if ( !desc->action )
> +{
> +printk("UNKNOWN LPI without handler\n");
> +goto err;
> +}
> +
> +if ( desc->status & IRQ_GUEST )
> +{
> +d = irq_get_domain(desc);
> +
> +desc->handler->end(desc);
> +
> +desc->status |= IRQ_INPROGRESS;
> +desc->arch.eoi_cpu = smp_processor_id();
> +
> +/* XXX: inject irq into all guest vcpus */
> +vgic_vcpu_inject_irq(d->vcpu[0], irqnr);
> +}

Does it really need a separate handler? It seems to me that LPIs could
just be handled from do_IRQ like the rest.

Also the comment is wrong in this case.


> +err:
> +spin_unlock(&desc->lock);
> +irq_exit();
> +}
> +
>  static u64 its_cmd_ptr_to_offset(struct its_node *its,
>   struct its_cmd_block *ptr)
>  {
> diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
> index 02e71dd..b654535 100644
> --- a/xen/arch/arm/gic-v3.c
> +++ b/xen/arch/arm/gic-v3.c
> @@ -848,9 +848,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->virq & GICH_LR_VIRTUAL_MASK) << 
> GICH_LR_VIRTUAL_SHIFT;
> +else
> +val |= ((uint64_t)p->irq & GICH_LR_VIRTUAL_MASK) << 
> GICH_LR_VIRTUAL_SHIFT;

desc->virq should contain the right value for all interrupts, not just
lpis, so you should be able to do:

val |= ((uint64_t)p->desc-virq & GICH_LR_VIRTUAL_MASK) << 
GICH_LR_VIRTUAL_SHIFT;

in all cases.


> +   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 fb77387..c4d352a 100644
> --- a/xen/arch/arm/gic.c
> +++ b/xen/arch/arm/gic.c
> @@ -34,6 +34,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  static void gic_restore_pending_irqs(struct vcpu *v);
>  
> @@ -134,6 +135,21 @@ 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_its_hw_ops->gic_guest_lpi_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
>   */
> @@ -341,20 +357,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);

Shouldn't p->desc->irq return the pirq for LPIs too? If it doesn't, 

Re: [Xen-devel] [RFC PATCH 17/19] xen/arm: its: Support ITS interrupt handling

2015-03-03 Thread Julien Grall

Hi Stefano,

On 03/03/2015 18:07, Stefano Stabellini wrote:

I would like to see a more generic handling of virq != physical irq.
This is not specific to LPIs but to any scenario where the physical irq
differs from the virtual irq.


I though we talked about it during the meeting at Connect...

I've already got a patch for making virq != pirq :
https://patches.linaro.org/43012/

That would drop the static 8K added because of the changes in irq_desc.

Regards,

--
Julien Grall

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel


Re: [Xen-devel] [RFC PATCH 17/19] xen/arm: its: Support ITS interrupt handling

2015-03-04 Thread Stefano Stabellini
On Tue, 3 Mar 2015, Julien Grall wrote:
> Hi Stefano,
> 
> On 03/03/2015 18:07, Stefano Stabellini wrote:
> > I would like to see a more generic handling of virq != physical irq.
> > This is not specific to LPIs but to any scenario where the physical irq
> > differs from the virtual irq.
> 
> I though we talked about it during the meeting at Connect...
> 
> I've already got a patch for making virq != pirq :
> https://patches.linaro.org/43012/
> 
> That would drop the static 8K added because of the changes in irq_desc.

I was pretty sure you had a patch for this already but I didn't have a
link to it ready. Your patch could be a requirement for this series.

___
Xen-devel mailing list
Xen-devel@lists.xen.org
http://lists.xen.org/xen-devel