[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v1 5/8] xen/arm: vgic: Optimize the way to store GICD_IPRIORITYR in the rank



On Fri, 2015-09-25 at 15:51 +0100, Julien Grall wrote:
> Xen is currently directly storing the value of register GICD_IPRIORITYR

"of the GICD_... register"

> in the rank. This makes emulation of the register access very simple
> but makes the code to get the priority for a given IRQ more complex.
> 
> While the priority of an IRQ is retrieved everytime an IRQ is injected

"every time".

> to the guest, the access to register occurs less often.
> 
> So the data structure should be optimized for the most common case
> rather than the inverse.
> 
> This patch introduces the usage of an array to store the priority for
> every interrupt in the rank. This will make the code to get the priority
> very quick. The emulation code will now have to generate the
> GICD_PRIORITYR
> register for read access and split it to store in a convenient way.
> 
> Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>
> ---
> 
> The real reason is I'd like to drop vgic_byte_* helpers in favors of more
> generic access helper. Although it would make the code to retrieve the
> priority more complex. So reworking the way to get the priority was the
> best solution.
> 
>     Changes in v2:
>         - Patch added
> ---
>  xen/arch/arm/vgic-v2.c     | 24 ++++++++++++++----------
>  xen/arch/arm/vgic-v3.c     | 27 ++++++++++++++++-----------
>  xen/arch/arm/vgic.c        | 46
> ++++++++++++++++++++++++++++++++++++++++++++++
>  xen/include/asm-arm/vgic.h | 18 +++++++++++++++++-
>  4 files changed, 93 insertions(+), 22 deletions(-)
> 
> diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
> index 47f9da9..23d1982 100644
> --- a/xen/arch/arm/vgic-v2.c
> +++ b/xen/arch/arm/vgic-v2.c
> @@ -139,8 +139,8 @@ static int vgic_v2_distr_mmio_read(struct vcpu *v, 
> mmio_info_t *info,
>          if ( rank == NULL) goto read_as_zero;
>  
>          vgic_lock_rank(v, rank, flags);
> -        *r = rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR,
> -                                            DABT_WORD)];
> +        /* Recreate the IPRIORITYR register */
> +        *r = vgic_generate_ipriorityr(rank, gicd_reg - GICD_IPRIORITYR);
>          if ( dabt.size == DABT_BYTE )
>              *r = vgic_byte_read(*r, gicd_reg);
>          vgic_unlock_rank(v, rank, flags);
> @@ -400,18 +400,25 @@ static int vgic_v2_distr_mmio_write(struct vcpu *v, 
> mmio_info_t *info,
>      }
>  
>      case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
> +    {
> +        uint32_t ipriorityr;
> +
>          if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto 
> bad_width;
>          rank = vgic_rank_offset(v, 8, gicd_reg - GICD_IPRIORITYR, DABT_WORD);
>          if ( rank == NULL) goto write_ignore;
>          vgic_lock_rank(v, rank, flags);
>          if ( dabt.size == DABT_WORD )
> -            rank->ipriority[REG_RANK_INDEX(8, gicd_reg - GICD_IPRIORITYR,
> -                                           DABT_WORD)] = r;
> +            ipriorityr = r;
>          else
> -            vgic_byte_write(&rank->ipriority[REG_RANK_INDEX(8,
> -                        gicd_reg - GICD_IPRIORITYR, DABT_WORD)], r, 
> gicd_reg);
> +        {
> +            ipriorityr = vgic_generate_ipriorityr(rank,
> +                                                  gicd_reg - 
> GICD_IPRIORITYR);
> +            vgic_byte_write(&ipriorityr, r, gicd_reg);
> +        }
> +        vgic_store_ipriorityr(rank, gicd_reg - GICD_IPRIORITYR, ipriorityr);
>          vgic_unlock_rank(v, rank, flags);
>          return 1;
> +    }
>  
>      case GICD_ICFGR: /* SGIs */
>          goto write_ignore_32;
> @@ -516,14 +523,11 @@ static struct vcpu *vgic_v2_get_target_vcpu(struct vcpu 
> *v, unsigned int irq)
>  
>  static int vgic_v2_get_irq_priority(struct vcpu *v, unsigned int irq)
>  {
> -    int priority;
>      struct vgic_irq_rank *rank = vgic_rank_irq(v, irq);
>  
>      ASSERT(spin_is_locked(&rank->lock));
> -    priority = vgic_byte_read(rank->ipriority[REG_RANK_INDEX(8,
> -                                              irq, DABT_WORD)], irq & 0x3);
>  
> -    return priority;
> +    return rank->priority[irq & INTERRUPT_RANK_MASK];
>  }
>  
>  static int vgic_v2_vcpu_init(struct vcpu *v)
> diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
> index c013200..2787507 100644
> --- a/xen/arch/arm/vgic-v3.c
> +++ b/xen/arch/arm/vgic-v3.c
> @@ -430,18 +430,26 @@ static int __vgic_v3_distr_common_mmio_write(const char 
> *name, struct vcpu *v,
>          return 0;
>  
>      case GICD_IPRIORITYR ... GICD_IPRIORITYRN:
> +    {
> +        uint32_t ipriorityr;
> +
>          if ( dabt.size != DABT_BYTE && dabt.size != DABT_WORD ) goto 
> bad_width;
>          rank = vgic_rank_offset(v, 8, reg - GICD_IPRIORITYR, DABT_WORD);
> -        if ( rank == NULL ) goto write_ignore;
> +        if ( rank == NULL) goto write_ignore;
> +
>          vgic_lock_rank(v, rank, flags);
>          if ( dabt.size == DABT_WORD )
> -            rank->ipriority[REG_RANK_INDEX(8, reg - GICD_IPRIORITYR,
> -                                           DABT_WORD)] = r;
> +            ipriorityr = r;
>          else
> -            vgic_byte_write(&rank->ipriority[REG_RANK_INDEX(8,
> -                       reg - GICD_IPRIORITYR, DABT_WORD)], r, reg);
> +        {
> +            ipriorityr = vgic_generate_ipriorityr(rank, reg - 
> GICD_IPRIORITYR);
> +            vgic_byte_write(&ipriorityr, r, reg);
> +        }
> +        vgic_store_ipriorityr(rank, reg - GICD_IPRIORITYR, ipriorityr);

Given the underlying change to the datastructure I think you should instead
supply a helper to set the priority of a given IRQ and use that for the
DABT_BYTE case.

For the DABT_WORD case your existing store helper would become 4 calls to
the byte helper.

That would be better than generating the full 32-bit value,  masking in the
updated byte and then deconstructing the word again.

> diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
> index a6835a8..50ad360 100644
> --- a/xen/arch/arm/vgic.c
> +++ b/xen/arch/arm/vgic.c
> @@ -61,6 +61,52 @@ struct vgic_irq_rank *vgic_rank_irq(struct vcpu *v, 
> unsigned int irq)
>      return vgic_get_rank(v, rank);
>  }
>  
> +#define NR_PRIORITY_PER_REG 4U
> +#define NR_BIT_PER_PRIORITY 8U
> +
> +/*
> + * Generate the associated IPRIORITYR register based on an offset in the 
> rank.
> + * Note the offset will be round down to match a real HW register.

"rounded".

>  struct vgic_irq_rank {
>      spinlock_t lock; /* Covers access to all other members of this struct */
>      uint32_t ienable;
>      uint32_t icfg[2];
> -    uint32_t ipriority[8];
> +
> +    /*
> +     * It's more convenient to store one priority per interrupt than
> +     * the register IPRIORITYR itself
> +     */
> +    uint8_t priority[32];

Does:

    union {
        uint32_t ipriorityr[8];
        uint8_t priority[32];
    }

Get us the best of both worlds, or are we stymied by endianess?

Ian.

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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.