diff mbox

[v10,7/8] arm/arm64: vgic: Implement KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO ioctl

Message ID 1480576187-5012-8-git-send-email-vijay.kilari@gmail.com
State New
Headers show

Commit Message

Vijay Kilari Dec. 1, 2016, 7:09 a.m. UTC
From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>


Userspace requires to store and restore of line_level for
level triggered interrupts using ioctl KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO.

Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>

---
 arch/arm/include/uapi/asm/kvm.h     |  7 ++++++
 arch/arm64/include/uapi/asm/kvm.h   |  6 +++++
 virt/kvm/arm/vgic/vgic-kvm-device.c | 45 +++++++++++++++++++++++++++++++++++-
 virt/kvm/arm/vgic/vgic-mmio-v3.c    | 11 +++++++++
 virt/kvm/arm/vgic/vgic-mmio.c       | 46 +++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-mmio.h       |  5 ++++
 virt/kvm/arm/vgic/vgic.h            |  2 ++
 7 files changed, 121 insertions(+), 1 deletion(-)

-- 
1.9.1


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

Comments

Eric Auger Dec. 16, 2016, 12:07 p.m. UTC | #1
Hi Vijaya,

On 01/12/2016 08:09, vijay.kilari@gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>

> 

> Userspace requires to store and restore of line_level for

> level triggered interrupts using ioctl KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO.

> 

> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>

> ---

>  arch/arm/include/uapi/asm/kvm.h     |  7 ++++++

>  arch/arm64/include/uapi/asm/kvm.h   |  6 +++++

>  virt/kvm/arm/vgic/vgic-kvm-device.c | 45 +++++++++++++++++++++++++++++++++++-

>  virt/kvm/arm/vgic/vgic-mmio-v3.c    | 11 +++++++++

>  virt/kvm/arm/vgic/vgic-mmio.c       | 46 +++++++++++++++++++++++++++++++++++++

>  virt/kvm/arm/vgic/vgic-mmio.h       |  5 ++++

>  virt/kvm/arm/vgic/vgic.h            |  2 ++

>  7 files changed, 121 insertions(+), 1 deletion(-)

> 

> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h

> index 98658d9d..f347779 100644

> --- a/arch/arm/include/uapi/asm/kvm.h

> +++ b/arch/arm/include/uapi/asm/kvm.h

> @@ -191,6 +191,13 @@ struct kvm_arch_memory_slot {

>  #define KVM_DEV_ARM_VGIC_GRP_CTRL       4

>  #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5

>  #define KVM_DEV_ARM_VGIC_CPU_SYSREGS    6

> +#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7

> +#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT	10

> +#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \

> +			(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)

> +#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK	0x3ff

> +#define VGIC_LEVEL_INFO_LINE_LEVEL	0

> +

>  #define   KVM_DEV_ARM_VGIC_CTRL_INIT    0

>  

>  /* KVM_IRQ_LINE irq field index values */

> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h

> index 91c7137..4100f8c 100644

> --- a/arch/arm64/include/uapi/asm/kvm.h

> +++ b/arch/arm64/include/uapi/asm/kvm.h

> @@ -211,6 +211,12 @@ struct kvm_arch_memory_slot {

>  #define KVM_DEV_ARM_VGIC_GRP_CTRL	4

>  #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5

>  #define KVM_DEV_ARM_VGIC_CPU_SYSREGS    6

> +#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7

> +#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT	10

> +#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \

> +			(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)

> +#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK	0x3ff

> +#define VGIC_LEVEL_INFO_LINE_LEVEL	0

>  

>  #define   KVM_DEV_ARM_VGIC_CTRL_INIT	0

>  

> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c

> index b6266fe..d5f7197 100644

> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c

> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c

> @@ -510,6 +510,21 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,

>  						  regid, reg);

>  		break;

>  	}

> +	case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {

> +		unsigned int info, intid;

> +

> +		info = (attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>

> +			KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT;

> +		if (info == VGIC_LEVEL_INFO_LINE_LEVEL) {

> +			intid = attr->attr &

> +				KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK;

> +			ret = vgic_v3_line_level_info_uaccess(vcpu, is_write,

> +							      intid, reg);

> +		} else {

> +			ret = -EINVAL;

> +		}

> +		break;

> +	}

>  	default:

>  		ret = -EINVAL;

>  		break;

> @@ -552,6 +567,17 @@ static int vgic_v3_set_attr(struct kvm_device *dev,

>  

>  		return vgic_v3_attr_regs_access(dev, attr, &reg, true);

>  	}

> +	case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {

> +		u32 __user *uaddr = (u32 __user *)(long)attr->addr;

> +		u64 reg;

> +		u32 tmp32;

> +

> +		if (get_user(tmp32, uaddr))

> +			return -EFAULT;

> +

> +		reg = tmp32;

> +		return vgic_v3_attr_regs_access(dev, attr, &reg, true);

> +	}

>  	}

