From: Marc Zyngier <marc.zyngier@arm.com>
To: Andre Przywara <andre.przywara@arm.com>
Cc: Julien Grall <julien.grall@arm.com>,
kvmarm@lists.cs.columbia.edu,
linux-arm-kernel@lists.infradead.org,
Dave Martin <dave.martin@arm.com>
Subject: Re: [PATCH v2] KVM: arm: VGIC: properly initialise private IRQ affinity
Date: Thu, 22 Aug 2019 20:29:54 +0100 [thread overview]
Message-ID: <20190822202954.48239e0e@why> (raw)
In-Reply-To: <20190822170510.167076-1-andre.przywara@arm.com>
On Thu, 22 Aug 2019 18:05:10 +0100
Andre Przywara <andre.przywara@arm.com> wrote:
> At the moment we initialise the target *mask* of a virtual IRQ to the
> VCPU it belongs to, even though this mask is only defined for GICv2 and
> quickly runs out of bits for many GICv3 guests.
> This behaviour triggers an UBSAN complaint for more than 32 VCPUs:
> ------
> [ 5659.462377] UBSAN: Undefined behaviour in virt/kvm/arm/vgic/vgic-init.c:223:21
> [ 5659.471689] shift exponent 32 is too large for 32-bit type 'unsigned int'
> ------
> Also for GICv3 guests the reporting of TARGET in the "vgic-state" debugfs
> dump is wrong, due to this very same problem.
>
> Because there is no requirement to create the VGIC device before the
> VCPUs (and QEMU actually does it the other way round), we can't safely
> initialise mpidr or targets in kvm_vgic_vcpu_init(). But since we touch
> every private IRQ for each VCPU anyway later (in vgic_init()), we can
> just move the initialisation of those fields into there, where we
> definitely know the VGIC type.
>
> On the way make sure we really have either a VGICv2 or a VGICv3 device,
> since the former checks was just checking for "VGICv3 or not", silently
> ignoring the uninitialised case.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> Reported-by: Dave Martin <dave.martin@arm.com>
> ---
> Hi,
>
> tested with 4, 8 and 33 VCPUs with kvmtool and QEMU, on a GICv2 and a
> GICv3 machine.
> Also briefly tested localhost migration on the GICv3 machine w/ 33
> VCPUs, although I think all IRQs are group 1.
>
> Cheers,
> Andre
>
> virt/kvm/arm/vgic/vgic-init.c | 28 ++++++++++++++++++----------
> 1 file changed, 18 insertions(+), 10 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
> index 80127ca9269f..413fb6a5525c 100644
> --- a/virt/kvm/arm/vgic/vgic-init.c
> +++ b/virt/kvm/arm/vgic/vgic-init.c
> @@ -8,6 +8,7 @@
> #include <linux/cpu.h>
> #include <linux/kvm_host.h>
> #include <kvm/arm_vgic.h>
> +#include <asm/kvm_emulate.h>
> #include <asm/kvm_mmu.h>
> #include "vgic.h"
>
> @@ -165,12 +166,17 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
> irq->vcpu = NULL;
> irq->target_vcpu = vcpu0;
> kref_init(&irq->refcount);
> - if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) {
> + switch (dist->vgic_model) {
> + case KVM_DEV_TYPE_ARM_VGIC_V2:
> irq->targets = 0;
> irq->group = 0;
> - } else {
> + break;
> + case KVM_DEV_TYPE_ARM_VGIC_V3:
> irq->mpidr = 0;
> irq->group = 1;
> + break;
> + default:
> + BUG_ON(1);
> }
> }
> return 0;
> @@ -210,7 +216,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
> irq->intid = i;
> irq->vcpu = NULL;
> irq->target_vcpu = vcpu;
> - irq->targets = 1U << vcpu->vcpu_id;
> kref_init(&irq->refcount);
> if (vgic_irq_is_sgi(i)) {
> /* SGIs */
> @@ -220,11 +225,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
> /* PPIs */
> irq->config = VGIC_CONFIG_LEVEL;
> }
> -
> - if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
> - irq->group = 1;
> - else
> - irq->group = 0;
> }
>
> if (!irqchip_in_kernel(vcpu->kvm))
> @@ -287,10 +287,18 @@ int vgic_init(struct kvm *kvm)
>
> for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
> struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
> - if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
> + switch (dist->vgic_model) {
> + case KVM_DEV_TYPE_ARM_VGIC_V3:
> irq->group = 1;
> - else
> + irq->mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
> + break;
> + case KVM_DEV_TYPE_ARM_VGIC_V2:
> irq->group = 0;
> + irq->targets = 1U << idx;
> + break;
> + default:
> + BUG_ON(1);
> + }
> }
> }
>
Please drop the BUG_ON()s. If something is unexpected, just fail to
init the guest, but don't kill the box.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm
WARNING: multiple messages have this Message-ID (diff)
From: Marc Zyngier <marc.zyngier@arm.com>
To: Andre Przywara <andre.przywara@arm.com>
Cc: Julien Grall <julien.grall@arm.com>,
kvmarm@lists.cs.columbia.edu,
Christoffer Dall <christoffer.dall@arm.com>,
linux-arm-kernel@lists.infradead.org,
Dave Martin <dave.martin@arm.com>
Subject: Re: [PATCH v2] KVM: arm: VGIC: properly initialise private IRQ affinity
Date: Thu, 22 Aug 2019 20:29:54 +0100 [thread overview]
Message-ID: <20190822202954.48239e0e@why> (raw)
In-Reply-To: <20190822170510.167076-1-andre.przywara@arm.com>
On Thu, 22 Aug 2019 18:05:10 +0100
Andre Przywara <andre.przywara@arm.com> wrote:
> At the moment we initialise the target *mask* of a virtual IRQ to the
> VCPU it belongs to, even though this mask is only defined for GICv2 and
> quickly runs out of bits for many GICv3 guests.
> This behaviour triggers an UBSAN complaint for more than 32 VCPUs:
> ------
> [ 5659.462377] UBSAN: Undefined behaviour in virt/kvm/arm/vgic/vgic-init.c:223:21
> [ 5659.471689] shift exponent 32 is too large for 32-bit type 'unsigned int'
> ------
> Also for GICv3 guests the reporting of TARGET in the "vgic-state" debugfs
> dump is wrong, due to this very same problem.
>
> Because there is no requirement to create the VGIC device before the
> VCPUs (and QEMU actually does it the other way round), we can't safely
> initialise mpidr or targets in kvm_vgic_vcpu_init(). But since we touch
> every private IRQ for each VCPU anyway later (in vgic_init()), we can
> just move the initialisation of those fields into there, where we
> definitely know the VGIC type.
>
> On the way make sure we really have either a VGICv2 or a VGICv3 device,
> since the former checks was just checking for "VGICv3 or not", silently
> ignoring the uninitialised case.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> Reported-by: Dave Martin <dave.martin@arm.com>
> ---
> Hi,
>
> tested with 4, 8 and 33 VCPUs with kvmtool and QEMU, on a GICv2 and a
> GICv3 machine.
> Also briefly tested localhost migration on the GICv3 machine w/ 33
> VCPUs, although I think all IRQs are group 1.
>
> Cheers,
> Andre
>
> virt/kvm/arm/vgic/vgic-init.c | 28 ++++++++++++++++++----------
> 1 file changed, 18 insertions(+), 10 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
> index 80127ca9269f..413fb6a5525c 100644
> --- a/virt/kvm/arm/vgic/vgic-init.c
> +++ b/virt/kvm/arm/vgic/vgic-init.c
> @@ -8,6 +8,7 @@
> #include <linux/cpu.h>
> #include <linux/kvm_host.h>
> #include <kvm/arm_vgic.h>
> +#include <asm/kvm_emulate.h>
> #include <asm/kvm_mmu.h>
> #include "vgic.h"
>
> @@ -165,12 +166,17 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
> irq->vcpu = NULL;
> irq->target_vcpu = vcpu0;
> kref_init(&irq->refcount);
> - if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V2) {
> + switch (dist->vgic_model) {
> + case KVM_DEV_TYPE_ARM_VGIC_V2:
> irq->targets = 0;
> irq->group = 0;
> - } else {
> + break;
> + case KVM_DEV_TYPE_ARM_VGIC_V3:
> irq->mpidr = 0;
> irq->group = 1;
> + break;
> + default:
> + BUG_ON(1);
> }
> }
> return 0;
> @@ -210,7 +216,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
> irq->intid = i;
> irq->vcpu = NULL;
> irq->target_vcpu = vcpu;
> - irq->targets = 1U << vcpu->vcpu_id;
> kref_init(&irq->refcount);
> if (vgic_irq_is_sgi(i)) {
> /* SGIs */
> @@ -220,11 +225,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
> /* PPIs */
> irq->config = VGIC_CONFIG_LEVEL;
> }
> -
> - if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
> - irq->group = 1;
> - else
> - irq->group = 0;
> }
>
> if (!irqchip_in_kernel(vcpu->kvm))
> @@ -287,10 +287,18 @@ int vgic_init(struct kvm *kvm)
>
> for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
> struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
> - if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
> + switch (dist->vgic_model) {
> + case KVM_DEV_TYPE_ARM_VGIC_V3:
> irq->group = 1;
> - else
> + irq->mpidr = kvm_vcpu_get_mpidr_aff(vcpu);
> + break;
> + case KVM_DEV_TYPE_ARM_VGIC_V2:
> irq->group = 0;
> + irq->targets = 1U << idx;
> + break;
> + default:
> + BUG_ON(1);
> + }
> }
> }
>
Please drop the BUG_ON()s. If something is unexpected, just fail to
init the guest, but don't kill the box.
Thanks,
M.
--
Without deviation from the norm, progress is not possible.
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
next prev parent reply other threads:[~2019-08-22 19:30 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-08-22 17:05 [PATCH v2] KVM: arm: VGIC: properly initialise private IRQ affinity Andre Przywara
2019-08-22 17:05 ` Andre Przywara
2019-08-22 19:29 ` Marc Zyngier [this message]
2019-08-22 19:29 ` Marc Zyngier
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=20190822202954.48239e0e@why \
--to=marc.zyngier@arm.com \
--cc=andre.przywara@arm.com \
--cc=dave.martin@arm.com \
--cc=julien.grall@arm.com \
--cc=kvmarm@lists.cs.columbia.edu \
--cc=linux-arm-kernel@lists.infradead.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.