diff mbox

[v3,39/55] KVM: arm/arm64: vgic-new: vgic_kvm_device: KVM_DEV_ARM_VGIC_GRP_NR_IRQS

Message ID 1462531568-9799-40-git-send-email-andre.przywara@arm.com
State Superseded
Headers show

Commit Message

Andre Przywara May 6, 2016, 10:45 a.m. UTC
From: Eric Auger <eric.auger@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@linaro.org>

Signed-off-by: Andre Przywara <andre.przywara@arm.com>

---
 virt/kvm/arm/vgic/vgic-kvm-device.c | 83 +++++++++++++++++++++++++++++++++++--
 1 file changed, 79 insertions(+), 4 deletions(-)

-- 
2.7.3


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

Comments

Christoffer Dall May 13, 2016, 10:11 a.m. UTC | #1
On Fri, May 06, 2016 at 11:45:52AM +0100, Andre Przywara wrote:
> From: Eric Auger <eric.auger@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@linaro.org>

> Signed-off-by: Andre Przywara <andre.przywara@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@linaro.org>


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
diff mbox

Patch

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;
 }