>  	return -ENXIO;

>  }

> @@ -587,8 +613,18 @@ static int vgic_v3_get_attr(struct kvm_device *dev,

>  			return ret;

>  		return put_user(reg, uaddr);

>  	}

> -	}

> +	case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {

> +		u32 __user *uaddr = (u32 __user *)(long)attr->addr;

> +		u64 reg;

> +		u32 tmp32;

>  

> +		ret = vgic_v3_attr_regs_access(dev, attr, &reg, false);

> +		if (ret)

> +			return ret;

> +		tmp32 = reg;

> +		return put_user(tmp32, uaddr);

> +	}

> +	}

>  	return -ENXIO;

>  }

>  

> @@ -609,6 +645,13 @@ static int vgic_v3_has_attr(struct kvm_device *dev,

>  		return vgic_v3_has_attr_regs(dev, attr);

>  	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:

>  		return 0;

> +	case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {

> +		if (((attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>

> +		      KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT) ==

> +		      VGIC_LEVEL_INFO_LINE_LEVEL)

> +			return 0;

> +		break;

> +	}

>  	case KVM_DEV_ARM_VGIC_GRP_CTRL:

>  		switch (attr->attr) {

>  		case KVM_DEV_ARM_VGIC_CTRL_INIT:

> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c

> index 51439c9..9491d72 100644

> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c

> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c

> @@ -809,3 +809,14 @@ int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write,

>  		return vgic_uaccess(vcpu, &rd_dev, is_write,

>  				    offset, val);

>  }

> +

> +int vgic_v3_line_level_info_uaccess(struct kvm_vcpu *vcpu, bool is_write,

> +				    u32 intid, u64 *val)

> +{

I don't see anyone checking vINTID is multiple of 32 as emphasized in
Documentation/virtual/kvm/devices/arm-vgic-v3.txt
> +	if (is_write)

> +		vgic_write_irq_line_level_info(vcpu, intid, *val);

> +	else

> +		*val = vgic_read_irq_line_level_info(vcpu, intid);

> +

> +	return 0;

> +}

> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c

> index f81e0e5..28fef92b 100644

> --- a/virt/kvm/arm/vgic/vgic-mmio.c

> +++ b/virt/kvm/arm/vgic/vgic-mmio.c

> @@ -371,6 +371,52 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,

>  	}

>  }

>  

> +u64 vgic_read_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid)

> +{

> +	int i;

> +	u64 val = 0;

> +

> +	for (i = 0; i < 32; i++) {

> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);

> +

> +		if (irq->line_level)

> +			val |= (1U << i);

what about SGIs and higher ID than the number of interrupts supported.
Spec says RAZ/WI.
> +

> +		vgic_put_irq(vcpu->kvm, irq);

> +	}

> +

> +	return val;

> +}

> +

> +void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,

> +				    const u64 val)

> +{

> +	int i;

> +

> +	for (i = 0; i < 32; i++) {

> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);

> +

same as above.
> +		spin_lock(&irq->irq_lock);

> +		if (val & (1U << i)) {

> +			if (irq->config == VGIC_CONFIG_LEVEL) {

> +				irq->line_level = true;

> +				irq->pending = true;

> +				vgic_queue_irq_unlock(vcpu->kvm, irq);

> +			} else {

> +				spin_unlock(&irq->irq_lock);

> +			}

> +		} else {

> +			if (irq->config == VGIC_CONFIG_EDGE ||

can't we just ignore VGIC_CONFIG_EDGE case for which line_level is not
modeled?
> +			    (irq->config == VGIC_CONFIG_LEVEL &&

> +			    !irq->soft_pending))

> +				irq->line_level = false;

To me the line level does not depend on the soft_pending bit. The
pending state depends on both.

Thanks

Eric
> +			spin_unlock(&irq->irq_lock);

> +		}

> +

> +		vgic_put_irq(vcpu->kvm, irq);

> +	}

> +}

> +

>  static int match_region(const void *key, const void *elt)

>  {

>  	const unsigned int offset = (unsigned long)key;

> diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h

> index 1cc7faf..b9423b4 100644

> --- a/virt/kvm/arm/vgic/vgic-mmio.h

> +++ b/virt/kvm/arm/vgic/vgic-mmio.h

> @@ -181,6 +181,11 @@ int vgic_validate_mmio_region_addr(struct kvm_device *dev,

>  				   const struct vgic_register_region *regions,

>  				   int nr_regions, gpa_t addr);

>  

> +u64 vgic_read_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid);

> +

> +void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,

> +				    const u64 val);

> +

>  unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);

>  

>  unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev);

> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h

> index eac272c..60d4350 100644

> --- a/virt/kvm/arm/vgic/vgic.h

> +++ b/virt/kvm/arm/vgic/vgic.h

> @@ -144,6 +144,8 @@ int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write,

>  			 u64 id, u64 *val);

>  int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,

>  				u64 *reg);

> +int vgic_v3_line_level_info_uaccess(struct kvm_vcpu *vcpu, bool is_write,

> +				    u32 intid, u64 *val);

>  int kvm_register_vgic_device(unsigned long type);

>  void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);

>  void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);

> 


_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Peter Maydell Dec. 16, 2016, 12:44 p.m. UTC | #2
On 16 December 2016 at 12:07, Auger Eric <eric.auger@redhat.com> wrote:
> Hi Vijaya,

>

> On 01/12/2016 08:09, vijay.kilari@gmail.com wrote:

>> +void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,

>> +                                 const u64 val)

>> +{

>> +     int i;

>> +

>> +     for (i = 0; i < 32; i++) {

>> +             struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);

>> +

> same as above.

>> +             spin_lock(&irq->irq_lock);

>> +             if (val & (1U << i)) {

>> +                     if (irq->config == VGIC_CONFIG_LEVEL) {

>> +                             irq->line_level = true;

>> +                             irq->pending = true;

>> +                             vgic_queue_irq_unlock(vcpu->kvm, irq);

>> +                     } else {

>> +                             spin_unlock(&irq->irq_lock);

>> +                     }

>> +             } else {

>> +                     if (irq->config == VGIC_CONFIG_EDGE ||

> can't we just ignore VGIC_CONFIG_EDGE case for which line_level is not

> modeled?

>> +                         (irq->config == VGIC_CONFIG_LEVEL &&

>> +                         !irq->soft_pending))

>> +                             irq->line_level = false;

> To me the line level does not depend on the soft_pending bit. The

> pending state depends on both.


Without having looked at the details, it seems surprising to
me that the implementation of "set line level to X" is not
"set irq->line_level to X; figure out consequences and update
other state as necessary"...

thanks
-- PMM

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Christoffer Dall Jan. 20, 2017, 7:53 p.m. UTC | #3
On Thu, Dec 01, 2016 at 12:39:46PM +0530, vijay.kilari@gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>

> 

> Userspace requires to store and restore of line_level for

> level triggered interrupts using ioctl KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO.

> 

> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>

> ---

>  arch/arm/include/uapi/asm/kvm.h     |  7 ++++++

>  arch/arm64/include/uapi/asm/kvm.h   |  6 +++++

>  virt/kvm/arm/vgic/vgic-kvm-device.c | 45 +++++++++++++++++++++++++++++++++++-

>  virt/kvm/arm/vgic/vgic-mmio-v3.c    | 11 +++++++++

>  virt/kvm/arm/vgic/vgic-mmio.c       | 46 +++++++++++++++++++++++++++++++++++++

>  virt/kvm/arm/vgic/vgic-mmio.h       |  5 ++++

>  virt/kvm/arm/vgic/vgic.h            |  2 ++

>  7 files changed, 121 insertions(+), 1 deletion(-)

> 

> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h

> index 98658d9d..f347779 100644

> --- a/arch/arm/include/uapi/asm/kvm.h

> +++ b/arch/arm/include/uapi/asm/kvm.h

> @@ -191,6 +191,13 @@ struct kvm_arch_memory_slot {

>  #define KVM_DEV_ARM_VGIC_GRP_CTRL       4

>  #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5

>  #define KVM_DEV_ARM_VGIC_CPU_SYSREGS    6

> +#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7

> +#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT	10

> +#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \

> +			(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)

> +#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK	0x3ff

> +#define VGIC_LEVEL_INFO_LINE_LEVEL	0

> +

>  #define   KVM_DEV_ARM_VGIC_CTRL_INIT    0

>  

>  /* KVM_IRQ_LINE irq field index values */

> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h

> index 91c7137..4100f8c 100644

> --- a/arch/arm64/include/uapi/asm/kvm.h

> +++ b/arch/arm64/include/uapi/asm/kvm.h

> @@ -211,6 +211,12 @@ struct kvm_arch_memory_slot {

>  #define KVM_DEV_ARM_VGIC_GRP_CTRL	4

>  #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5

>  #define KVM_DEV_ARM_VGIC_CPU_SYSREGS    6

> +#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7

> +#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT	10

> +#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \

> +			(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)

> +#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK	0x3ff

> +#define VGIC_LEVEL_INFO_LINE_LEVEL	0

>  

>  #define   KVM_DEV_ARM_VGIC_CTRL_INIT	0

>  

> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c

> index b6266fe..d5f7197 100644

> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c

> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c

> @@ -510,6 +510,21 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,

>  						  regid, reg);

>  		break;

>  	}

> +	case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {

> +		unsigned int info, intid;

> +

> +		info = (attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>

> +			KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT;

> +		if (info == VGIC_LEVEL_INFO_LINE_LEVEL) {

> +			intid = attr->attr &

> +				KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK;

> +			ret = vgic_v3_line_level_info_uaccess(vcpu, is_write,

> +							      intid, reg);

> +		} else {

> +			ret = -EINVAL;

> +		}

> +		break;

> +	}

>  	default:

>  		ret = -EINVAL;

>  		break;

> @@ -552,6 +567,17 @@ static int vgic_v3_set_attr(struct kvm_device *dev,

>  

>  		return vgic_v3_attr_regs_access(dev, attr, &reg, true);

>  	}

> +	case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {

> +		u32 __user *uaddr = (u32 __user *)(long)attr->addr;

> +		u64 reg;

> +		u32 tmp32;

> +

> +		if (get_user(tmp32, uaddr))

> +			return -EFAULT;

> +

> +		reg = tmp32;

> +		return vgic_v3_attr_regs_access(dev, attr, &reg, true);

> +	}

>  	}

>  	return -ENXIO;

>  }

> @@ -587,8 +613,18 @@ static int vgic_v3_get_attr(struct kvm_device *dev,

>  			return ret;

>  		return put_user(reg, uaddr);

>  	}

> -	}

> +	case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {

> +		u32 __user *uaddr = (u32 __user *)(long)attr->addr;

> +		u64 reg;

> +		u32 tmp32;

>  

> +		ret = vgic_v3_attr_regs_access(dev, attr, &reg, false);

> +		if (ret)

> +			return ret;

> +		tmp32 = reg;

> +		return put_user(tmp32, uaddr);

> +	}

> +	}

>  	return -ENXIO;

>  }

>  

> @@ -609,6 +645,13 @@ static int vgic_v3_has_attr(struct kvm_device *dev,

>  		return vgic_v3_has_attr_regs(dev, attr);

>  	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:

>  		return 0;

> +	case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {

> +		if (((attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>

> +		      KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT) ==

> +		      VGIC_LEVEL_INFO_LINE_LEVEL)

> +			return 0;

> +		break;

> +	}

>  	case KVM_DEV_ARM_VGIC_GRP_CTRL:

>  		switch (attr->attr) {

>  		case KVM_DEV_ARM_VGIC_CTRL_INIT:

> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c

> index 51439c9..9491d72 100644

> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c

> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c

> @@ -809,3 +809,14 @@ int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write,

>  		return vgic_uaccess(vcpu, &rd_dev, is_write,

>  				    offset, val);

>  }

> +

> +int vgic_v3_line_level_info_uaccess(struct kvm_vcpu *vcpu, bool is_write,

> +				    u32 intid, u64 *val)

> +{

> +	if (is_write)

> +		vgic_write_irq_line_level_info(vcpu, intid, *val);

> +	else

> +		*val = vgic_read_irq_line_level_info(vcpu, intid);

> +

> +	return 0;

> +}

> diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c

> index f81e0e5..28fef92b 100644

> --- a/virt/kvm/arm/vgic/vgic-mmio.c

> +++ b/virt/kvm/arm/vgic/vgic-mmio.c

> @@ -371,6 +371,52 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,

>  	}

>  }

>  

> +u64 vgic_read_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid)

> +{

> +	int i;

> +	u64 val = 0;

> +

> +	for (i = 0; i < 32; i++) {

> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);

> +

> +		if (irq->line_level)

> +			val |= (1U << i);

> +

> +		vgic_put_irq(vcpu->kvm, irq);

> +	}

> +

> +	return val;

> +}

> +

> +void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,

> +				    const u64 val)

