All of lore.kernel.org
 help / color / mirror / Atom feed
From: Julien Grall <julien.grall@citrix.com>
To: Chen Baozi <cbz@baozis.org>, xen-devel@lists.xenproject.org
Cc: Julien Grall <julien.grall@citrix.com>,
	Chen Baozi <baozich@gmail.com>,
	Ian Campbell <ian.campbell@citrix.com>
Subject: Re: [PATCH V4 4/8] xen/arm: Use cpumask_t type for vcpu_mask in vgic_to_sgi
Date: Fri, 29 May 2015 16:20:32 +0100	[thread overview]
Message-ID: <556883C0.7040702@citrix.com> (raw)
In-Reply-To: <1432808109-31466-5-git-send-email-cbz@baozis.org>

Hi Chen,

On 28/05/15 11:15, Chen Baozi wrote:
> From: Chen Baozi <baozich@gmail.com>
> 
> Use cpumask_t instead of unsigned long which can only express 64 cpus at
> the most. Add the {gicv2|gicv3}_sgir_to_cpumask in corresponding vGICs
> to translate GICD_SGIR/ICC_SGI1R_EL1 to vcpu_mask for vgic_to_sgi.

This patch does more than using cpumask_t. It's also add AFF1 support
for GICv3. This should at least be mentioned in the patch (and commit
message). But I would prefer a separate patch to add this feature.

Furthermore, cpumask_t is based on NR_CPUS. There is not relation
between NR_CPUS and MAX_VIRT_CPUS so you need to add a BUILD_BUG_ON in
order to catch wrong configuration.

> 
> Signed-off-by: Chen Baozi <baozich@gmail.com>
> ---
>  xen/arch/arm/vgic-v2.c     | 16 ++++++++++++++--
>  xen/arch/arm/vgic-v3.c     | 19 ++++++++++++++++---
>  xen/arch/arm/vgic.c        | 15 +++++++--------
>  xen/include/asm-arm/vgic.h |  2 +-
>  4 files changed, 38 insertions(+), 14 deletions(-)
> 
> diff --git a/xen/arch/arm/vgic-v2.c b/xen/arch/arm/vgic-v2.c
> index 3be1a51..2dbe371 100644
> --- a/xen/arch/arm/vgic-v2.c
> +++ b/xen/arch/arm/vgic-v2.c
> @@ -33,6 +33,17 @@
>  #include <asm/gic.h>
>  #include <asm/vgic.h>
>  
> +static void gicv2_sgir_to_cpumask(cpumask_t *cpumask, const register_t sgir)

static inline

