Commit 15f9017c authored by Marc Zyngier's avatar Marc Zyngier

Merge branch kvm-arm64/vgic-ipa-checks into kvmarm-master/next

* kvm-arm64/vgic-ipa-checks:
  : .
  : Add extra checks to prevent ther various GIC regions to land
  : outside of the IPA space (and tests to verify that it works).
  : .
  KVM: arm64: selftests: Add init ITS device test
  KVM: arm64: selftests: Add test for legacy GICv3 REDIST base partially above IPA range
  KVM: arm64: selftests: Add tests for GIC redist/cpuif partially above IPA range
  KVM: arm64: selftests: Add some tests for GICv2 in vgic_init
  KVM: arm64: selftests: Make vgic_init/vm_gic_create version agnostic
  KVM: arm64: selftests: Make vgic_init gic version agnostic
  KVM: arm64: vgic: Drop vgic_check_ioaddr()
  KVM: arm64: vgic-v3: Check ITS region is not above the VM IPA size
  KVM: arm64: vgic-v2: Check cpu interface region is not above the VM IPA size
  KVM: arm64: vgic-v3: Check redist region is not above the VM IPA size
  kvm: arm64: vgic: Introduce vgic_check_iorange
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents 3864d17f 3e197f17
...@@ -2710,8 +2710,8 @@ static int vgic_its_set_attr(struct kvm_device *dev, ...@@ -2710,8 +2710,8 @@ static int vgic_its_set_attr(struct kvm_device *dev,
if (copy_from_user(&addr, uaddr, sizeof(addr))) if (copy_from_user(&addr, uaddr, sizeof(addr)))
return -EFAULT; return -EFAULT;
ret = vgic_check_ioaddr(dev->kvm, &its->vgic_its_base, ret = vgic_check_iorange(dev->kvm, its->vgic_its_base,
addr, SZ_64K); addr, SZ_64K, KVM_VGIC_V3_ITS_SIZE);
if (ret) if (ret)
return ret; return ret;
......
...@@ -14,17 +14,21 @@ ...@@ -14,17 +14,21 @@
/* common helpers */ /* common helpers */
int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr, int vgic_check_iorange(struct kvm *kvm, phys_addr_t ioaddr,
phys_addr_t addr, phys_addr_t alignment) phys_addr_t addr, phys_addr_t alignment,
phys_addr_t size)
{ {
if (addr & ~kvm_phys_mask(kvm)) if (!IS_VGIC_ADDR_UNDEF(ioaddr))
return -E2BIG; return -EEXIST;
if (!IS_ALIGNED(addr, alignment)) if (!IS_ALIGNED(addr, alignment) || !IS_ALIGNED(size, alignment))
return -EINVAL; return -EINVAL;
if (!IS_VGIC_ADDR_UNDEF(*ioaddr)) if (addr + size < addr)
return -EEXIST; return -EINVAL;
if (addr & ~kvm_phys_mask(kvm) || addr + size > kvm_phys_size(kvm))
return -E2BIG;
return 0; return 0;
} }
...@@ -57,7 +61,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write) ...@@ -57,7 +61,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
{ {
int r = 0; int r = 0;
struct vgic_dist *vgic = &kvm->arch.vgic; struct vgic_dist *vgic = &kvm->arch.vgic;
phys_addr_t *addr_ptr, alignment; phys_addr_t *addr_ptr, alignment, size;
u64 undef_value = VGIC_ADDR_UNDEF; u64 undef_value = VGIC_ADDR_UNDEF;
mutex_lock(&kvm->lock); mutex_lock(&kvm->lock);
...@@ -66,16 +70,19 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write) ...@@ -66,16 +70,19 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2); r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
addr_ptr = &vgic->vgic_dist_base; addr_ptr = &vgic->vgic_dist_base;
alignment = SZ_4K; alignment = SZ_4K;
size = KVM_VGIC_V2_DIST_SIZE;
break; break;
case KVM_VGIC_V2_ADDR_TYPE_CPU: case KVM_VGIC_V2_ADDR_TYPE_CPU:
r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2); r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V2);
addr_ptr = &vgic->vgic_cpu_base; addr_ptr = &vgic->vgic_cpu_base;
alignment = SZ_4K; alignment = SZ_4K;
size = KVM_VGIC_V2_CPU_SIZE;
break; break;
case KVM_VGIC_V3_ADDR_TYPE_DIST: case KVM_VGIC_V3_ADDR_TYPE_DIST:
r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V3); r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V3);
addr_ptr = &vgic->vgic_dist_base; addr_ptr = &vgic->vgic_dist_base;
alignment = SZ_64K; alignment = SZ_64K;
size = KVM_VGIC_V3_DIST_SIZE;
break; break;
case KVM_VGIC_V3_ADDR_TYPE_REDIST: { case KVM_VGIC_V3_ADDR_TYPE_REDIST: {
struct vgic_redist_region *rdreg; struct vgic_redist_region *rdreg;
...@@ -140,7 +147,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write) ...@@ -140,7 +147,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
goto out; goto out;
if (write) { if (write) {
r = vgic_check_ioaddr(kvm, addr_ptr, *addr, alignment); r = vgic_check_iorange(kvm, *addr_ptr, *addr, alignment, size);
if (!r) if (!r)
*addr_ptr = *addr; *addr_ptr = *addr;
} else { } else {
......
...@@ -796,7 +796,9 @@ static int vgic_v3_alloc_redist_region(struct kvm *kvm, uint32_t index, ...@@ -796,7 +796,9 @@ static int vgic_v3_alloc_redist_region(struct kvm *kvm, uint32_t index,
struct vgic_dist *d = &kvm->arch.vgic; struct vgic_dist *d = &kvm->arch.vgic;
struct vgic_redist_region *rdreg; struct vgic_redist_region *rdreg;
struct list_head *rd_regions = &d->rd_regions; struct list_head *rd_regions = &d->rd_regions;
size_t size = count * KVM_VGIC_V3_REDIST_SIZE; int nr_vcpus = atomic_read(&kvm->online_vcpus);
size_t size = count ? count * KVM_VGIC_V3_REDIST_SIZE
: nr_vcpus * KVM_VGIC_V3_REDIST_SIZE;
int ret; int ret;
/* cross the end of memory ? */ /* cross the end of memory ? */
...@@ -840,7 +842,7 @@ static int vgic_v3_alloc_redist_region(struct kvm *kvm, uint32_t index, ...@@ -840,7 +842,7 @@ static int vgic_v3_alloc_redist_region(struct kvm *kvm, uint32_t index,
rdreg->base = VGIC_ADDR_UNDEF; rdreg->base = VGIC_ADDR_UNDEF;
ret = vgic_check_ioaddr(kvm, &rdreg->base, base, SZ_64K); ret = vgic_check_iorange(kvm, rdreg->base, base, SZ_64K, size);
if (ret) if (ret)
goto free; goto free;
......
...@@ -483,8 +483,10 @@ bool vgic_v3_check_base(struct kvm *kvm) ...@@ -483,8 +483,10 @@ bool vgic_v3_check_base(struct kvm *kvm)
return false; return false;
list_for_each_entry(rdreg, &d->rd_regions, list) { list_for_each_entry(rdreg, &d->rd_regions, list) {
if (rdreg->base + vgic_v3_rd_region_size(kvm, rdreg) < size_t sz = vgic_v3_rd_region_size(kvm, rdreg);
rdreg->base)
if (vgic_check_iorange(kvm, VGIC_ADDR_UNDEF,
rdreg->base, SZ_64K, sz))
return false; return false;
} }
......
...@@ -172,8 +172,9 @@ void vgic_kick_vcpus(struct kvm *kvm); ...@@ -172,8 +172,9 @@ void vgic_kick_vcpus(struct kvm *kvm);
void vgic_irq_handle_resampling(struct vgic_irq *irq, void vgic_irq_handle_resampling(struct vgic_irq *irq,
bool lr_deactivated, bool lr_pending); bool lr_deactivated, bool lr_pending);
int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr, int vgic_check_iorange(struct kvm *kvm, phys_addr_t ioaddr,
phys_addr_t addr, phys_addr_t alignment); phys_addr_t addr, phys_addr_t alignment,
phys_addr_t size);
void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu); void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu);
void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr); void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment