From: Marc Zyngier <marc.zyngier@arm.com>
To: Andre Przywara <andre.przywara@arm.com>,
Christoffer Dall <christoffer.dall@linaro.org>,
Eric Auger <eric.auger@redhat.com>
Cc: linux-arm-kernel@lists.infradead.org,
kvmarm@lists.cs.columbia.edu, kvm@vger.kernel.org
Subject: Re: [PATCH v9 10/17] KVM: arm64: introduce new KVM ITS device
Date: Thu, 14 Jul 2016 09:36:46 +0100 [thread overview]
Message-ID: <57874F1E.3000202@arm.com> (raw)
In-Reply-To: <20160713015909.28793-11-andre.przywara@arm.com>
On 13/07/16 02:59, Andre Przywara wrote:
> Introduce a new KVM device that represents an ARM Interrupt Translation
> Service (ITS) controller. Since there can be multiple of this per guest,
> we can't piggy back on the existing GICv3 distributor device, but create
> a new type of KVM device.
> On the KVM_CREATE_DEVICE ioctl we allocate and initialize the ITS data
> structure and store the pointer in the kvm_device data.
> Upon an explicit init ioctl from userland (after having setup the MMIO
> address) we register the handlers with the kvm_io_bus framework.
> Any reference to an ITS thus has to go via this interface.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> Documentation/virtual/kvm/devices/arm-vgic.txt | 25 +++--
> arch/arm/kvm/arm.c | 1 +
> arch/arm64/include/uapi/asm/kvm.h | 2 +
> include/kvm/arm_vgic.h | 3 +
> include/uapi/linux/kvm.h | 2 +
> virt/kvm/arm/vgic/vgic-its.c | 144 ++++++++++++++++++++++++-
> virt/kvm/arm/vgic/vgic-kvm-device.c | 7 +-
> virt/kvm/arm/vgic/vgic-mmio-v3.c | 2 +-
> virt/kvm/arm/vgic/vgic.h | 8 ++
> 9 files changed, 183 insertions(+), 11 deletions(-)
>
> diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
> index 59541d4..89182f8 100644
> --- a/Documentation/virtual/kvm/devices/arm-vgic.txt
> +++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
> @@ -4,16 +4,22 @@ ARM Virtual Generic Interrupt Controller (VGIC)
> Device types supported:
> KVM_DEV_TYPE_ARM_VGIC_V2 ARM Generic Interrupt Controller v2.0
> KVM_DEV_TYPE_ARM_VGIC_V3 ARM Generic Interrupt Controller v3.0
> + KVM_DEV_TYPE_ARM_VGIC_ITS ARM Interrupt Translation Service Controller
>
> -Only one VGIC instance may be instantiated through either this API or the
> -legacy KVM_CREATE_IRQCHIP api. The created VGIC will act as the VM interrupt
> -controller, requiring emulated user-space devices to inject interrupts to the
> -VGIC instead of directly to CPUs.
> +Only one VGIC instance of the V2/V3 types above may be instantiated through
> +either this API or the legacy KVM_CREATE_IRQCHIP api. The created VGIC will
> +act as the VM interrupt controller, requiring emulated user-space devices to
> +inject interrupts to the VGIC instead of directly to CPUs.
>
> Creating a guest GICv3 device requires a host GICv3 as well.
> GICv3 implementations with hardware compatibility support allow a guest GICv2
> as well.
>
> +Creating a virtual ITS controller requires a host GICv3 (but does not depend
> +on having physical ITS controllers).
> +There can be multiple ITS controllers per guest, each of them has to have
> +a separate, non-overlapping MMIO region.
> +
> Groups:
> KVM_DEV_ARM_VGIC_GRP_ADDR
> Attributes:
> @@ -39,6 +45,13 @@ Groups:
> Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
> This address needs to be 64K aligned.
>
> + KVM_VGIC_V3_ADDR_TYPE_ITS (rw, 64-bit)
> + Base address in the guest physical address space of the GICv3 ITS
> + control register frame. The ITS allows MSI(-X) interrupts to be
> + injected into guests. This extension is optional. If the kernel
> + does not support the ITS, the call returns -ENODEV.
> + Only valid for KVM_DEV_TYPE_ARM_VGIC_ITS.
> + This address needs to be 64K aligned and the region covers 128K.
>
> KVM_DEV_ARM_VGIC_GRP_DIST_REGS
> Attributes:
> @@ -109,8 +122,8 @@ Groups:
> KVM_DEV_ARM_VGIC_GRP_CTRL
> Attributes:
> KVM_DEV_ARM_VGIC_CTRL_INIT
> - request the initialization of the VGIC, no additional parameter in
> - kvm_device_attr.addr.
> + request the initialization of the VGIC or ITS, no additional parameter
> + in kvm_device_attr.addr.
> Errors:
> -ENXIO: VGIC not properly configured as required prior to calling
> this attribute
> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> index 557e390..0d5c255 100644
> --- a/arch/arm/kvm/arm.c
> +++ b/arch/arm/kvm/arm.c
> @@ -20,6 +20,7 @@
> #include <linux/errno.h>
> #include <linux/err.h>
> #include <linux/kvm_host.h>
> +#include <linux/list.h>
> #include <linux/module.h>
> #include <linux/vmalloc.h>
> #include <linux/fs.h>
> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index f209ea1..3051f86 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -87,9 +87,11 @@ struct kvm_regs {
> /* Supported VGICv3 address types */
> #define KVM_VGIC_V3_ADDR_TYPE_DIST 2
> #define KVM_VGIC_V3_ADDR_TYPE_REDIST 3
> +#define KVM_VGIC_ITS_ADDR_TYPE 4
>
> #define KVM_VGIC_V3_DIST_SIZE SZ_64K
> #define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K)
> +#define KVM_VGIC_V3_ITS_SIZE (2 * SZ_64K)
>
> #define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
> #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 685f339..8609fac 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -134,6 +134,7 @@ struct vgic_its {
> gpa_t vgic_its_base;
>
> bool enabled;
> + bool initialized;
> struct vgic_io_device iodev;
> };
>
> @@ -167,6 +168,8 @@ struct vgic_dist {
>
> struct vgic_io_device dist_iodev;
>
> + bool has_its;
> +
> /*
> * Contains the attributes and gpa of the LPI configuration table.
> * Since we report GICR_TYPER.CommonLPIAff as 0b00, we can share
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 7de96f5..d8c4c32 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -1077,6 +1077,8 @@ enum kvm_device_type {
> #define KVM_DEV_TYPE_FLIC KVM_DEV_TYPE_FLIC
> KVM_DEV_TYPE_ARM_VGIC_V3,
> #define KVM_DEV_TYPE_ARM_VGIC_V3 KVM_DEV_TYPE_ARM_VGIC_V3
> + KVM_DEV_TYPE_ARM_VGIC_ITS,
> +#define KVM_DEV_TYPE_ARM_VGIC_ITS KVM_DEV_TYPE_ARM_VGIC_ITS
> KVM_DEV_TYPE_MAX,
> };
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 06ad94d..393ad3a 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -21,6 +21,7 @@
> #include <linux/kvm.h>
> #include <linux/kvm_host.h>
> #include <linux/interrupt.h>
> +#include <linux/uaccess.h>
>
> #include <linux/irqchip/arm-gic-v3.h>
>
> @@ -79,7 +80,7 @@ static struct vgic_register_region its_registers[] = {
> VGIC_ACCESS_32bit),
> };
>
> -int vgic_its_register(struct kvm *kvm, struct vgic_its *its)
> +static int vgic_its_register(struct kvm *kvm, struct vgic_its *its)
Please move this hunk to the previous patch...
> {
> struct vgic_io_device *iodev = &its->iodev;
> int ret;
> @@ -93,8 +94,147 @@ int vgic_its_register(struct kvm *kvm, struct vgic_its *its)
> iodev->its = its;
> mutex_lock(&kvm->slots_lock);
> ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, iodev->base_addr,
> - SZ_64K, &iodev->dev);
> + KVM_VGIC_V3_ITS_SIZE, &iodev->dev);
as well as this one.
> mutex_unlock(&kvm->slots_lock);
>
> return ret;
> }
> +
> +static int vgic_its_create(struct kvm_device *dev, u32 type)
> +{
> + struct vgic_its *its;
> +
> + if (type != KVM_DEV_TYPE_ARM_VGIC_ITS)
> + return -ENODEV;
> +
> + its = kzalloc(sizeof(struct vgic_its), GFP_KERNEL);
> + if (!its)
> + return -ENOMEM;
> +
> + its->vgic_its_base = VGIC_ADDR_UNDEF;
> +
> + dev->kvm->arch.vgic.has_its = true;
> + its->initialized = false;
> + its->enabled = false;
> +
> + dev->private = its;
> +
> + return 0;
> +}
> +
> +static void vgic_its_destroy(struct kvm_device *kvm_dev)
> +{
> + struct vgic_its *its = kvm_dev->private;
> +
> + kfree(its);
> +}
> +
> +static int vgic_its_has_attr(struct kvm_device *dev,
> + struct kvm_device_attr *attr)
> +{
> + switch (attr->group) {
> + case KVM_DEV_ARM_VGIC_GRP_ADDR:
> + switch (attr->attr) {
> + case KVM_VGIC_ITS_ADDR_TYPE:
> + return 0;
> + }
> + break;
> + case KVM_DEV_ARM_VGIC_GRP_CTRL:
> + switch (attr->attr) {
> + case KVM_DEV_ARM_VGIC_CTRL_INIT:
> + return 0;
> + }
> + break;
> + }
> + return -ENXIO;
> +}
> +
> +static int vgic_its_set_attr(struct kvm_device *dev,
> + struct kvm_device_attr *attr)
> +{
> + struct vgic_its *its = dev->private;
> + int ret;
> +
> + switch (attr->group) {
> + case KVM_DEV_ARM_VGIC_GRP_ADDR: {
> + u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> + unsigned long type = (unsigned long)attr->attr;
> + u64 addr;
> +
> + if (type != KVM_VGIC_ITS_ADDR_TYPE)
> + return -ENODEV;
> +
> + if (its->initialized)
> + return -EBUSY;
> +
> + if (copy_from_user(&addr, uaddr, sizeof(addr)))
> + return -EFAULT;
> +
> + ret = vgic_check_ioaddr(dev->kvm, &its->vgic_its_base,
> + addr, SZ_64K);
Shouldn't that be the ITS size (128kB)?
> + if (ret)
> + return ret;
> +
> + its->vgic_its_base = addr;
> +
> + return 0;
> + }
> + case KVM_DEV_ARM_VGIC_GRP_CTRL:
> + switch (attr->attr) {
> + case KVM_DEV_ARM_VGIC_CTRL_INIT:
> + if (its->initialized)
> + return 0;
> +
> + if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base))
> + return -ENXIO;
> +
> + ret = vgic_its_register(dev->kvm, its);
> + if (ret)
> + return ret;
> +
> + its->initialized = true;
> + return 0;
Can't you move all of that into vgic_its_register? That'd be a lot cleaner.
> + }
> + break;
> + }
> + return -ENXIO;
> +}
> +
> +static int vgic_its_get_attr(struct kvm_device *dev,
> + struct kvm_device_attr *attr)
> +{
> + switch (attr->group) {
> + case KVM_DEV_ARM_VGIC_GRP_ADDR: {
> + struct vgic_its *its = dev->private;
> + u64 addr = its->vgic_its_base;
> + u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> + unsigned long type = (unsigned long)attr->attr;
> +
> + if (type != KVM_VGIC_ITS_ADDR_TYPE)
> + return -ENODEV;
> +
> + if (copy_to_user(uaddr, &addr, sizeof(addr)))
> + return -EFAULT;
> + break;
> + default:
> + return -ENXIO;
> + }
> + }
> +
> + return 0;
> +}
> +
> +struct kvm_device_ops kvm_arm_vgic_its_ops = {
Should be static.
> + .name = "kvm-arm-vgic-its",
> + .create = vgic_its_create,
> + .destroy = vgic_its_destroy,
> + .set_attr = vgic_its_set_attr,
> + .get_attr = vgic_its_get_attr,
> + .has_attr = vgic_its_has_attr,
> +};
> +
> +int kvm_vgic_register_its_device(void)
> +{
> + return kvm_register_device_ops(&kvm_arm_vgic_its_ops,
> + KVM_DEV_TYPE_ARM_VGIC_ITS);
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index 2f24f13..1813f93 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -21,8 +21,8 @@
>
> /* common helpers */
>
> -static int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
> - phys_addr_t addr, phys_addr_t alignment)
> +int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
> + phys_addr_t addr, phys_addr_t alignment)
> {
> if (addr & ~KVM_PHYS_MASK)
> return -E2BIG;
> @@ -223,6 +223,9 @@ int kvm_register_vgic_device(unsigned long type)
> case KVM_DEV_TYPE_ARM_VGIC_V3:
> ret = kvm_register_device_ops(&kvm_arm_vgic_v3_ops,
> KVM_DEV_TYPE_ARM_VGIC_V3);
> + if (ret)
> + break;
> + ret = kvm_vgic_register_its_device();
> break;
> #endif
> }
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index 4169e22..6cb52dd 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -49,7 +49,7 @@ bool vgic_has_its(struct kvm *kvm)
> if (dist->vgic_model != KVM_DEV_TYPE_ARM_VGIC_V3)
> return false;
>
> - return false;
> + return dist->has_its;
> }
>
> static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 31807c1..9dc7207 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -42,6 +42,9 @@ void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq);
> bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
> void vgic_kick_vcpus(struct kvm *kvm);
>
> +int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
> + phys_addr_t addr, phys_addr_t alignment);
> +
> void vgic_v2_process_maintenance(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);
> @@ -73,6 +76,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info);
> int vgic_v3_map_resources(struct kvm *kvm);
> int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
> bool vgic_has_its(struct kvm *kvm);
> +int kvm_vgic_register_its_device(void);
> #else
> static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
> {
> @@ -130,6 +134,10 @@ static inline bool vgic_has_its(struct kvm *kvm)
> return false;
> }
>
> +static inline int kvm_vgic_register_its_device(void)
> +{
> + return -ENODEV;
> +}
> #endif
>
> int kvm_register_vgic_device(unsigned long type);
>
Thanks,
M.
--
Jazz is not dead. It just smells funny...
WARNING: multiple messages have this Message-ID (diff)
From: marc.zyngier@arm.com (Marc Zyngier)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH v9 10/17] KVM: arm64: introduce new KVM ITS device
Date: Thu, 14 Jul 2016 09:36:46 +0100 [thread overview]
Message-ID: <57874F1E.3000202@arm.com> (raw)
In-Reply-To: <20160713015909.28793-11-andre.przywara@arm.com>
On 13/07/16 02:59, Andre Przywara wrote:
> Introduce a new KVM device that represents an ARM Interrupt Translation
> Service (ITS) controller. Since there can be multiple of this per guest,
> we can't piggy back on the existing GICv3 distributor device, but create
> a new type of KVM device.
> On the KVM_CREATE_DEVICE ioctl we allocate and initialize the ITS data
> structure and store the pointer in the kvm_device data.
> Upon an explicit init ioctl from userland (after having setup the MMIO
> address) we register the handlers with the kvm_io_bus framework.
> Any reference to an ITS thus has to go via this interface.
>
> Signed-off-by: Andre Przywara <andre.przywara@arm.com>
> ---
> Documentation/virtual/kvm/devices/arm-vgic.txt | 25 +++--
> arch/arm/kvm/arm.c | 1 +
> arch/arm64/include/uapi/asm/kvm.h | 2 +
> include/kvm/arm_vgic.h | 3 +
> include/uapi/linux/kvm.h | 2 +
> virt/kvm/arm/vgic/vgic-its.c | 144 ++++++++++++++++++++++++-
> virt/kvm/arm/vgic/vgic-kvm-device.c | 7 +-
> virt/kvm/arm/vgic/vgic-mmio-v3.c | 2 +-
> virt/kvm/arm/vgic/vgic.h | 8 ++
> 9 files changed, 183 insertions(+), 11 deletions(-)
>
> diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
> index 59541d4..89182f8 100644
> --- a/Documentation/virtual/kvm/devices/arm-vgic.txt
> +++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
> @@ -4,16 +4,22 @@ ARM Virtual Generic Interrupt Controller (VGIC)
> Device types supported:
> KVM_DEV_TYPE_ARM_VGIC_V2 ARM Generic Interrupt Controller v2.0
> KVM_DEV_TYPE_ARM_VGIC_V3 ARM Generic Interrupt Controller v3.0
> + KVM_DEV_TYPE_ARM_VGIC_ITS ARM Interrupt Translation Service Controller
>
> -Only one VGIC instance may be instantiated through either this API or the
> -legacy KVM_CREATE_IRQCHIP api. The created VGIC will act as the VM interrupt
> -controller, requiring emulated user-space devices to inject interrupts to the
> -VGIC instead of directly to CPUs.
> +Only one VGIC instance of the V2/V3 types above may be instantiated through
> +either this API or the legacy KVM_CREATE_IRQCHIP api. The created VGIC will
> +act as the VM interrupt controller, requiring emulated user-space devices to
> +inject interrupts to the VGIC instead of directly to CPUs.
>
> Creating a guest GICv3 device requires a host GICv3 as well.
> GICv3 implementations with hardware compatibility support allow a guest GICv2
> as well.
>
> +Creating a virtual ITS controller requires a host GICv3 (but does not depend
> +on having physical ITS controllers).
> +There can be multiple ITS controllers per guest, each of them has to have
> +a separate, non-overlapping MMIO region.
> +
> Groups:
> KVM_DEV_ARM_VGIC_GRP_ADDR
> Attributes:
> @@ -39,6 +45,13 @@ Groups:
> Only valid for KVM_DEV_TYPE_ARM_VGIC_V3.
> This address needs to be 64K aligned.
>
> + KVM_VGIC_V3_ADDR_TYPE_ITS (rw, 64-bit)
> + Base address in the guest physical address space of the GICv3 ITS
> + control register frame. The ITS allows MSI(-X) interrupts to be
> + injected into guests. This extension is optional. If the kernel
> + does not support the ITS, the call returns -ENODEV.
> + Only valid for KVM_DEV_TYPE_ARM_VGIC_ITS.
> + This address needs to be 64K aligned and the region covers 128K.
>
> KVM_DEV_ARM_VGIC_GRP_DIST_REGS
> Attributes:
> @@ -109,8 +122,8 @@ Groups:
> KVM_DEV_ARM_VGIC_GRP_CTRL
> Attributes:
> KVM_DEV_ARM_VGIC_CTRL_INIT
> - request the initialization of the VGIC, no additional parameter in
> - kvm_device_attr.addr.
> + request the initialization of the VGIC or ITS, no additional parameter
> + in kvm_device_attr.addr.
> Errors:
> -ENXIO: VGIC not properly configured as required prior to calling
> this attribute
> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> index 557e390..0d5c255 100644
> --- a/arch/arm/kvm/arm.c
> +++ b/arch/arm/kvm/arm.c
> @@ -20,6 +20,7 @@
> #include <linux/errno.h>
> #include <linux/err.h>
> #include <linux/kvm_host.h>
> +#include <linux/list.h>
> #include <linux/module.h>
> #include <linux/vmalloc.h>
> #include <linux/fs.h>
> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index f209ea1..3051f86 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -87,9 +87,11 @@ struct kvm_regs {
> /* Supported VGICv3 address types */
> #define KVM_VGIC_V3_ADDR_TYPE_DIST 2
> #define KVM_VGIC_V3_ADDR_TYPE_REDIST 3
> +#define KVM_VGIC_ITS_ADDR_TYPE 4
>
> #define KVM_VGIC_V3_DIST_SIZE SZ_64K
> #define KVM_VGIC_V3_REDIST_SIZE (2 * SZ_64K)
> +#define KVM_VGIC_V3_ITS_SIZE (2 * SZ_64K)
>
> #define KVM_ARM_VCPU_POWER_OFF 0 /* CPU is started in OFF state */
> #define KVM_ARM_VCPU_EL1_32BIT 1 /* CPU running a 32bit VM */
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 685f339..8609fac 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -134,6 +134,7 @@ struct vgic_its {
> gpa_t vgic_its_base;
>
> bool enabled;
> + bool initialized;
> struct vgic_io_device iodev;
> };
>
> @@ -167,6 +168,8 @@ struct vgic_dist {
>
> struct vgic_io_device dist_iodev;
>
> + bool has_its;
> +
> /*
> * Contains the attributes and gpa of the LPI configuration table.
> * Since we report GICR_TYPER.CommonLPIAff as 0b00, we can share
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 7de96f5..d8c4c32 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -1077,6 +1077,8 @@ enum kvm_device_type {
> #define KVM_DEV_TYPE_FLIC KVM_DEV_TYPE_FLIC
> KVM_DEV_TYPE_ARM_VGIC_V3,
> #define KVM_DEV_TYPE_ARM_VGIC_V3 KVM_DEV_TYPE_ARM_VGIC_V3
> + KVM_DEV_TYPE_ARM_VGIC_ITS,
> +#define KVM_DEV_TYPE_ARM_VGIC_ITS KVM_DEV_TYPE_ARM_VGIC_ITS
> KVM_DEV_TYPE_MAX,
> };
>
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 06ad94d..393ad3a 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -21,6 +21,7 @@
> #include <linux/kvm.h>
> #include <linux/kvm_host.h>
> #include <linux/interrupt.h>
> +#include <linux/uaccess.h>
>
> #include <linux/irqchip/arm-gic-v3.h>
>
> @@ -79,7 +80,7 @@ static struct vgic_register_region its_registers[] = {
> VGIC_ACCESS_32bit),
> };
>
> -int vgic_its_register(struct kvm *kvm, struct vgic_its *its)
> +static int vgic_its_register(struct kvm *kvm, struct vgic_its *its)
Please move this hunk to the previous patch...
> {
> struct vgic_io_device *iodev = &its->iodev;
> int ret;
> @@ -93,8 +94,147 @@ int vgic_its_register(struct kvm *kvm, struct vgic_its *its)
> iodev->its = its;
> mutex_lock(&kvm->slots_lock);
> ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, iodev->base_addr,
> - SZ_64K, &iodev->dev);
> + KVM_VGIC_V3_ITS_SIZE, &iodev->dev);
as well as this one.
> mutex_unlock(&kvm->slots_lock);
>
> return ret;
> }
> +
> +static int vgic_its_create(struct kvm_device *dev, u32 type)
> +{
> + struct vgic_its *its;
> +
> + if (type != KVM_DEV_TYPE_ARM_VGIC_ITS)
> + return -ENODEV;
> +
> + its = kzalloc(sizeof(struct vgic_its), GFP_KERNEL);
> + if (!its)
> + return -ENOMEM;
> +
> + its->vgic_its_base = VGIC_ADDR_UNDEF;
> +
> + dev->kvm->arch.vgic.has_its = true;
> + its->initialized = false;
> + its->enabled = false;
> +
> + dev->private = its;
> +
> + return 0;
> +}
> +
> +static void vgic_its_destroy(struct kvm_device *kvm_dev)
> +{
> + struct vgic_its *its = kvm_dev->private;
> +
> + kfree(its);
> +}
> +
> +static int vgic_its_has_attr(struct kvm_device *dev,
> + struct kvm_device_attr *attr)
> +{
> + switch (attr->group) {
> + case KVM_DEV_ARM_VGIC_GRP_ADDR:
> + switch (attr->attr) {
> + case KVM_VGIC_ITS_ADDR_TYPE:
> + return 0;
> + }
> + break;
> + case KVM_DEV_ARM_VGIC_GRP_CTRL:
> + switch (attr->attr) {
> + case KVM_DEV_ARM_VGIC_CTRL_INIT:
> + return 0;
> + }
> + break;
> + }
> + return -ENXIO;
> +}
> +
> +static int vgic_its_set_attr(struct kvm_device *dev,
> + struct kvm_device_attr *attr)
> +{
> + struct vgic_its *its = dev->private;
> + int ret;
> +
> + switch (attr->group) {
> + case KVM_DEV_ARM_VGIC_GRP_ADDR: {
> + u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> + unsigned long type = (unsigned long)attr->attr;
> + u64 addr;
> +
> + if (type != KVM_VGIC_ITS_ADDR_TYPE)
> + return -ENODEV;
> +
> + if (its->initialized)
> + return -EBUSY;
> +
> + if (copy_from_user(&addr, uaddr, sizeof(addr)))
> + return -EFAULT;
> +
> + ret = vgic_check_ioaddr(dev->kvm, &its->vgic_its_base,
> + addr, SZ_64K);
Shouldn't that be the ITS size (128kB)?
> + if (ret)
> + return ret;
> +
> + its->vgic_its_base = addr;
> +
> + return 0;
> + }
> + case KVM_DEV_ARM_VGIC_GRP_CTRL:
> + switch (attr->attr) {
> + case KVM_DEV_ARM_VGIC_CTRL_INIT:
> + if (its->initialized)
> + return 0;
> +
> + if (IS_VGIC_ADDR_UNDEF(its->vgic_its_base))
> + return -ENXIO;
> +
> + ret = vgic_its_register(dev->kvm, its);
> + if (ret)
> + return ret;
> +
> + its->initialized = true;
> + return 0;
Can't you move all of that into vgic_its_register? That'd be a lot cleaner.
> + }
> + break;
> + }
> + return -ENXIO;
> +}
> +
> +static int vgic_its_get_attr(struct kvm_device *dev,
> + struct kvm_device_attr *attr)
> +{
> + switch (attr->group) {
> + case KVM_DEV_ARM_VGIC_GRP_ADDR: {
> + struct vgic_its *its = dev->private;
> + u64 addr = its->vgic_its_base;
> + u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> + unsigned long type = (unsigned long)attr->attr;
> +
> + if (type != KVM_VGIC_ITS_ADDR_TYPE)
> + return -ENODEV;
> +
> + if (copy_to_user(uaddr, &addr, sizeof(addr)))
> + return -EFAULT;
> + break;
> + default:
> + return -ENXIO;
> + }
> + }
> +
> + return 0;
> +}
> +
> +struct kvm_device_ops kvm_arm_vgic_its_ops = {
Should be static.
> + .name = "kvm-arm-vgic-its",
> + .create = vgic_its_create,
> + .destroy = vgic_its_destroy,
> + .set_attr = vgic_its_set_attr,
> + .get_attr = vgic_its_get_attr,
> + .has_attr = vgic_its_has_attr,
> +};
> +
> +int kvm_vgic_register_its_device(void)
> +{
> + return kvm_register_device_ops(&kvm_arm_vgic_its_ops,
> + KVM_DEV_TYPE_ARM_VGIC_ITS);
> +}
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index 2f24f13..1813f93 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -21,8 +21,8 @@
>
> /* common helpers */
>
> -static int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
> - phys_addr_t addr, phys_addr_t alignment)
> +int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
> + phys_addr_t addr, phys_addr_t alignment)
> {
> if (addr & ~KVM_PHYS_MASK)
> return -E2BIG;
> @@ -223,6 +223,9 @@ int kvm_register_vgic_device(unsigned long type)
> case KVM_DEV_TYPE_ARM_VGIC_V3:
> ret = kvm_register_device_ops(&kvm_arm_vgic_v3_ops,
> KVM_DEV_TYPE_ARM_VGIC_V3);
> + if (ret)
> + break;
> + ret = kvm_vgic_register_its_device();
> break;
> #endif
> }
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index 4169e22..6cb52dd 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -49,7 +49,7 @@ bool vgic_has_its(struct kvm *kvm)
> if (dist->vgic_model != KVM_DEV_TYPE_ARM_VGIC_V3)
> return false;
>
> - return false;
> + return dist->has_its;
> }
>
> static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 31807c1..9dc7207 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -42,6 +42,9 @@ void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq);
> bool vgic_queue_irq_unlock(struct kvm *kvm, struct vgic_irq *irq);
> void vgic_kick_vcpus(struct kvm *kvm);
>
> +int vgic_check_ioaddr(struct kvm *kvm, phys_addr_t *ioaddr,
> + phys_addr_t addr, phys_addr_t alignment);
> +
> void vgic_v2_process_maintenance(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);
> @@ -73,6 +76,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info);
> int vgic_v3_map_resources(struct kvm *kvm);
> int vgic_register_redist_iodevs(struct kvm *kvm, gpa_t dist_base_address);
> bool vgic_has_its(struct kvm *kvm);
> +int kvm_vgic_register_its_device(void);
> #else
> static inline void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
> {
> @@ -130,6 +134,10 @@ static inline bool vgic_has_its(struct kvm *kvm)
> return false;
> }
>
> +static inline int kvm_vgic_register_its_device(void)
> +{
> + return -ENODEV;
> +}
> #endif
>
> int kvm_register_vgic_device(unsigned long type);
>
Thanks,
M.
--
Jazz is not dead. It just smells funny...
next prev parent reply other threads:[~2016-07-14 8:30 UTC|newest]
Thread overview: 82+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-07-13 1:58 [PATCH v9 00/17] KVM: arm64: GICv3 ITS emulation Andre Przywara
2016-07-13 1:58 ` Andre Przywara
2016-07-13 1:58 ` [PATCH v9 01/17] KVM: arm/arm64: move redistributor kvm_io_devices Andre Przywara
2016-07-13 1:58 ` Andre Przywara
2016-07-13 1:58 ` [PATCH v9 02/17] KVM: arm/arm64: check return value for kvm_register_vgic_device Andre Przywara
2016-07-13 1:58 ` Andre Przywara
2016-07-13 1:58 ` [PATCH v9 03/17] KVM: extend struct kvm_msi to hold a 32-bit device ID Andre Przywara
2016-07-13 1:58 ` Andre Przywara
2016-07-13 10:28 ` Paolo Bonzini
2016-07-13 10:28 ` Paolo Bonzini
2016-07-13 1:58 ` [PATCH v9 04/17] KVM: arm/arm64: extend arch CAP checks to allow per-VM capabilities Andre Przywara
2016-07-13 1:58 ` Andre Przywara
2016-07-13 1:58 ` [PATCH v9 05/17] KVM: kvm_io_bus: add kvm_io_bus_get_dev() call Andre Przywara
2016-07-13 1:58 ` Andre Przywara
2016-07-13 10:29 ` Paolo Bonzini
2016-07-13 10:29 ` Paolo Bonzini
2016-07-13 1:58 ` [PATCH v9 06/17] KVM: arm/arm64: VGIC: add refcounting for IRQs Andre Przywara
2016-07-13 1:58 ` Andre Przywara
2016-07-13 12:15 ` Marc Zyngier
2016-07-13 12:15 ` Marc Zyngier
2016-07-13 13:50 ` Andre Przywara
2016-07-13 13:50 ` Andre Przywara
2016-07-13 1:58 ` [PATCH v9 07/17] irqchip: refactor and add GICv3 definitions Andre Przywara
2016-07-13 1:58 ` Andre Przywara
2016-07-13 12:28 ` Marc Zyngier
2016-07-13 12:28 ` Marc Zyngier
2016-07-13 1:59 ` [PATCH v9 08/17] KVM: arm64: handle ITS related GICv3 redistributor registers Andre Przywara
2016-07-13 1:59 ` Andre Przywara
2016-07-13 1:59 ` [PATCH v9 09/17] KVM: arm64: introduce ITS emulation file with MMIO framework Andre Przywara
2016-07-13 1:59 ` Andre Przywara
2016-07-13 1:59 ` [PATCH v9 10/17] KVM: arm64: introduce new KVM ITS device Andre Przywara
2016-07-13 1:59 ` Andre Przywara
2016-07-14 8:36 ` Marc Zyngier [this message]
2016-07-14 8:36 ` Marc Zyngier
2016-07-14 11:11 ` Andre Przywara
2016-07-14 11:11 ` Andre Przywara
2016-07-14 12:57 ` Marc Zyngier
2016-07-14 12:57 ` Marc Zyngier
2016-07-15 9:33 ` Andre Przywara
2016-07-15 9:33 ` Andre Przywara
2016-07-13 1:59 ` [PATCH v9 11/17] KVM: arm64: implement basic ITS register handlers Andre Przywara
2016-07-13 1:59 ` Andre Przywara
2016-07-14 9:13 ` Marc Zyngier
2016-07-14 9:13 ` Marc Zyngier
2016-07-13 1:59 ` [PATCH v9 12/17] KVM: arm64: connect LPIs to the VGIC emulation Andre Przywara
2016-07-13 1:59 ` Andre Przywara
2016-07-13 1:59 ` [PATCH v9 13/17] KVM: arm64: read initial LPI pending table Andre Przywara
2016-07-13 1:59 ` Andre Przywara
2016-07-14 9:34 ` Marc Zyngier
2016-07-14 9:34 ` Marc Zyngier
2016-07-14 10:16 ` Andre Przywara
2016-07-14 10:16 ` Andre Przywara
2016-07-13 1:59 ` [PATCH v9 14/17] KVM: arm64: allow updates of LPI configuration table Andre Przywara
2016-07-13 1:59 ` Andre Przywara
2016-07-14 9:46 ` Marc Zyngier
2016-07-14 9:46 ` Marc Zyngier
2016-07-14 10:00 ` Andre Przywara
2016-07-14 10:00 ` Andre Przywara
2016-07-14 10:10 ` Marc Zyngier
2016-07-14 10:10 ` Marc Zyngier
2016-07-13 1:59 ` [PATCH v9 15/17] KVM: arm64: implement ITS command queue command handlers Andre Przywara
2016-07-13 1:59 ` Andre Przywara
2016-07-14 10:38 ` Marc Zyngier
2016-07-14 10:38 ` Marc Zyngier
2016-07-14 15:35 ` Andre Przywara
2016-07-14 15:35 ` Andre Przywara
2016-07-14 16:33 ` Marc Zyngier
2016-07-14 16:33 ` Marc Zyngier
2016-07-15 8:19 ` Marc Zyngier
2016-07-15 8:19 ` Marc Zyngier
2016-07-13 1:59 ` [PATCH v9 16/17] KVM: arm64: implement MSI injection in ITS emulation Andre Przywara
2016-07-13 1:59 ` Andre Przywara
2016-07-13 1:59 ` [PATCH v9 17/17] KVM: arm64: enable ITS emulation as a virtual MSI controller Andre Przywara
2016-07-13 1:59 ` Andre Przywara
2016-07-13 7:57 ` [PATCH v9 00/17] KVM: arm64: GICv3 ITS emulation Diana Madalina Craciun
2016-07-13 7:57 ` Diana Madalina Craciun
2016-07-13 8:15 ` Andre Przywara
2016-07-13 8:15 ` Andre Przywara
2016-07-14 10:52 ` Marc Zyngier
2016-07-14 10:52 ` Marc Zyngier
2016-07-14 11:01 ` Paolo Bonzini
2016-07-14 11:01 ` Paolo Bonzini
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=57874F1E.3000202@arm.com \
--to=marc.zyngier@arm.com \
--cc=andre.przywara@arm.com \
--cc=christoffer.dall@linaro.org \
--cc=eric.auger@redhat.com \
--cc=kvm@vger.kernel.org \
--cc=kvmarm@lists.cs.columbia.edu \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.