From: Marc Zyngier <marc.zyngier@arm.com> To: Christoffer Dall <christoffer.dall@linaro.org>, Peter Maydell <peter.maydell@linaro.org>, Eric Auger <eric.auger@redhat.com>, Andre Przywara <andre.przywara@arm.com> Cc: linux-arm-kernel@lists.infradead.org, kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org Subject: [PATCH 1/2] KVM: arm/arm64: vgic-v2: Expose the correct GICC_PMR values to userspace Date: Thu, 16 Mar 2017 11:45:34 +0000 [thread overview] Message-ID: <20170316114535.25233-2-marc.zyngier@arm.com> (raw) In-Reply-To: <20170316114535.25233-1-marc.zyngier@arm.com> We allow userspace to save/restore the GICC_PMR values in order to allow migration. This value is extracted from GICH_PMCR, where it occupies a 5 bit field. But the canonical PMR is an 8 bit value and we fail to shift the virtual priority, resulting in a non-sensical value being reported to userspace. Fixing it once and for all would be ideal, but that would break migration of guest from old to new kernels. We thus introduce a new GICv2 attribute (KVM_DEV_ARM_VGIC_CTRL_CANONICAL_PMR) that allows userspace to register its interest for the one true representation of PMR. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> --- arch/arm/include/uapi/asm/kvm.h | 4 ++-- arch/arm64/include/uapi/asm/kvm.h | 4 ++-- include/kvm/arm_vgic.h | 5 +++++ virt/kvm/arm/vgic/vgic-kvm-device.c | 5 +++++ virt/kvm/arm/vgic/vgic-v2.c | 16 ++++++++++++++++ 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index 6ebd3e6a1fd1..2852836221c0 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -189,6 +189,8 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff) #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3 #define KVM_DEV_ARM_VGIC_GRP_CTRL 4 +#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 +#define KVM_DEV_ARM_VGIC_CTRL_CANONICAL_PMR 1 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7 @@ -198,8 +200,6 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff #define VGIC_LEVEL_INFO_LINE_LEVEL 0 -#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 - /* KVM_IRQ_LINE irq field index values */ #define KVM_ARM_IRQ_TYPE_SHIFT 24 #define KVM_ARM_IRQ_TYPE_MASK 0xff diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index c2860358ae3e..e649dc753759 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -209,6 +209,8 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff) #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3 #define KVM_DEV_ARM_VGIC_GRP_CTRL 4 +#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 +#define KVM_DEV_ARM_VGIC_CTRL_CANONICAL_PMR 1 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7 @@ -218,8 +220,6 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff #define VGIC_LEVEL_INFO_LINE_LEVEL 0 -#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 - /* Device Control API on vcpu fd */ #define KVM_ARM_VCPU_PMU_V3_CTRL 0 #define KVM_ARM_VCPU_PMU_V3_IRQ 0 diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index b72dd2ad5f44..af46ec3c427d 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -170,6 +170,8 @@ struct vgic_its { struct vgic_state_iter; +#define VGIC_QUIRK_CANONICAL_PMR 0 + struct vgic_dist { bool in_kernel; bool ready; @@ -218,6 +220,9 @@ struct vgic_dist { struct list_head lpi_list_head; int lpi_list_count; + /* Quirks driven by userspace requests */ + unsigned long quirks; + /* used by vgic-debug */ struct vgic_state_iter *iter; }; diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c index d181d2baee9c..b4935cd49c24 100644 --- a/virt/kvm/arm/vgic/vgic-kvm-device.c +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c @@ -160,6 +160,10 @@ static int vgic_set_common_attr(struct kvm_device *dev, r = vgic_init(dev->kvm); mutex_unlock(&dev->kvm->lock); return r; + case KVM_DEV_ARM_VGIC_CTRL_CANONICAL_PMR: + set_bit(VGIC_QUIRK_CANONICAL_PMR, + &dev->kvm->arch.vgic.quirks); + break; } break; } @@ -408,6 +412,7 @@ static int vgic_v2_has_attr(struct kvm_device *dev, case KVM_DEV_ARM_VGIC_GRP_CTRL: switch (attr->attr) { case KVM_DEV_ARM_VGIC_CTRL_INIT: + case KVM_DEV_ARM_VGIC_CTRL_CANONICAL_PMR: return 0; } } diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c index b834ecdf3225..87f9dd1eaf1c 100644 --- a/virt/kvm/arm/vgic/vgic-v2.c +++ b/virt/kvm/arm/vgic/vgic-v2.c @@ -191,6 +191,15 @@ void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) GICH_VMCR_ALIAS_BINPOINT_MASK; vmcr |= (vmcrp->bpr << GICH_VMCR_BINPOINT_SHIFT) & GICH_VMCR_BINPOINT_MASK; + + /* + * If userspace is happy to deal with the normal PMR range (8 + * bits), we need to strip the 3 lowest bits so that we fit + * into the 5 bits that GICv2 gives us on the virtual side. + */ + if (test_bit(VGIC_QUIRK_CANONICAL_PMR, &vcpu->kvm->arch.vgic.quirks)) + vmcrp->pmr >>= 3; + vmcr |= (vmcrp->pmr << GICH_VMCR_PRIMASK_SHIFT) & GICH_VMCR_PRIMASK_MASK; @@ -209,6 +218,13 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) GICH_VMCR_BINPOINT_SHIFT; vmcrp->pmr = (vmcr & GICH_VMCR_PRIMASK_MASK) >> GICH_VMCR_PRIMASK_SHIFT; + /* + * If userspace is happy to deal with the normal PMR range (8 + * bits), we need to shift the reduced range (5 bits) to + * expose it as if it was a normal value. + */ + if (test_bit(VGIC_QUIRK_CANONICAL_PMR, &vcpu->kvm->arch.vgic.quirks)) + vmcrp->pmr <<= 3; } void vgic_v2_enable(struct kvm_vcpu *vcpu) -- 2.11.0
WARNING: multiple messages have this Message-ID (diff)
From: marc.zyngier@arm.com (Marc Zyngier) To: linux-arm-kernel@lists.infradead.org Subject: [PATCH 1/2] KVM: arm/arm64: vgic-v2: Expose the correct GICC_PMR values to userspace Date: Thu, 16 Mar 2017 11:45:34 +0000 [thread overview] Message-ID: <20170316114535.25233-2-marc.zyngier@arm.com> (raw) In-Reply-To: <20170316114535.25233-1-marc.zyngier@arm.com> We allow userspace to save/restore the GICC_PMR values in order to allow migration. This value is extracted from GICH_PMCR, where it occupies a 5 bit field. But the canonical PMR is an 8 bit value and we fail to shift the virtual priority, resulting in a non-sensical value being reported to userspace. Fixing it once and for all would be ideal, but that would break migration of guest from old to new kernels. We thus introduce a new GICv2 attribute (KVM_DEV_ARM_VGIC_CTRL_CANONICAL_PMR) that allows userspace to register its interest for the one true representation of PMR. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> --- arch/arm/include/uapi/asm/kvm.h | 4 ++-- arch/arm64/include/uapi/asm/kvm.h | 4 ++-- include/kvm/arm_vgic.h | 5 +++++ virt/kvm/arm/vgic/vgic-kvm-device.c | 5 +++++ virt/kvm/arm/vgic/vgic-v2.c | 16 ++++++++++++++++ 5 files changed, 30 insertions(+), 4 deletions(-) diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h index 6ebd3e6a1fd1..2852836221c0 100644 --- a/arch/arm/include/uapi/asm/kvm.h +++ b/arch/arm/include/uapi/asm/kvm.h @@ -189,6 +189,8 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff) #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3 #define KVM_DEV_ARM_VGIC_GRP_CTRL 4 +#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 +#define KVM_DEV_ARM_VGIC_CTRL_CANONICAL_PMR 1 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7 @@ -198,8 +200,6 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff #define VGIC_LEVEL_INFO_LINE_LEVEL 0 -#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 - /* KVM_IRQ_LINE irq field index values */ #define KVM_ARM_IRQ_TYPE_SHIFT 24 #define KVM_ARM_IRQ_TYPE_MASK 0xff diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h index c2860358ae3e..e649dc753759 100644 --- a/arch/arm64/include/uapi/asm/kvm.h +++ b/arch/arm64/include/uapi/asm/kvm.h @@ -209,6 +209,8 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff) #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3 #define KVM_DEV_ARM_VGIC_GRP_CTRL 4 +#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 +#define KVM_DEV_ARM_VGIC_CTRL_CANONICAL_PMR 1 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5 #define KVM_DEV_ARM_VGIC_GRP_CPU_SYSREGS 6 #define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7 @@ -218,8 +220,6 @@ struct kvm_arch_memory_slot { #define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff #define VGIC_LEVEL_INFO_LINE_LEVEL 0 -#define KVM_DEV_ARM_VGIC_CTRL_INIT 0 - /* Device Control API on vcpu fd */ #define KVM_ARM_VCPU_PMU_V3_CTRL 0 #define KVM_ARM_VCPU_PMU_V3_IRQ 0 diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index b72dd2ad5f44..af46ec3c427d 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -170,6 +170,8 @@ struct vgic_its { struct vgic_state_iter; +#define VGIC_QUIRK_CANONICAL_PMR 0 + struct vgic_dist { bool in_kernel; bool ready; @@ -218,6 +220,9 @@ struct vgic_dist { struct list_head lpi_list_head; int lpi_list_count; + /* Quirks driven by userspace requests */ + unsigned long quirks; + /* used by vgic-debug */ struct vgic_state_iter *iter; }; diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c index d181d2baee9c..b4935cd49c24 100644 --- a/virt/kvm/arm/vgic/vgic-kvm-device.c +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c @@ -160,6 +160,10 @@ static int vgic_set_common_attr(struct kvm_device *dev, r = vgic_init(dev->kvm); mutex_unlock(&dev->kvm->lock); return r; + case KVM_DEV_ARM_VGIC_CTRL_CANONICAL_PMR: + set_bit(VGIC_QUIRK_CANONICAL_PMR, + &dev->kvm->arch.vgic.quirks); + break; } break; } @@ -408,6 +412,7 @@ static int vgic_v2_has_attr(struct kvm_device *dev, case KVM_DEV_ARM_VGIC_GRP_CTRL: switch (attr->attr) { case KVM_DEV_ARM_VGIC_CTRL_INIT: + case KVM_DEV_ARM_VGIC_CTRL_CANONICAL_PMR: return 0; } } diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c index b834ecdf3225..87f9dd1eaf1c 100644 --- a/virt/kvm/arm/vgic/vgic-v2.c +++ b/virt/kvm/arm/vgic/vgic-v2.c @@ -191,6 +191,15 @@ void vgic_v2_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) GICH_VMCR_ALIAS_BINPOINT_MASK; vmcr |= (vmcrp->bpr << GICH_VMCR_BINPOINT_SHIFT) & GICH_VMCR_BINPOINT_MASK; + + /* + * If userspace is happy to deal with the normal PMR range (8 + * bits), we need to strip the 3 lowest bits so that we fit + * into the 5 bits that GICv2 gives us on the virtual side. + */ + if (test_bit(VGIC_QUIRK_CANONICAL_PMR, &vcpu->kvm->arch.vgic.quirks)) + vmcrp->pmr >>= 3; + vmcr |= (vmcrp->pmr << GICH_VMCR_PRIMASK_SHIFT) & GICH_VMCR_PRIMASK_MASK; @@ -209,6 +218,13 @@ void vgic_v2_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcrp) GICH_VMCR_BINPOINT_SHIFT; vmcrp->pmr = (vmcr & GICH_VMCR_PRIMASK_MASK) >> GICH_VMCR_PRIMASK_SHIFT; + /* + * If userspace is happy to deal with the normal PMR range (8 + * bits), we need to shift the reduced range (5 bits) to + * expose it as if it was a normal value. + */ + if (test_bit(VGIC_QUIRK_CANONICAL_PMR, &vcpu->kvm->arch.vgic.quirks)) + vmcrp->pmr <<= 3; } void vgic_v2_enable(struct kvm_vcpu *vcpu) -- 2.11.0
next prev parent reply other threads:[~2017-03-16 11:46 UTC|newest] Thread overview: 18+ messages / expand[flat|nested] mbox.gz Atom feed top 2017-03-16 11:45 [PATCH 0/2] KVM: arm/arm64: vgic: Workaround GICC_PMR misreporting Marc Zyngier 2017-03-16 11:45 ` Marc Zyngier 2017-03-16 11:45 ` Marc Zyngier [this message] 2017-03-16 11:45 ` [PATCH 1/2] KVM: arm/arm64: vgic-v2: Expose the correct GICC_PMR values to userspace Marc Zyngier 2017-03-20 14:24 ` Christoffer Dall 2017-03-20 14:24 ` Christoffer Dall 2017-03-20 15:12 ` Marc Zyngier 2017-03-20 15:12 ` Marc Zyngier 2017-03-20 18:31 ` Christoffer Dall 2017-03-20 18:31 ` Christoffer Dall 2017-03-20 18:55 ` Christoffer Dall 2017-03-20 18:55 ` Christoffer Dall 2017-03-20 19:03 ` Marc Zyngier 2017-03-20 19:03 ` Marc Zyngier 2017-03-16 11:45 ` [PATCH 2/2] KVM: arm/arm64: vgic-v3: Format PMR to mimic the GICv2 behaviour Marc Zyngier 2017-03-16 11:45 ` Marc Zyngier 2017-03-20 14:24 ` Christoffer Dall 2017-03-20 14:24 ` Christoffer Dall
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=20170316114535.25233-2-marc.zyngier@arm.com \ --to=marc.zyngier@arm.com \ --cc=andre.przywara@arm.com \ --cc=christoffer.dall@linaro.org \ --cc=eric.auger@redhat.com \ --cc=kvm@vger.kernel.org \ --cc=kvmarm@lists.cs.columbia.edu \ --cc=linux-arm-kernel@lists.infradead.org \ --cc=peter.maydell@linaro.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: linkBe 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.