> +{
> +    unsigned long target_list;
> +    int cpuid;
> +
> +    target_list = ((sgir & GICD_SGI_TARGET_MASK) >> GICD_SGI_TARGET_SHIFT);
> +    for_each_set_bit( cpuid, &target_list, 8 )
> +        cpumask_set_cpu(cpuid, cpumask);

The SGI code is called very often by the guest so we need an optimized code.
As there is already a loop later I'd like to avoid another here.

I think the loop can be replaced with:

bitmap_copy(cpumask_bits(cpumask), &target_list, 8);

The operation will be in O(1).

Also please use a define rather than the hardcoded value 8.

> +
> +}
> +
>  static int vgic_v2_distr_mmio_read(struct vcpu *v, mmio_info_t *info)
>  {
>      struct hsr_dabt dabt = info->dabt;
> @@ -201,11 +212,12 @@ static int vgic_v2_to_sgi(struct vcpu *v, register_t sgir)
>      int virq;
>      int irqmode;
>      enum gic_sgi_mode sgi_mode;
> -    unsigned long vcpu_mask = 0;
> +    cpumask_t vcpu_mask;
>  
> +    cpumask_clear(&vcpu_mask);
>      irqmode = (sgir & GICD_SGI_TARGET_LIST_MASK) >> GICD_SGI_TARGET_LIST_SHIFT;
>      virq = (sgir & GICD_SGI_INTID_MASK);
> -    vcpu_mask = (sgir & GICD_SGI_TARGET_MASK) >> GICD_SGI_TARGET_SHIFT;
> +    gicv2_sgir_to_cpumask(&vcpu_mask, sgir);

This is only necessary to call when the SGI target a list of VCPUs
(GICD_SGI_TARGET_LIST_VAL).

>  
>      /* Map GIC sgi value to enum value */
>      switch ( irqmode )
> diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
> index ef9a71a..0da031c 100644
> --- a/xen/arch/arm/vgic-v3.c
> +++ b/xen/arch/arm/vgic-v3.c
> @@ -972,17 +972,30 @@ write_ignore:
>      return 1;
>  }
>  
> +static void gicv3_sgir_to_cpumask(cpumask_t *cpumask, const register_t sgir)
> +{
> +    int target, cpuid;
> +    unsigned long target_mask = sgir & ICH_SGI_TARGETLIST_MASK;
> +
> +    for_each_set_bit( target, &target_mask, 16 )
> +    {
> +        /* XXX: We assume that only AFF1 is used in ICC_SGI1R_EL1. */
> +        cpuid = target + ((sgir >> 16) & 0xff) * 16;

Please use define rather than constant.

> +        cpumask_set_cpu(cpuid, cpumask);
> +    }

Same remark as above, the loop can be avoided.

Furthermore you need to validate the AFF1. A malicious guest can decide
to pass AFF1 >= 16 which will give a CPU higher than 128 and potentially
allow the guest to do a stack overflow in Xen.

> +}
> +
>  static int vgic_v3_to_sgi(struct vcpu *v, register_t sgir)
>  {
>      int virq;
>      int irqmode;
>      enum gic_sgi_mode sgi_mode;
> -    unsigned long vcpu_mask = 0;
> +    cpumask_t vcpu_mask;
>  
> +    cpumask_clear(&vcpu_mask);
>      irqmode = (sgir >> ICH_SGI_IRQMODE_SHIFT) & ICH_SGI_IRQMODE_MASK;
>      virq = (sgir >> ICH_SGI_IRQ_SHIFT ) & ICH_SGI_IRQ_MASK;
> -    /* SGI's are injected at Rdist level 0. ignoring affinity 1, 2, 3 */
> -    vcpu_mask = sgir & ICH_SGI_TARGETLIST_MASK;
> +    gicv3_sgir_to_cpumask(&vcpu_mask, sgir);

It's only necessary when the SGI targets a list of VCPU
(ICH_SGI_TARGET_LIST).

>  
>      /* Map GIC sgi value to enum value */
>      switch ( irqmode )
> diff --git a/xen/arch/arm/vgic.c b/xen/arch/arm/vgic.c
> index 7b387b7..4bf8486 100644
> --- a/xen/arch/arm/vgic.c
> +++ b/xen/arch/arm/vgic.c
> @@ -318,9 +318,8 @@ void vgic_enable_irqs(struct vcpu *v, uint32_t r, int n)
>      }
>  }
>  
> -/* TODO: unsigned long is used to fit vcpu_mask.*/
>  int vgic_to_sgi(struct vcpu *v, register_t sgir, enum gic_sgi_mode irqmode, int virq,
> -                unsigned long vcpu_mask)
> +                cpumask_t vcpu_mask)

You need to pass a pointer here, otherwise you will copy all the
cpumask_t everytime which is very expensive.

