[PATCH v3 39/55] KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_NR_IRQS
Christoffer Dall
christoffer.dall at linaro.org
Fri May 13 03:11:53 PDT 2016
On Fri, May 06, 2016 at 11:45:52AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger at linaro.org>
>
> This patch implements the KVM_DEV_ARM_VGIC_GRP_NR_IRQS group. This
> modality is supported by both VGIC V2 and V3 KVM device as will be
> other groups, hence the introduction of common helpers.
>
> Signed-off-by: Eric Auger <eric.auger at linaro.org>
> Signed-off-by: Andre Przywara <andre.przywara at arm.com>
> ---
> virt/kvm/arm/vgic/vgic-kvm-device.c | 83 +++++++++++++++++++++++++++++++++++--
> 1 file changed, 79 insertions(+), 4 deletions(-)
>
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index ff332f3..05ff925 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -15,9 +15,69 @@
> */
> #include <linux/kvm_host.h>
> #include <kvm/arm_vgic.h>
> +#include <linux/uaccess.h>
> +#include "vgic.h"
>
> /* common helpers */
>
> +static int vgic_set_common_attr(struct kvm_device *dev,
> + struct kvm_device_attr *attr)
> +{
> + switch (attr->group) {
> + case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
> + u32 __user *uaddr = (u32 __user *)(long)attr->addr;
> + u32 val;
> + int ret = 0;
> +
> + if (get_user(val, uaddr))
> + return -EFAULT;
> +
> + /*
> + * We require:
> + * - at least 32 SPIs on top of the 16 SGIs and 16 PPIs
> + * - at most 1024 interrupts
> + * - a multiple of 32 interrupts
> + */
> + if (val < (VGIC_NR_PRIVATE_IRQS + 32) ||
> + val > VGIC_MAX_RESERVED ||
> + (val & 31))
> + return -EINVAL;
> +
> + mutex_lock(&dev->kvm->lock);
> +
> + if (vgic_ready(dev->kvm) || dev->kvm->arch.vgic.nr_spis)
> + ret = -EBUSY;
> + else
> + dev->kvm->arch.vgic.nr_spis =
> + val - VGIC_NR_PRIVATE_IRQS;
> +
> + mutex_unlock(&dev->kvm->lock);
> +
> + return ret;
> + }
> + }
> +
> + return -ENXIO;
> +}
> +
> +static int vgic_get_common_attr(struct kvm_device *dev,
> + struct kvm_device_attr *attr)
> +{
> + int r = -ENXIO;
> +
> + switch (attr->group) {
> + case KVM_DEV_ARM_VGIC_GRP_NR_IRQS: {
> + u32 __user *uaddr = (u32 __user *)(long)attr->addr;
> +
> + r = put_user(dev->kvm->arch.vgic.nr_spis +
> + VGIC_NR_PRIVATE_IRQS, uaddr);
> + break;
> + }
> + }
> +
> + return r;
> +}
> +
> static int vgic_create(struct kvm_device *dev, u32 type)
> {
> return kvm_vgic_create(dev->kvm, type);
> @@ -49,18 +109,29 @@ void kvm_register_vgic_device(unsigned long type)
> static int vgic_v2_set_attr(struct kvm_device *dev,
> struct kvm_device_attr *attr)
> {
> - return -ENXIO;
> + int ret;
> +
> + ret = vgic_set_common_attr(dev, attr);
> + return ret;
> +
> }
>
> static int vgic_v2_get_attr(struct kvm_device *dev,
> struct kvm_device_attr *attr)
> {
> - return -ENXIO;
> + int ret;
> +
> + ret = vgic_get_common_attr(dev, attr);
> + return ret;
> }
>
> static int vgic_v2_has_attr(struct kvm_device *dev,
> struct kvm_device_attr *attr)
> {
> + switch (attr->group) {
> + case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
> + return 0;
> + }
> return -ENXIO;
> }
>
> @@ -80,18 +151,22 @@ struct kvm_device_ops kvm_arm_vgic_v2_ops = {
> static int vgic_v3_set_attr(struct kvm_device *dev,
> struct kvm_device_attr *attr)
> {
> - return -ENXIO;
> + return vgic_set_common_attr(dev, attr);
> }
>
> static int vgic_v3_get_attr(struct kvm_device *dev,
> struct kvm_device_attr *attr)
> {
> - return -ENXIO;
> + return vgic_get_common_attr(dev, attr);
> }
>
> static int vgic_v3_has_attr(struct kvm_device *dev,
> struct kvm_device_attr *attr)
> {
> + switch (attr->group) {
> + case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
> + return 0;
> + }
> return -ENXIO;
> }
>
> --
> 2.7.3
>
Reviewed-by: Christoffer Dall <christoffer.dall at linaro.org>
More information about the linux-arm-kernel
mailing list