> +{

> +	int i;

> +

> +	for (i = 0; i < 32; i++) {

> +		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);

> +

> +		spin_lock(&irq->irq_lock);

> +		if (val & (1U << i)) {

> +			if (irq->config == VGIC_CONFIG_LEVEL) {

> +				irq->line_level = true;

> +				irq->pending = true;

> +				vgic_queue_irq_unlock(vcpu->kvm, irq);

> +			} else {

> +				spin_unlock(&irq->irq_lock);

> +			}

> +		} else {

> +			if (irq->config == VGIC_CONFIG_EDGE ||

> +			    (irq->config == VGIC_CONFIG_LEVEL &&

> +			    !irq->soft_pending))

> +				irq->line_level = false;

> +			spin_unlock(&irq->irq_lock);

> +		}



So last time we had a discussion about whether or not the API should
support any random order of restoring the registers, but I cannot see
how we can support that, because how can we tell the difference between
the following two scenarios without knowing if an interrupt is
edge-triggered or level triggered:

  (1) Clearing the line_level for an edge-triggered interrupt after
      having set it to pending, which means it should stay pending.

  (2) Clearing the line_level for a level-triggered interrupt when the
      state is already pending for some reason, but the soft_pending
      (latch) state is not set, in which case the pending state should
      be removed.

This leads me to conclude that userspace must restore the configuration
state of the interrupt before at least the line_level, in which case the
implementation becomes:

	for (i = 0; i < 32; i++) {
		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
		bool new_level = !!(val & (1U << i));

		if (irq->config == VGIC_CONFIG_EDGE)
			continue;

		spin_lock(&irq->irq_lock);
		irq->line_level = new_level;
		if (new_level) {
			irq->pending = true;
			vgic_queue_irq_unlock(vcpu->kvm, irq);
		} else {
			if (!irq->soft_pending)
				irq->pending = false;
			spin_unlock(&irq->irq_lock);
		}

		vgic_put_irq(vcpu->kvm, irq);
	}

Thanks,
-Christoffer

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Christoffer Dall Jan. 20, 2017, 7:54 p.m. UTC | #4
On Fri, Dec 16, 2016 at 12:44:18PM +0000, Peter Maydell wrote:
> On 16 December 2016 at 12:07, Auger Eric <eric.auger@redhat.com> wrote:

> > Hi Vijaya,

> >

> > On 01/12/2016 08:09, vijay.kilari@gmail.com wrote:

> >> +void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,

> >> +                                 const u64 val)

