diff mbox

[v4,19/24] arm/acpi: Configure SPI interrupt type and route to Dom0 dynamically

Message ID 1456658360-16080-20-git-send-email-zhaoshenglong@huawei.com (mailing list archive)
State New, archived
Headers show

Commit Message

Shannon Zhao Feb. 28, 2016, 11:19 a.m. UTC
From: Shannon Zhao <shannon.zhao@linaro.org>

Interrupt information is described in DSDT and is not available at the
time of booting. Check if the interrupt is permitted to access and set
the interrupt type, route it to guest dynamically only for SPI
and Dom0.

Signed-off-by: Parth Dixit <parth.dixit@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 xen/arch/arm/vgic.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

Comments

Stefano Stabellini Feb. 29, 2016, 4:58 p.m. UTC | #1
On Sun, 28 Feb 2016, Shannon Zhao wrote:
> From: Shannon Zhao <shannon.zhao@linaro.org>
> 
> Interrupt information is described in DSDT and is not available at the
> time of booting. Check if the interrupt is permitted to access and set
> the interrupt type, route it to guest dynamically only for SPI
> and Dom0.
> 
> Signed-off-by: Parth Dixit <parth.dixit@linaro.org>
> Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
> ---
>  xen/arch/arm/vgic.c | 32 ++++++++++++++++++++++++++++++++
>  1 file changed, 32 insertions(+)
> 
> diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
> index ee35683..902a16d 100644
> --- a/xen/arch/arm/vgic.c
> +++ b/xen/arch/arm/vgic.c
> @@ -25,6 +25,8 @@
>  #include <xen/irq.h>
>  #include <xen/sched.h>
>  #include <xen/perfc.h>
> +#include <xen/iocap.h>
> +#include <xen/acpi.h>
>  
>  #include <asm/current.h>
>  
> @@ -334,6 +336,8 @@ void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n)
>      }
>  }
>  
> +#define VGIC_ICFG_MASK(intr) ( 1 << ( ( 2 * ( intr % 16 ) ) + 1 ) )

I would prefer to see a small function that given an icfg register and
an interrupt number, returns the appropriate IRQ_TYPE for it.

The rest is fine.


>  void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
>  {
>      const unsigned long mask = r;
> @@ -342,9 +346,37 @@ void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
>      unsigned long flags;
>      int i = 0;
>      struct vcpu *v_target;
> +#ifdef CONFIG_HAS_ACPI
> +    struct domain *d = v->domain;
> +    struct vgic_irq_rank *vr = vgic_get_rank(v, n);
> +    uint32_t tr;
> +    int ret;
> +#endif
>  
>      while ( (i = find_next_bit(&mask, 32, i)) < 32 ) {
>          irq = i + (32 * n);
> +#ifdef CONFIG_HAS_ACPI
> +        /* Set the irq type and route it to guest only for SPI and Dom0 */
> +        if( irq_access_permitted(d, irq) && is_hardware_domain(d) &&
> +            ( irq >= 32 ) && ( !acpi_disabled ) )
> +        {
> +            tr = vr->icfg[i >> 4];
> +
> +            if ( tr & VGIC_ICFG_MASK(i) )
> +                ret = irq_set_spi_type(irq, IRQ_TYPE_EDGE_BOTH);
> +            else
> +                ret = irq_set_spi_type(irq, IRQ_TYPE_LEVEL_MASK);
> +            if ( ret )
> +                printk(XENLOG_WARNING "The irq type is not correct\n");
> +
> +            vgic_reserve_virq(d, irq);
> +
> +            ret = route_irq_to_guest(d, irq, irq, NULL);
> +            if ( ret )
> +                printk(XENLOG_ERR "Unable to route IRQ %u to domain %u\n",
> +                       irq, d->domain_id);
> +        }
> +#endif
>          v_target = __vgic_get_target_vcpu(v, irq);
>          p = irq_to_pending(v_target, irq);
>          set_bit(GIC_IRQ_GUEST_ENABLED, &p->status);
> -- 
> 2.0.4
> 
>
diff mbox

Patch

diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index ee35683..902a16d 100644
--- a/xen/arch/arm/vgic.c
+++ b/xen/arch/arm/vgic.c
@@ -25,6 +25,8 @@ 
 #include <xen/irq.h>
 #include <xen/sched.h>
 #include <xen/perfc.h>
+#include <xen/iocap.h>
+#include <xen/acpi.h>
 
 #include <asm/current.h>
 
@@ -334,6 +336,8 @@  void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n)
     }
 }
 
+#define VGIC_ICFG_MASK(intr) ( 1 << ( ( 2 * ( intr % 16 ) ) + 1 ) )
+
 void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
 {
     const unsigned long mask = r;
@@ -342,9 +346,37 @@  void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
     unsigned long flags;
     int i = 0;
     struct vcpu *v_target;
+#ifdef CONFIG_HAS_ACPI
+    struct domain *d = v->domain;
+    struct vgic_irq_rank *vr = vgic_get_rank(v, n);
+    uint32_t tr;
+    int ret;
+#endif
 
     while ( (i = find_next_bit(&mask, 32, i)) < 32 ) {
         irq = i + (32 * n);
+#ifdef CONFIG_HAS_ACPI
+        /* Set the irq type and route it to guest only for SPI and Dom0 */
+        if( irq_access_permitted(d, irq) && is_hardware_domain(d) &&
+            ( irq >= 32 ) && ( !acpi_disabled ) )
+        {
+            tr = vr->icfg[i >> 4];
+
+            if ( tr & VGIC_ICFG_MASK(i) )
+                ret = irq_set_spi_type(irq, IRQ_TYPE_EDGE_BOTH);
+            else
+                ret = irq_set_spi_type(irq, IRQ_TYPE_LEVEL_MASK);
+            if ( ret )
+                printk(XENLOG_WARNING "The irq type is not correct\n");
+
+            vgic_reserve_virq(d, irq);
+
+            ret = route_irq_to_guest(d, irq, irq, NULL);
+            if ( ret )
+                printk(XENLOG_ERR "Unable to route IRQ %u to domain %u\n",
+                       irq, d->domain_id);
+        }
+#endif
         v_target = __vgic_get_target_vcpu(v, irq);
         p = irq_to_pending(v_target, irq);
         set_bit(GIC_IRQ_GUEST_ENABLED, &p->status);