diff mbox

[Xen-devel,v5,16/22] arm/acpi: Configure SPI interrupt type and route to Dom0 dynamically

Message ID 1457072152-16128-17-git-send-email-zhaoshenglong@huawei.com
State Superseded
Headers show

Commit Message

Shannon Zhao March 4, 2016, 6:15 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>
---
v5: add a small function to get the irq type from ICFG
---
 xen/arch/arm/vgic.c | 38 ++++++++++++++++++++++++++++++++++++++
 1 file changed, 38 insertions(+)

Comments

Shannon Zhao March 4, 2016, 3:16 p.m. UTC | #1
On 2016年03月04日 19:26, Stefano Stabellini wrote:
> On Fri, 4 Mar 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>
>> > ---
>> > v5: add a small function to get the irq type from ICFG
>> > ---
>> >  xen/arch/arm/vgic.c | 38 ++++++++++++++++++++++++++++++++++++++
>> >  1 file changed, 38 insertions(+)
>> > 
>> > diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
>> > index ee35683..52378a3 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,21 @@ void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n)
>> >      }
>> >  }
>> >  
>> > +#ifdef CONFIG_ACPI
>> > +#define VGIC_ICFG_MASK(intr) ( 1 << ( ( 2 * ( intr % 16 ) ) + 1 ) )
>                   remove spaces: ^      ^                   ^       ^
> 
>> > +static unsigned int get_the_irq_type(struct vcpu *v, int n, int index)
> static inline
> 
> 
>> > +{
>> > +    struct vgic_irq_rank *vr = vgic_get_rank(v, n);
>> > +    uint32_t tr = vr->icfg[index >> 4];
>> > +
>> > +    if ( tr & VGIC_ICFG_MASK(index) )
>> > +        return IRQ_TYPE_EDGE_BOTH;
>> > +    else
>> > +        return IRQ_TYPE_LEVEL_MASK;
>> > +}
>> > +#endif
>> > +
>> >  void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
>> >  {
>> >      const unsigned long mask = r;
>> > @@ -342,9 +359,30 @@ void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
>> >      unsigned long flags;
>> >      int i = 0;
>> >      struct vcpu *v_target;
>> > +#ifdef CONFIG_ACPI
>> > +    struct domain *d = v->domain;
>> > +    int ret;
>> > +#endif
>> >  
>> >      while ( (i = find_next_bit(&mask, 32, i)) < 32 ) {
>> >          irq = i + (32 * n);
>> > +#ifdef CONFIG_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 ) )
> Is there a reason why we need to have this code inside an ifdef? It
> looks like we can remove all ifdefs from this patch.
> 
> 
Ah, right! Will remove it.

Thanks,
diff mbox

Patch

diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
index ee35683..52378a3 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,21 @@  void vgic_disable_irqs(struct vcpu *v, uint32_t r, int n)
     }
 }
 
+#ifdef CONFIG_ACPI
+#define VGIC_ICFG_MASK(intr) ( 1 << ( ( 2 * ( intr % 16 ) ) + 1 ) )
+
+static unsigned int get_the_irq_type(struct vcpu *v, int n, int index)
+{
+    struct vgic_irq_rank *vr = vgic_get_rank(v, n);
+    uint32_t tr = vr->icfg[index >> 4];
+
+    if ( tr & VGIC_ICFG_MASK(index) )
+        return IRQ_TYPE_EDGE_BOTH;
+    else
+        return IRQ_TYPE_LEVEL_MASK;
+}
+#endif
+
 void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
 {
     const unsigned long mask = r;
@@ -342,9 +359,30 @@  void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
     unsigned long flags;
     int i = 0;
     struct vcpu *v_target;
+#ifdef CONFIG_ACPI
+    struct domain *d = v->domain;
+    int ret;
+#endif
 
     while ( (i = find_next_bit(&mask, 32, i)) < 32 ) {
         irq = i + (32 * n);
+#ifdef CONFIG_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 ) )
+        {
+            ret = irq_set_spi_type(irq, get_the_irq_type(v, n, i));
+            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);