> >> +{

> >> +     int i;

> >> +

> >> +     for (i = 0; i < 32; i++) {

> >> +             struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);

> >> +

> > same as above.

> >> +             spin_lock(&irq->irq_lock);

> >> +             if (val & (1U << i)) {

> >> +                     if (irq->config == VGIC_CONFIG_LEVEL) {

> >> +                             irq->line_level = true;

> >> +                             irq->pending = true;

> >> +                             vgic_queue_irq_unlock(vcpu->kvm, irq);

> >> +                     } else {

> >> +                             spin_unlock(&irq->irq_lock);

> >> +                     }

> >> +             } else {

> >> +                     if (irq->config == VGIC_CONFIG_EDGE ||

> > can't we just ignore VGIC_CONFIG_EDGE case for which line_level is not

> > modeled?

> >> +                         (irq->config == VGIC_CONFIG_LEVEL &&

> >> +                         !irq->soft_pending))

> >> +                             irq->line_level = false;

> > To me the line level does not depend on the soft_pending bit. The

> > pending state depends on both.

> 

> Without having looked at the details, it seems surprising to

> me that the implementation of "set line level to X" is not

> "set irq->line_level to X; figure out consequences and update

> other state as necessary"...

> 

Indeed.  Assuming you're ok with the API requiring config state to be
restored before the line level state, I think my suggestion in the
separate reply should work.

Of course, we need to clarify the ordering requirement in the API.

Thanks,
-Christoffer

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Peter Maydell Jan. 23, 2017, 10:16 a.m. UTC | #5
On 20 January 2017 at 19:53, Christoffer Dall
<christoffer.dall@linaro.org> wrote:
> So last time we had a discussion about whether or not the API should

> support any random order of restoring the registers, but I cannot see

> how we can support that, because how can we tell the difference between

> the following two scenarios without knowing if an interrupt is

> edge-triggered or level triggered:

>

>   (1) Clearing the line_level for an edge-triggered interrupt after

>       having set it to pending, which means it should stay pending.


This is userspace doing:
 * set pending-latch to 1
 * set linelevel to 0

right? The pending state is pending-latch | (linelevel & ~edge_trigger),
and you can recalculate that when userspace updates either of the
pending-latch state or linelevel. (It will be temporarily wrong
before userspace has told the kernel about all the state, but
that's fine because we won't try to run the VM until we've finished
loading everything.)

>   (2) Clearing the line_level for a level-triggered interrupt when the

>       state is already pending for some reason, but the soft_pending

>       (latch) state is not set, in which case the pending state should

>       be removed.


This is userspace doing
 * set pending-latch to 0
 * set line_level to 0

and thus the pending state goes to 0 (same calculation as above).

pending is always a pure logical function of pending-latch,
linelevel and edge-trigger bits, so as long as you recalculate
it at the right time then it shouldn't matter which order userspace
tells you about the three things in.

thanks
-- PMM

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Christoffer Dall Jan. 23, 2017, 11:06 a.m. UTC | #6
On Mon, Jan 23, 2017 at 10:16:04AM +0000, Peter Maydell wrote:
> On 20 January 2017 at 19:53, Christoffer Dall

> <christoffer.dall@linaro.org> wrote:

> > So last time we had a discussion about whether or not the API should

> > support any random order of restoring the registers, but I cannot see

> > how we can support that, because how can we tell the difference between

> > the following two scenarios without knowing if an interrupt is

> > edge-triggered or level triggered:

> >

> >   (1) Clearing the line_level for an edge-triggered interrupt after

> >       having set it to pending, which means it should stay pending.

> 

> This is userspace doing:

>  * set pending-latch to 1

>  * set linelevel to 0

> 

> right? The pending state is pending-latch | (linelevel & ~edge_trigger),

> and you can recalculate that when userspace updates either of the

> pending-latch state or linelevel. (It will be temporarily wrong

> before userspace has told the kernel about all the state, but

> that's fine because we won't try to run the VM until we've finished

> loading everything.)

> 

> >   (2) Clearing the line_level for a level-triggered interrupt when the

> >       state is already pending for some reason, but the soft_pending

> >       (latch) state is not set, in which case the pending state should

> >       be removed.

> 

> This is userspace doing

>  * set pending-latch to 0

>  * set line_level to 0

> 

> and thus the pending state goes to 0 (same calculation as above).

> 

> pending is always a pure logical function of pending-latch,

> linelevel and edge-trigger bits, so as long as you recalculate

> it at the right time then it shouldn't matter which order userspace

> tells you about the three things in.

> 


ok, I think you're right that it can be done this way, but it has the
unfortunate consequence of having to change a lot of the implementation.

The reason is that we store the latch state in two different variables,
depening on whether it's an edge- or level-triggered interrupts.

We use the irq->pending field for the computed result (using above
calculaiton) for level interrupts based on irq->line_level and
irq->soft_pending.  soft_pending is the latch state for level interrupts
only.

For edge triggered interrupts the computed result and the latch state
are alway the same (right?) so we we only use the irq->pending field for
that.

But unless I didn't have enough coffee this morning, this only works if
you have a-priori knowledge of which interrupts are level and which are
edge.  When this is not the case, as in the case of order-free
save/restore, then I think the only solution is to rework the logic so
that the soft_pending field is used for the latch state for both edge
and level interrupts, and the pending field is just the internal
computed value.

Thoughts?

Andre, Marc, Eric, do you agree with the above?

(I wonder how we could go through an entire redesign of the vgic and
still have issues like this, but I do remember we all felt tired when we
finally got to design the soft_pending stuff.)

Thanks,
-Christoffer

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Peter Maydell Jan. 23, 2017, 11:41 a.m. UTC | #7
On 23 January 2017 at 11:06, Christoffer Dall
<christoffer.dall@linaro.org> wrote:
> ok, I think you're right that it can be done this way, but it has the

> unfortunate consequence of having to change a lot of the implementation.

>

> The reason is that we store the latch state in two different variables,

> depening on whether it's an edge- or level-triggered interrupts.

>

> We use the irq->pending field for the computed result (using above

> calculaiton) for level interrupts based on irq->line_level and

> irq->soft_pending.  soft_pending is the latch state for level interrupts

> only.

>

> For edge triggered interrupts the computed result and the latch state

> are alway the same (right?) so we we only use the irq->pending field for

> that.

>

> But unless I didn't have enough coffee this morning, this only works if

> you have a-priori knowledge of which interrupts are level and which are

> edge.  When this is not the case, as in the case of order-free

> save/restore, then I think the only solution is to rework the logic so

> that the soft_pending field is used for the latch state for both edge

> and level interrupts, and the pending field is just the internal

> computed value.


I *think* you could fudge it by saying "when the config changes
from edge to level, copy the current irq->pending into irq->soft_pending".
Then you can always read the latch state (it's soft_pending
if level, otherwise pending), and writing it is "set both if
level, just irq->pending if edge". That in turn gives you enough
information I think to cope with restores of all of (config,
level, pending-latch) in any order. It feels a bit fragile, though.

thanks
-- PMM

_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Christoffer Dall Jan. 23, 2017, 1:42 p.m. UTC | #8
On Mon, Jan 23, 2017 at 11:41:41AM +0000, Peter Maydell wrote:
> On 23 January 2017 at 11:06, Christoffer Dall

> <christoffer.dall@linaro.org> wrote:

> > ok, I think you're right that it can be done this way, but it has the

> > unfortunate consequence of having to change a lot of the implementation.

> >

> > The reason is that we store the latch state in two different variables,

> > depening on whether it's an edge- or level-triggered interrupts.

> >

> > We use the irq->pending field for the computed result (using above

> > calculaiton) for level interrupts based on irq->line_level and

> > irq->soft_pending.  soft_pending is the latch state for level interrupts

> > only.

> >

> > For edge triggered interrupts the computed result and the latch state

> > are alway the same (right?) so we we only use the irq->pending field for

> > that.

> >

> > But unless I didn't have enough coffee this morning, this only works if

> > you have a-priori knowledge of which interrupts are level and which are

> > edge.  When this is not the case, as in the case of order-free

> > save/restore, then I think the only solution is to rework the logic so

> > that the soft_pending field is used for the latch state for both edge

> > and level interrupts, and the pending field is just the internal

> > computed value.

> 

> I *think* you could fudge it by saying "when the config changes

> from edge to level, copy the current irq->pending into irq->soft_pending".

> Then you can always read the latch state (it's soft_pending

> if level, otherwise pending), and writing it is "set both if

> level, just irq->pending if edge". That in turn gives you enough

> information I think to cope with restores of all of (config,

> level, pending-latch) in any order. It feels a bit fragile, though.


Right, thanks for working this out.  I agree it's fragile and I cannot
seem to easily convince myself it would be correct, so I sent out a
patch to get rid of the pending cached state which should simplify the
save/restore patches as well.

Assuming the other VGIC suspects don't object to that, I suggest we base
these patches on top of that one and see if we can convince ourselves
that it's correct then.

Thanks,
-Christoffer

_______________________________________________
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/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 98658d9d..f347779 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -191,6 +191,13 @@  struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_CTRL       4
 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
 #define KVM_DEV_ARM_VGIC_CPU_SYSREGS    6
+#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT	10
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
+			(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK	0x3ff
+#define VGIC_LEVEL_INFO_LINE_LEVEL	0
+
 #define   KVM_DEV_ARM_VGIC_CTRL_INIT    0
 
 /* KVM_IRQ_LINE irq field index values */
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 91c7137..4100f8c 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -211,6 +211,12 @@  struct kvm_arch_memory_slot {
 #define KVM_DEV_ARM_VGIC_GRP_CTRL	4
 #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
 #define KVM_DEV_ARM_VGIC_CPU_SYSREGS    6
+#define KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO 7
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT	10
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK \
+			(0x3fffffULL << KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT)
+#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK	0x3ff
+#define VGIC_LEVEL_INFO_LINE_LEVEL	0
 
 #define   KVM_DEV_ARM_VGIC_CTRL_INIT	0
 
diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
index b6266fe..d5f7197 100644
--- a/virt/kvm/arm/vgic/vgic-kvm-device.c
+++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
@@ -510,6 +510,21 @@  static int vgic_v3_attr_regs_access(struct kvm_device *dev,
 						  regid, reg);
 		break;
 	}
+	case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
+		unsigned int info, intid;
+
+		info = (attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>
+			KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT;
+		if (info == VGIC_LEVEL_INFO_LINE_LEVEL) {
+			intid = attr->attr &
+				KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK;
+			ret = vgic_v3_line_level_info_uaccess(vcpu, is_write,
+							      intid, reg);
+		} else {
+			ret = -EINVAL;
+		}
+		break;
+	}
 	default:
 		ret = -EINVAL;
 		break;
@@ -552,6 +567,17 @@  static int vgic_v3_set_attr(struct kvm_device *dev,
 
 		return vgic_v3_attr_regs_access(dev, attr, &reg, true);
 	}
+	case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u64 reg;
+		u32 tmp32;
+
+		if (get_user(tmp32, uaddr))
+			return -EFAULT;
+
+		reg = tmp32;
+		return vgic_v3_attr_regs_access(dev, attr, &reg, true);
+	}
 	}
 	return -ENXIO;
 }
