All of lore.kernel.org
 help / color / mirror / Atom feed
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

  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: 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.