summaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorAndre Przywara <andre.przywara@arm.com>2015-01-13 12:02:13 +0000
committerChristoffer Dall <christoffer.dall@linaro.org>2015-01-20 18:25:33 +0100
commit4fa96afd94a9bb29135d6e2e8fdb527e58f4fd5c (patch)
treeaa982135e881964a54d5e6e7f85563393abefb3d /virt
parentac3d373564d9744068d867a0eb16da2ff8d5ee9d (diff)
downloadlinux-4fa96afd94a9bb29135d6e2e8fdb527e58f4fd5c.tar.bz2
arm/arm64: KVM: force alignment of VGIC dist/CPU/redist addresses
Although the GIC architecture requires us to map the MMIO regions only at page aligned addresses, we currently do not enforce this from the kernel side. Restrict any vGICv2 regions to be 4K aligned and any GICv3 regions to be 64K aligned. Document this requirement. Signed-off-by: Andre Przywara <andre.przywara@arm.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/arm/vgic.c16
1 files changed, 13 insertions, 3 deletions
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 184c6dbd5165..0cc6ab6005a0 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1683,6 +1683,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
struct vgic_dist *vgic = &kvm->arch.vgic;
int type_needed;
phys_addr_t *addr_ptr, block_size;
+ phys_addr_t alignment;
mutex_lock(&kvm->lock);
switch (type) {
@@ -1690,22 +1691,26 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
addr_ptr = &vgic->vgic_dist_base;
block_size = KVM_VGIC_V2_DIST_SIZE;
+ alignment = SZ_4K;
break;
case KVM_VGIC_V2_ADDR_TYPE_CPU:
type_needed = KVM_DEV_TYPE_ARM_VGIC_V2;
addr_ptr = &vgic->vgic_cpu_base;
block_size = KVM_VGIC_V2_CPU_SIZE;
+ alignment = SZ_4K;
break;
#ifdef CONFIG_ARM_GIC_V3
case KVM_VGIC_V3_ADDR_TYPE_DIST:
type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
addr_ptr = &vgic->vgic_dist_base;
block_size = KVM_VGIC_V3_DIST_SIZE;
+ alignment = SZ_64K;
break;
case KVM_VGIC_V3_ADDR_TYPE_REDIST:
type_needed = KVM_DEV_TYPE_ARM_VGIC_V3;
addr_ptr = &vgic->vgic_redist_base;
block_size = KVM_VGIC_V3_REDIST_SIZE;
+ alignment = SZ_64K;
break;
#endif
default:
@@ -1718,10 +1723,15 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
goto out;
}
- if (write)
- r = vgic_ioaddr_assign(kvm, addr_ptr, *addr, block_size);
- else
+ if (write) {
+ if (!IS_ALIGNED(*addr, alignment))
+ r = -EINVAL;
+ else
+ r = vgic_ioaddr_assign(kvm, addr_ptr, *addr,
+ block_size);
+ } else {
*addr = *addr_ptr;
+ }
out:
mutex_unlock(&kvm->lock);