@@ -587,8 +613,18 @@  static int vgic_v3_get_attr(struct kvm_device *dev,
 			return ret;
 		return put_user(reg, uaddr);
 	}
-	}
+	case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
+		u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+		u64 reg;
+		u32 tmp32;
 
+		ret = vgic_v3_attr_regs_access(dev, attr, &reg, false);
+		if (ret)
+			return ret;
+		tmp32 = reg;
+		return put_user(tmp32, uaddr);
+	}
+	}
 	return -ENXIO;
 }
 
@@ -609,6 +645,13 @@  static int vgic_v3_has_attr(struct kvm_device *dev,
 		return vgic_v3_has_attr_regs(dev, attr);
 	case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
 		return 0;
+	case KVM_DEV_ARM_VGIC_GRP_LEVEL_INFO: {
+		if (((attr->attr & KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_MASK) >>
+		      KVM_DEV_ARM_VGIC_LINE_LEVEL_INFO_SHIFT) ==
+		      VGIC_LEVEL_INFO_LINE_LEVEL)
+			return 0;
+		break;
+	}
 	case KVM_DEV_ARM_VGIC_GRP_CTRL:
 		switch (attr->attr) {
 		case KVM_DEV_ARM_VGIC_CTRL_INIT:
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 51439c9..9491d72 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -809,3 +809,14 @@  int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 		return vgic_uaccess(vcpu, &rd_dev, is_write,
 				    offset, val);
 }
+
+int vgic_v3_line_level_info_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+				    u32 intid, u64 *val)
+{
+	if (is_write)
+		vgic_write_irq_line_level_info(vcpu, intid, *val);
+	else
+		*val = vgic_read_irq_line_level_info(vcpu, intid);
+
+	return 0;
+}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index f81e0e5..28fef92b 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -371,6 +371,52 @@  void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
 	}
 }
 
