diff options
author | Eric Auger <eric.auger@linaro.org> | 2015-12-21 17:34:52 +0100 |
---|---|---|
committer | Christoffer Dall <christoffer.dall@linaro.org> | 2016-05-20 15:40:02 +0200 |
commit | f94591e2e6fdca6e9a2cbf23e36a8803b4f605fe (patch) | |
tree | 9c8c530509ef85a77af1568fad11dcb46cdfb378 /virt/kvm/arm/vgic/vgic-mmio-v2.c | |
parent | e5c3029467cfa0acd89cfbd9cee1ae848e5eb8b0 (diff) | |
download | linux-f94591e2e6fdca6e9a2cbf23e36a8803b4f605fe.tar.bz2 |
KVM: arm/arm64: vgic-new: vgic_kvm_device: access to VGIC registers
This patch implements the switches for KVM_DEV_ARM_VGIC_GRP_DIST_REGS
and KVM_DEV_ARM_VGIC_GRP_CPU_REGS API which allows the userspace to
access VGIC registers.
Signed-off-by: Eric Auger <eric.auger@linaro.org>
Signed-off-by: Andre Przywara <andre.przywara@arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'virt/kvm/arm/vgic/vgic-mmio-v2.c')
-rw-r--r-- | virt/kvm/arm/vgic/vgic-mmio-v2.c | 38 |
1 files changed, 38 insertions, 0 deletions
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v2.c b/virt/kvm/arm/vgic/vgic-mmio-v2.c index 3925d4cbec62..71896900ad12 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v2.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v2.c @@ -258,3 +258,41 @@ unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev) return SZ_4K; } + +int vgic_v2_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr) +{ + int nr_irqs = dev->kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS; + const struct vgic_register_region *regions; + gpa_t addr; + int nr_regions, i, len; + + addr = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK; + + switch (attr->group) { + case KVM_DEV_ARM_VGIC_GRP_DIST_REGS: + regions = vgic_v2_dist_registers; + nr_regions = ARRAY_SIZE(vgic_v2_dist_registers); + break; + case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: + return -ENXIO; /* TODO: describe CPU i/f regs also */ + default: + return -ENXIO; + } + + /* We only support aligned 32-bit accesses. */ + if (addr & 3) + return -ENXIO; + + for (i = 0; i < nr_regions; i++) { + if (regions[i].bits_per_irq) + len = (regions[i].bits_per_irq * nr_irqs) / 8; + else + len = regions[i].len; + + if (regions[i].reg_offset <= addr && + regions[i].reg_offset + len > addr) + return 0; + } + + return -ENXIO; +} |