diff mbox

[Xen-devel,01/10] xen/arm: vgic-v3: Correctly set GICD_TYPER.IDbits

Message ID 1421684957-29884-2-git-send-email-julien.grall@linaro.org
State Superseded, archived
Headers show

Commit Message

Julien Grall Jan. 19, 2015, 4:29 p.m. UTC
From Linux 3.19, the GICv3 drivers is using GICD_TYPER.IDbits to check
the validity of the hardware interrupt number.

The field IDBits in the register GICD_TYPER is used to know the number of
interrupt identifiers (SPI, PPIs, SGIs, LPIs) supported by GIC Stream Protocol
Interface.

This field contains the number of interrupt identifier bits minus one.

Signed-off-by: Julien Grall <julien.grall@linaro.org>

---
    This patch should be backported to Xen 4.5. Without it any Linux
    kernel > 3.19 won't boot as a Xen domain.

    I'm wondering if we should add a release note for this bug.
---
 xen/arch/arm/vgic-v3.c            | 16 ++++++++++++++++
 xen/include/asm-arm/gic_v3_defs.h |  4 ++++
 2 files changed, 20 insertions(+)

Comments

Julien Grall Jan. 20, 2015, 5:16 p.m. UTC | #1
Hi Ian,

On 20/01/15 15:34, Ian Campbell wrote:
> On Mon, 2015-01-19 at 16:29 +0000, Julien Grall wrote:
>> +        unsigned int order;
>> +
>>          if ( dabt.size != DABT_WORD ) goto bad_width;
>>          /* No secure world support for guests. */
>>          *r = (((v->domain->max_vcpus << 5) & GICD_TYPE_CPUS ) |
>>                ((v->domain->arch.vgic.nr_lines / 32) & GICD_TYPE_LINES));
>> +
>> +        /*
>> +         * Calculate number of interrupt identifier bits supported by
>> +         * the GIC Stream Protocol Interface
>> +         */
>> +        irqs--;
>> +        for ( order = 0; irqs; order++ )
>> +            irqs >>= 1;
> 
> This is some variant on fls(). See get_bitmask_order() or
> get_count_order() for an example of use, possibly even one you could
> call.

get_count_order sounds the best function to use. I will give a try.

Regards,
diff mbox

Patch

diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index c738ca9..8420c09 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -671,11 +671,27 @@  static int vgic_v3_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
         vgic_unlock(v);
         return 1;
     case GICD_TYPER:
+    {
+        unsigned int irqs = v->domain->arch.vgic.nr_lines + 32;
+        unsigned int order;
+
         if ( dabt.size != DABT_WORD ) goto bad_width;
         /* No secure world support for guests. */
         *r = (((v->domain->max_vcpus << 5) & GICD_TYPE_CPUS ) |
               ((v->domain->arch.vgic.nr_lines / 32) & GICD_TYPE_LINES));
+
+        /*
+         * Calculate number of interrupt identifier bits supported by
+         * the GIC Stream Protocol Interface
+         */
+        irqs--;
+        for ( order = 0; irqs; order++ )
+            irqs >>= 1;
+
+        *r |= ((order - 1) << GICD_TYPE_ID_BITS_SHIFT) & GICD_TYPE_ID_BITS_MASK;
+
         return 1;
+    }
     case GICD_STATUSR:
         /*
          *  Optional, Not implemented for now.
diff --git a/xen/include/asm-arm/gic_v3_defs.h b/xen/include/asm-arm/gic_v3_defs.h
index 13adb53..6214663 100644
--- a/xen/include/asm-arm/gic_v3_defs.h
+++ b/xen/include/asm-arm/gic_v3_defs.h
@@ -18,6 +18,10 @@ 
 #ifndef __ASM_ARM_GIC_V3_DEFS_H__
 #define __ASM_ARM_GIC_V3_DEFS_H__
 
+/* Additional bits in GICD_TYPER defined by GICv3 */
+#define GICD_TYPE_ID_BITS_SHIFT 19
+#define GICD_TYPE_ID_BITS_MASK  (0x1f << GICD_TYPE_ID_BITS_SHIFT)
+
 /*
  * Additional registers defined in GIC v3.
  * Common GICD registers are defined in gic.h