+u64 vgic_read_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid)
+{
+	int i;
+	u64 val = 0;
+
+	for (i = 0; i < 32; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		if (irq->line_level)
+			val |= (1U << i);
+
+		vgic_put_irq(vcpu->kvm, irq);
+	}
+
+	return val;
+}
+
+void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,
+				    const u64 val)
+{
+	int i;
+
+	for (i = 0; i < 32; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+
+		spin_lock(&irq->irq_lock);
+		if (val & (1U << i)) {
+			if (irq->config == VGIC_CONFIG_LEVEL) {
+				irq->line_level = true;
+				irq->pending = true;
+				vgic_queue_irq_unlock(vcpu->kvm, irq);
+			} else {
+				spin_unlock(&irq->irq_lock);
+			}
+		} else {
+			if (irq->config == VGIC_CONFIG_EDGE ||
+			    (irq->config == VGIC_CONFIG_LEVEL &&
+			    !irq->soft_pending))
+				irq->line_level = false;
+			spin_unlock(&irq->irq_lock);
+		}
+
+		vgic_put_irq(vcpu->kvm, irq);
+	}
+}
+
 static int match_region(const void *key, const void *elt)
 {
 	const unsigned int offset = (unsigned long)key;
diff --git a/virt/kvm/arm/vgic/vgic-mmio.h b/virt/kvm/arm/vgic/vgic-mmio.h
index 1cc7faf..b9423b4 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.h
+++ b/virt/kvm/arm/vgic/vgic-mmio.h
@@ -181,6 +181,11 @@  int vgic_validate_mmio_region_addr(struct kvm_device *dev,
 				   const struct vgic_register_region *regions,
 				   int nr_regions, gpa_t addr);
 
+u64 vgic_read_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid);
+
+void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,
+				    const u64 val);
+
 unsigned int vgic_v2_init_dist_iodev(struct vgic_io_device *dev);
 
 unsigned int vgic_v3_init_dist_iodev(struct vgic_io_device *dev);
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index eac272c..60d4350 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -144,6 +144,8 @@  int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write,
 			 u64 id, u64 *val);
 int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
 				u64 *reg);
+int vgic_v3_line_level_info_uaccess(struct kvm_vcpu *vcpu, bool is_write,
+				    u32 intid, u64 *val);
 int kvm_register_vgic_device(unsigned long type);
 void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 void vgic_get_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);