>  {
>      struct domain *d = v->domain;
>      int vcpuid;

The BUG_ON below can be removed. Keeping here is a call to a potential
unwanted crash of Xen by the guest.

> @@ -341,12 +340,12 @@ int vgic_to_sgi(struct vcpu *v, register_t sgir, enum gic_sgi_mode irqmode, int

>          break;
>      case SGI_TARGET_SELF:
> @@ -355,8 +354,8 @@ int vgic_to_sgi(struct vcpu *v, register_t sgir, enum gic_sgi_mode irqmode, int
>           * SGI_TARGET_SELF mode. So Force vcpu_mask to 0
>           */
>          perfc_incr(vgic_sgi_self);
> -        vcpu_mask = 0;
> -        set_bit(current->vcpu_id, &vcpu_mask);
> +        cpumask_clear(&vcpu_mask);
> +        cpumask_set_cpu(current->vcpu_id, &vcpu_mask);
>          break;
>      default:
>          gprintk(XENLOG_WARNING,
> @@ -365,12 +364,12 @@ int vgic_to_sgi(struct vcpu *v, register_t sgir, enum gic_sgi_mode irqmode, int
>          return 0;
>      }
>  
> -    for_each_set_bit( vcpuid, &vcpu_mask, d->max_vcpus )
> +    for_each_cpu( vcpuid, &vcpu_mask )

Is there any potential performance impact? You are moving from a loop of
d->max_vcpus to 128 (and potentially more).

>      {
>          if ( d->vcpu[vcpuid] != NULL && !is_vcpu_online(d->vcpu[vcpuid]) )
>          {
>              gprintk(XENLOG_WARNING, "VGIC: write r=%"PRIregister" \
> -                    vcpu_mask=%lx, wrong CPUTargetList\n", sgir, vcpu_mask);
> +                    , wrong CPUTargetList\n", sgir);
>              continue;
>          }

Regards,

-- 
Julien Grall

  reply	other threads:[~2015-05-29 15:21 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-28 10:15 [PATCH V4 0/8] Support more than 8 vcpus on arm64 with GICv3 Chen Baozi
2015-05-28 10:15 ` [PATCH V4 1/8] xen/arm: gic-v3: Increase the size of GICR in address space for guest Chen Baozi
2015-05-28 10:15 ` [PATCH V4 2/8] xen/arm: Add functions of mapping between vCPUID and virtual affinity Chen Baozi
2015-05-29 14:27   ` Julien Grall
2015-05-28 10:15 ` [PATCH V4 3/8] xen/arm: Use the new functions for vCPUID/vaffinity transformation Chen Baozi
2015-05-29 14:34   ` Julien Grall
2015-05-28 10:15 ` [PATCH V4 4/8] xen/arm: Use cpumask_t type for vcpu_mask in vgic_to_sgi Chen Baozi
2015-05-29 15:20   ` Julien Grall [this message]
2015-05-28 10:15 ` [PATCH V4 5/8] tools/libxl: Set 'reg' of cpu node equal to MPIDR affinity for domU Chen Baozi
2015-05-29 15:44   ` Julien Grall
2015-05-29 15:55     ` Ian Campbell
2015-05-29 16:08       ` Julien Grall
2015-05-30  2:08         ` Chen Baozi
2015-05-30  2:27           ` Chen Baozi
2015-05-28 10:15 ` [PATCH V4 6/8] xen/arm: Set 'reg' of cpu node for dom0 to match MPIDR's affinity Chen Baozi
2015-05-29 15:49   ` Julien Grall
2015-05-30  2:10     ` Chen Baozi
2015-05-28 10:15 ` [PATCH V4 7/8] xen/arm64: increase MAX_VIRT_CPUS to 128 on arm64 Chen Baozi
2015-05-29 15:51   ` Julien Grall
2015-05-29 16:20     ` Julien Grall
2015-05-29 16:41       ` Andrew Cooper
2015-05-29 16:45         ` Julien Grall
2015-05-29 16:49           ` Andrew Cooper
2015-05-28 10:15 ` [PATCH V4 8/8] xen/arm: make domain_max_vcpus return value according to vGIC version Chen Baozi
2015-05-28 10:17   ` Andrew Cooper
2015-05-29 16:18   ` Julien Grall

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=556883C0.7040702@citrix.com \
    --to=julien.grall@citrix.com \
    --cc=baozich@gmail.com \
    --cc=cbz@baozis.org \
    --cc=ian.campbell@citrix.com \
    --cc=xen-devel@lists.xenproject.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.