aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/virt/kvm/arm/vgic/vgic-mmio-v2.c
diff options
context:
space:
mode:
authorChristoffer Dall <cdall@linaro.org>2017-03-21 22:05:22 +0100
committerChristoffer Dall <cdall@linaro.org>2017-04-04 14:33:59 +0200
commit6d56111c92d247bb64301029fe88365aa4caf16e (patch)
tree0ceec9bfeae39452c020baa35b99f91d9e4bae76 /virt/kvm/arm/vgic/vgic-mmio-v2.c
parentKVM: arm64: Ensure LRs are clear when they should be (diff)
downloadwireguard-linux-6d56111c92d247bb64301029fe88365aa4caf16e.tar.xz
wireguard-linux-6d56111c92d247bb64301029fe88365aa4caf16e.zip
KVM: arm/arm64: vgic: Fix GICC_PMR uaccess on GICv3 and clarify ABI
As an oversight, for GICv2, we accidentally export the GICC_PMR register in the format of the GICH_VMCR.VMPriMask field in the lower 5 bits of a word, meaning that userspace must always use the lower 5 bits to communicate with the KVM device and must shift the value left by 3 places to obtain the actual priority mask level. Since GICv3 supports the full 8 bits of priority masking in the ICH_VMCR, we have to fix the value we export when emulating a GICv2 on top of a hardware GICv3 and exporting the emulated GICv2 state to userspace. Take the chance to clarify this aspect of the ABI. Reviewed-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <cdall@linaro.org>
Diffstat (limited to 'virt/kvm/arm/vgic/vgic-mmio-v2.c')
-rw-r--r--virt/kvm/arm/vgic/vgic-mmio-v2.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c
index a3ad7ff95c9b..0a4283ed9aa7 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v2.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c
@@ -229,7 +229,15 @@ static unsigned long vgic_mmio_read_vcpuif(struct kvm_vcpu *vcpu,
val = vmcr.ctlr;
break;
case GIC_CPU_PRIMASK:
- val = vmcr.pmr;
+ /*
+ * Our KVM_DEV_TYPE_ARM_VGIC_V2 device ABI exports the
+ * the PMR field as GICH_VMCR.VMPriMask rather than
+ * GICC_PMR.Priority, so we expose the upper five bits of
+ * priority mask to userspace using the lower bits in the
+ * unsigned long.
+ */
+ val = (vmcr.pmr & GICV_PMR_PRIORITY_MASK) >>
+ GICV_PMR_PRIORITY_SHIFT;
break;
case GIC_CPU_BINPOINT:
val = vmcr.bpr;
@@ -262,7 +270,15 @@ static void vgic_mmio_write_vcpuif(struct kvm_vcpu *vcpu,
vmcr.ctlr = val;
break;
case GIC_CPU_PRIMASK:
- vmcr.pmr = val;
+ /*
+ * Our KVM_DEV_TYPE_ARM_VGIC_V2 device ABI exports the
+ * the PMR field as GICH_VMCR.VMPriMask rather than
+ * GICC_PMR.Priority, so we expose the upper five bits of
+ * priority mask to userspace using the lower bits in the
+ * unsigned long.
+ */
+ vmcr.pmr = (val << GICV_PMR_PRIORITY_SHIFT) &
+ GICV_PMR_PRIORITY_MASK;
break;
case GIC_CPU_BINPOINT:
vmcr.bpr = val;