* [PATCH 1/7] KVM: arm-vgic: Support KVM_CREATE_DEVICE for VGIC
2013-06-11 4:51 [PATCH 0/7] KVM: arm-vgic: Implement save/restore of VGIC state Christoffer Dall
@ 2013-06-11 4:51 ` Christoffer Dall
2013-06-18 13:21 ` Alexander Graf
2013-06-11 4:51 ` [PATCH 2/7] KVM: arm-vgic: Set base addr through device API Christoffer Dall
` (6 subsequent siblings)
7 siblings, 1 reply; 14+ messages in thread
From: Christoffer Dall @ 2013-06-11 4:51 UTC (permalink / raw)
To: linux-arm-kernel
Support creating the ARM VGIC device through the KVM_CREATE_DEVICE
ioctl, which can then later be leveraged to use the
KVM_{GET/SET}_DEVICE_ATTR, which is useful both for setting addresses in
a more generic API than the ARM-specific one and is useful for
save/restore of VGIC state.
Adds KVM_CAP_DEVICE_CTRL to ARM capabilities.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
Documentation/virtual/kvm/devices/arm-vgic.txt | 10 +++++++
arch/arm/include/uapi/asm/kvm.h | 8 ++++++
arch/arm/kvm/arm.c | 1 +
include/linux/kvm_host.h | 1 +
include/uapi/linux/kvm.h | 1 +
virt/kvm/arm/vgic.c | 34 ++++++++++++++++++++++++
virt/kvm/kvm_main.c | 4 +++
7 files changed, 59 insertions(+)
create mode 100644 Documentation/virtual/kvm/devices/arm-vgic.txt
diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
new file mode 100644
index 0000000..25fd2d9
--- /dev/null
+++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
@@ -0,0 +1,10 @@
+MPIC interrupt controller
+=========================
+
+Device types supported:
+ KVM_DEV_TYPE_ARM_VGIC ARM Generic Interrupt Controller v2.0
+
+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.
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index c1ee007..587f1ae 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -142,6 +142,14 @@ struct kvm_arch_memory_slot {
#define KVM_REG_ARM_VFP_FPINST 0x1009
#define KVM_REG_ARM_VFP_FPINST2 0x100A
+/* Device Control API: ARM VGIC */
+#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
+#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
+#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
+#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
+#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
+#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
+#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
/* KVM_IRQ_LINE irq field index values */
#define KVM_ARM_IRQ_TYPE_SHIFT 24
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 741f66a..b8e3b6e 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -187,6 +187,7 @@ int kvm_dev_ioctl_check_extension(long ext)
case KVM_CAP_IRQCHIP:
r = vgic_present;
break;
+ case KVM_CAP_DEVICE_CTRL:
case KVM_CAP_USER_MEMORY:
case KVM_CAP_SYNC_MMU:
case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index d9a3c30..e2d6556 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1086,6 +1086,7 @@ struct kvm_device *kvm_device_from_filp(struct file *filp);
extern struct kvm_device_ops kvm_mpic_ops;
extern struct kvm_device_ops kvm_xics_ops;
+extern struct kvm_device_ops kvm_arm_vgic_ops;
#ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index a5c86fc..4f2a4ab 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -839,6 +839,7 @@ struct kvm_device_attr {
#define KVM_DEV_TYPE_FSL_MPIC_20 1
#define KVM_DEV_TYPE_FSL_MPIC_42 2
#define KVM_DEV_TYPE_XICS 3
+#define KVM_DEV_TYPE_ARM_VGIC 4
/*
* ioctls for VM fds
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 17c5ac7..b3dcd66 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1497,3 +1497,37 @@ int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr)
mutex_unlock(&kvm->lock);
return r;
}
+
+static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+ return -ENXIO;
+}
+
+static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+ return -ENXIO;
+}
+
+static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
+{
+ return -ENXIO;
+}
+
+static void vgic_destroy(struct kvm_device *dev)
+{
+ kfree(dev);
+}
+
+static int vgic_create(struct kvm_device *dev, u32 type)
+{
+ return kvm_vgic_create(dev->kvm);
+}
+
+struct kvm_device_ops kvm_arm_vgic_ops = {
+ .name = "kvm-arm-vgic",
+ .create = vgic_create,
+ .destroy = vgic_destroy,
+ .set_attr = vgic_set_attr,
+ .get_attr = vgic_get_attr,
+ .has_attr = vgic_has_attr,
+};
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index b547a1c..774e77c 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -2282,6 +2282,10 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
ops = &kvm_xics_ops;
break;
#endif
+#ifdef CONFIG_KVM_ARM_VGIC
+ case KVM_DEV_TYPE_ARM_VGIC:
+ ops = &kvm_arm_vgic_ops;
+#endif
default:
return -ENODEV;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 1/7] KVM: arm-vgic: Support KVM_CREATE_DEVICE for VGIC
2013-06-11 4:51 ` [PATCH 1/7] KVM: arm-vgic: Support KVM_CREATE_DEVICE for VGIC Christoffer Dall
@ 2013-06-18 13:21 ` Alexander Graf
2013-06-18 15:44 ` Christoffer Dall
0 siblings, 1 reply; 14+ messages in thread
From: Alexander Graf @ 2013-06-18 13:21 UTC (permalink / raw)
To: linux-arm-kernel
Am 11.06.2013 um 06:51 schrieb Christoffer Dall <christoffer.dall@linaro.org>:
> Support creating the ARM VGIC device through the KVM_CREATE_DEVICE
> ioctl, which can then later be leveraged to use the
> KVM_{GET/SET}_DEVICE_ATTR, which is useful both for setting addresses in
> a more generic API than the ARM-specific one and is useful for
> save/restore of VGIC state.
>
> Adds KVM_CAP_DEVICE_CTRL to ARM capabilities.
>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> ---
> Documentation/virtual/kvm/devices/arm-vgic.txt | 10 +++++++
> arch/arm/include/uapi/asm/kvm.h | 8 ++++++
> arch/arm/kvm/arm.c | 1 +
> include/linux/kvm_host.h | 1 +
> include/uapi/linux/kvm.h | 1 +
> virt/kvm/arm/vgic.c | 34 ++++++++++++++++++++++++
> virt/kvm/kvm_main.c | 4 +++
> 7 files changed, 59 insertions(+)
> create mode 100644 Documentation/virtual/kvm/devices/arm-vgic.txt
>
> diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
> new file mode 100644
> index 0000000..25fd2d9
> --- /dev/null
> +++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
> @@ -0,0 +1,10 @@
> +MPIC interrupt controller
MPIC?
> +=========================
> +
> +Device types supported:
> + KVM_DEV_TYPE_ARM_VGIC ARM Generic Interrupt Controller v2.0
> +
> +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.
> diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
> index c1ee007..587f1ae 100644
> --- a/arch/arm/include/uapi/asm/kvm.h
> +++ b/arch/arm/include/uapi/asm/kvm.h
> @@ -142,6 +142,14 @@ struct kvm_arch_memory_slot {
> #define KVM_REG_ARM_VFP_FPINST 0x1009
> #define KVM_REG_ARM_VFP_FPINST2 0x100A
>
> +/* Device Control API: ARM VGIC */
> +#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
> +#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
> +#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
> +#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
> +#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
> +#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
> +#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
Could you please describe the groups in the documentation too?
>
> /* KVM_IRQ_LINE irq field index values */
> #define KVM_ARM_IRQ_TYPE_SHIFT 24
> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> index 741f66a..b8e3b6e 100644
> --- a/arch/arm/kvm/arm.c
> +++ b/arch/arm/kvm/arm.c
> @@ -187,6 +187,7 @@ int kvm_dev_ioctl_check_extension(long ext)
> case KVM_CAP_IRQCHIP:
> r = vgic_present;
> break;
> + case KVM_CAP_DEVICE_CTRL:
> case KVM_CAP_USER_MEMORY:
> case KVM_CAP_SYNC_MMU:
> case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index d9a3c30..e2d6556 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -1086,6 +1086,7 @@ struct kvm_device *kvm_device_from_filp(struct file *filp);
>
> extern struct kvm_device_ops kvm_mpic_ops;
> extern struct kvm_device_ops kvm_xics_ops;
> +extern struct kvm_device_ops kvm_arm_vgic_ops;
>
> #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT
>
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index a5c86fc..4f2a4ab 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -839,6 +839,7 @@ struct kvm_device_attr {
> #define KVM_DEV_TYPE_FSL_MPIC_20 1
> #define KVM_DEV_TYPE_FSL_MPIC_42 2
> #define KVM_DEV_TYPE_XICS 3
> +#define KVM_DEV_TYPE_ARM_VGIC 4
Should this be versioned? Gicv2 is different from v3, no?
Alex
>
> /*
> * ioctls for VM fds
> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
> index 17c5ac7..b3dcd66 100644
> --- a/virt/kvm/arm/vgic.c
> +++ b/virt/kvm/arm/vgic.c
> @@ -1497,3 +1497,37 @@ int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr)
> mutex_unlock(&kvm->lock);
> return r;
> }
> +
> +static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
> +{
> + return -ENXIO;
> +}
> +
> +static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
> +{
> + return -ENXIO;
> +}
> +
> +static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
> +{
> + return -ENXIO;
> +}
> +
> +static void vgic_destroy(struct kvm_device *dev)
> +{
> + kfree(dev);
> +}
> +
> +static int vgic_create(struct kvm_device *dev, u32 type)
> +{
> + return kvm_vgic_create(dev->kvm);
> +}
> +
> +struct kvm_device_ops kvm_arm_vgic_ops = {
> + .name = "kvm-arm-vgic",
> + .create = vgic_create,
> + .destroy = vgic_destroy,
> + .set_attr = vgic_set_attr,
> + .get_attr = vgic_get_attr,
> + .has_attr = vgic_has_attr,
> +};
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index b547a1c..774e77c 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -2282,6 +2282,10 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
> ops = &kvm_xics_ops;
> break;
> #endif
> +#ifdef CONFIG_KVM_ARM_VGIC
> + case KVM_DEV_TYPE_ARM_VGIC:
> + ops = &kvm_arm_vgic_ops;
> +#endif
> default:
> return -ENODEV;
> }
> --
> 1.7.9.5
>
> _______________________________________________
> kvmarm mailing list
> kvmarm at lists.cs.columbia.edu
> https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 1/7] KVM: arm-vgic: Support KVM_CREATE_DEVICE for VGIC
2013-06-18 13:21 ` Alexander Graf
@ 2013-06-18 15:44 ` Christoffer Dall
0 siblings, 0 replies; 14+ messages in thread
From: Christoffer Dall @ 2013-06-18 15:44 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Jun 18, 2013 at 03:21:38PM +0200, Alexander Graf wrote:
>
>
> Am 11.06.2013 um 06:51 schrieb Christoffer Dall <christoffer.dall@linaro.org>:
>
> > Support creating the ARM VGIC device through the KVM_CREATE_DEVICE
> > ioctl, which can then later be leveraged to use the
> > KVM_{GET/SET}_DEVICE_ATTR, which is useful both for setting addresses in
> > a more generic API than the ARM-specific one and is useful for
> > save/restore of VGIC state.
> >
> > Adds KVM_CAP_DEVICE_CTRL to ARM capabilities.
> >
> > Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> > ---
> > Documentation/virtual/kvm/devices/arm-vgic.txt | 10 +++++++
> > arch/arm/include/uapi/asm/kvm.h | 8 ++++++
> > arch/arm/kvm/arm.c | 1 +
> > include/linux/kvm_host.h | 1 +
> > include/uapi/linux/kvm.h | 1 +
> > virt/kvm/arm/vgic.c | 34 ++++++++++++++++++++++++
> > virt/kvm/kvm_main.c | 4 +++
> > 7 files changed, 59 insertions(+)
> > create mode 100644 Documentation/virtual/kvm/devices/arm-vgic.txt
> >
> > diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
> > new file mode 100644
> > index 0000000..25fd2d9
> > --- /dev/null
> > +++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
> > @@ -0,0 +1,10 @@
> > +MPIC interrupt controller
>
> MPIC?
>
yes, ARM MPIC, haven't heard of it?
> > +=========================
> > +
> > +Device types supported:
> > + KVM_DEV_TYPE_ARM_VGIC ARM Generic Interrupt Controller v2.0
> > +
> > +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.
> > diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
> > index c1ee007..587f1ae 100644
> > --- a/arch/arm/include/uapi/asm/kvm.h
> > +++ b/arch/arm/include/uapi/asm/kvm.h
> > @@ -142,6 +142,14 @@ struct kvm_arch_memory_slot {
> > #define KVM_REG_ARM_VFP_FPINST 0x1009
> > #define KVM_REG_ARM_VFP_FPINST2 0x100A
> >
> > +/* Device Control API: ARM VGIC */
> > +#define KVM_DEV_ARM_VGIC_GRP_ADDR 0
> > +#define KVM_DEV_ARM_VGIC_GRP_DIST_REGS 1
> > +#define KVM_DEV_ARM_VGIC_GRP_CPU_REGS 2
> > +#define KVM_DEV_ARM_VGIC_CPUID_SHIFT 32
> > +#define KVM_DEV_ARM_VGIC_CPUID_MASK (0xffULL << KVM_DEV_ARM_VGIC_CPUID_SHIFT)
> > +#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
> > +#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
>
> Could you please describe the groups in the documentation too?
>
these defines can go in the other patch
> >
> > /* KVM_IRQ_LINE irq field index values */
> > #define KVM_ARM_IRQ_TYPE_SHIFT 24
> > diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> > index 741f66a..b8e3b6e 100644
> > --- a/arch/arm/kvm/arm.c
> > +++ b/arch/arm/kvm/arm.c
> > @@ -187,6 +187,7 @@ int kvm_dev_ioctl_check_extension(long ext)
> > case KVM_CAP_IRQCHIP:
> > r = vgic_present;
> > break;
> > + case KVM_CAP_DEVICE_CTRL:
> > case KVM_CAP_USER_MEMORY:
> > case KVM_CAP_SYNC_MMU:
> > case KVM_CAP_DESTROY_MEMORY_REGION_WORKS:
> > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> > index d9a3c30..e2d6556 100644
> > --- a/include/linux/kvm_host.h
> > +++ b/include/linux/kvm_host.h
> > @@ -1086,6 +1086,7 @@ struct kvm_device *kvm_device_from_filp(struct file *filp);
> >
> > extern struct kvm_device_ops kvm_mpic_ops;
> > extern struct kvm_device_ops kvm_xics_ops;
> > +extern struct kvm_device_ops kvm_arm_vgic_ops;
> >
> > #ifdef CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT
> >
> > diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> > index a5c86fc..4f2a4ab 100644
> > --- a/include/uapi/linux/kvm.h
> > +++ b/include/uapi/linux/kvm.h
> > @@ -839,6 +839,7 @@ struct kvm_device_attr {
> > #define KVM_DEV_TYPE_FSL_MPIC_20 1
> > #define KVM_DEV_TYPE_FSL_MPIC_42 2
> > #define KVM_DEV_TYPE_XICS 3
> > +#define KVM_DEV_TYPE_ARM_VGIC 4
>
> Should this be versioned? Gicv2 is different from v3, no?
>
yes, we can call it all XXX_VGIC_V2. It just becomes so verbose, but
it's really the right thing to do.
> Alex
>
> >
> > /*
> > * ioctls for VM fds
> > diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
> > index 17c5ac7..b3dcd66 100644
> > --- a/virt/kvm/arm/vgic.c
> > +++ b/virt/kvm/arm/vgic.c
> > @@ -1497,3 +1497,37 @@ int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr)
> > mutex_unlock(&kvm->lock);
> > return r;
> > }
> > +
> > +static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
> > +{
> > + return -ENXIO;
> > +}
> > +
> > +static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
> > +{
> > + return -ENXIO;
> > +}
> > +
> > +static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
> > +{
> > + return -ENXIO;
> > +}
> > +
> > +static void vgic_destroy(struct kvm_device *dev)
> > +{
> > + kfree(dev);
> > +}
> > +
> > +static int vgic_create(struct kvm_device *dev, u32 type)
> > +{
> > + return kvm_vgic_create(dev->kvm);
> > +}
> > +
> > +struct kvm_device_ops kvm_arm_vgic_ops = {
> > + .name = "kvm-arm-vgic",
> > + .create = vgic_create,
> > + .destroy = vgic_destroy,
> > + .set_attr = vgic_set_attr,
> > + .get_attr = vgic_get_attr,
> > + .has_attr = vgic_has_attr,
> > +};
> > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> > index b547a1c..774e77c 100644
> > --- a/virt/kvm/kvm_main.c
> > +++ b/virt/kvm/kvm_main.c
> > @@ -2282,6 +2282,10 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
> > ops = &kvm_xics_ops;
> > break;
> > #endif
> > +#ifdef CONFIG_KVM_ARM_VGIC
> > + case KVM_DEV_TYPE_ARM_VGIC:
> > + ops = &kvm_arm_vgic_ops;
> > +#endif
> > default:
> > return -ENODEV;
> > }
> > --
> > 1.7.9.5
> >
> > _______________________________________________
> > kvmarm mailing list
> > kvmarm at lists.cs.columbia.edu
> > https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/7] KVM: arm-vgic: Set base addr through device API
2013-06-11 4:51 [PATCH 0/7] KVM: arm-vgic: Implement save/restore of VGIC state Christoffer Dall
2013-06-11 4:51 ` [PATCH 1/7] KVM: arm-vgic: Support KVM_CREATE_DEVICE for VGIC Christoffer Dall
@ 2013-06-11 4:51 ` Christoffer Dall
2013-06-18 13:25 ` Alexander Graf
2013-06-11 4:51 ` [PATCH 3/7] irqchip: arm-gic: Define additional MMIO offsets and masks Christoffer Dall
` (5 subsequent siblings)
7 siblings, 1 reply; 14+ messages in thread
From: Christoffer Dall @ 2013-06-11 4:51 UTC (permalink / raw)
To: linux-arm-kernel
Support setting the distributor and cpu interface base addresses in the
VM physical address space through the KVM_{SET,GET}_DEVICE_ATTR API
in addition the ARM specific API.
This has the added benefit of being able to share more code in user
space and do things in a uniform maner.
Also deprecate the older API at the same time, but backwards
compatibility will be maintained.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
Documentation/virtual/kvm/api.txt | 5 +-
Documentation/virtual/kvm/devices/arm-vgic.txt | 11 +++
arch/arm/kvm/arm.c | 2 +-
include/kvm/arm_vgic.h | 2 +-
virt/kvm/arm/vgic.c | 90 ++++++++++++++++++++----
5 files changed, 95 insertions(+), 15 deletions(-)
diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 5f91eda..ea5ec4a 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2305,7 +2305,7 @@ This ioctl returns the guest registers that are supported for the
KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
-4.80 KVM_ARM_SET_DEVICE_ADDR
+4.80 KVM_ARM_SET_DEVICE_ADDR (deprecated)
Capability: KVM_CAP_ARM_SET_DEVICE_ADDR
Architectures: arm
@@ -2342,6 +2342,9 @@ and distributor interface, the ioctl must be called after calling
KVM_CREATE_IRQCHIP, but before calling KVM_RUN on any of the VCPUs. Calling
this ioctl twice for any of the base addresses will return -EEXIST.
+Note, this IOCTL is deprecated and the more flexible SET/GET_DEVICE_ATTR API
+should be used instead.
+
4.82 KVM_PPC_RTAS_DEFINE_TOKEN
Capability: KVM_CAP_PPC_RTAS
diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
index 25fd2d9..ca83ad8 100644
--- a/Documentation/virtual/kvm/devices/arm-vgic.txt
+++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
@@ -8,3 +8,14 @@ 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.
+
+Groups:
+ KVM_DEV_ARM_VGIC_GRP_ADDR
+ Attributes:
+ KVM_VGIC_V2_ADDR_TYPE_DIST (rw, 64-bit)
+ Base address in the guest physical address space of the GIC distributor
+ register mappings.
+
+ KVM_VGIC_V2_ADDR_TYPE_CPU (rw, 64-bit)
+ Base address in the guest physical address space of the GIC virtual cpu
+ interface register mappings.
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index b8e3b6e..63ddccb 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -768,7 +768,7 @@ static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm,
case KVM_ARM_DEVICE_VGIC_V2:
if (!vgic_present)
return -ENXIO;
- return kvm_vgic_set_addr(kvm, type, dev_addr->addr);
+ return kvm_vgic_addr(kvm, type, &dev_addr->addr, true);
default:
return -ENODEV;
}
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 343744e..5631cfa 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -144,7 +144,7 @@ struct kvm_run;
struct kvm_exit_mmio;
#ifdef CONFIG_KVM_ARM_VGIC
-int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr);
+int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
int kvm_vgic_hyp_init(void);
int kvm_vgic_init(struct kvm *kvm);
int kvm_vgic_create(struct kvm *kvm);
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index b3dcd66..8e915b7 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1457,6 +1457,12 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
{
int ret;
+ if (addr & ~KVM_PHYS_MASK)
+ return -E2BIG;
+
+ if (addr & (SZ_4K - 1))
+ return -EINVAL;
+
if (!IS_VGIC_ADDR_UNDEF(*ioaddr))
return -EEXIST;
if (addr + size < addr)
@@ -1469,26 +1475,41 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
return ret;
}
-int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr)
+/**
+ * kvm_vgic_addr - set or get vgic VM base addresses
+ * @kvm: pointer to the vm struct
+ * @type: the VGIC addr type, one of KVM_VGIC_V2_ADDR_TYPE_XXX
+ * @addr: pointer to address value
+ * @write: if true set the address in the VM address space, if false read the
+ * address
+ *
+ * Set or get the vgic base addresses for the distributor and the virtual CPU
+ * interface in the VM physical address space. These addresses are properties
+ * of the emulated core/SoC and therefore user space initially knows this
+ * information.
+ */
+int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
{
int r = 0;
struct vgic_dist *vgic = &kvm->arch.vgic;
- if (addr & ~KVM_PHYS_MASK)
- return -E2BIG;
-
- if (addr & (SZ_4K - 1))
- return -EINVAL;
-
mutex_lock(&kvm->lock);
switch (type) {
case KVM_VGIC_V2_ADDR_TYPE_DIST:
- r = vgic_ioaddr_assign(kvm, &vgic->vgic_dist_base,
- addr, KVM_VGIC_V2_DIST_SIZE);
+ if (write) {
+ r = vgic_ioaddr_assign(kvm, &vgic->vgic_dist_base,
+ *addr, KVM_VGIC_V2_DIST_SIZE);
+ } else {
+ *addr = vgic->vgic_dist_base;
+ }
break;
case KVM_VGIC_V2_ADDR_TYPE_CPU:
- r = vgic_ioaddr_assign(kvm, &vgic->vgic_cpu_base,
- addr, KVM_VGIC_V2_CPU_SIZE);
+ if (write) {
+ r = vgic_ioaddr_assign(kvm, &vgic->vgic_cpu_base,
+ *addr, KVM_VGIC_V2_CPU_SIZE);
+ } else {
+ *addr = vgic->vgic_cpu_base;
+ }
break;
default:
r = -ENODEV;
@@ -1500,16 +1521,61 @@ int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr)
static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
{
+ int r;
+
+ switch (attr->group) {
+ case KVM_DEV_ARM_VGIC_GRP_ADDR: {
+ u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+ u64 addr;
+ unsigned long type = (unsigned long)attr->attr;
+
+ if (copy_from_user(&addr, uaddr, sizeof(addr)))
+ return -EFAULT;
+
+ r = kvm_vgic_addr(dev->kvm, type, &addr, true);
+ return (r == -ENODEV) ? -ENXIO : r;
+ }
+ }
+
return -ENXIO;
}
static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
{
- return -ENXIO;
+ int r = ENXIO;
+
+ switch (attr->group) {
+ case KVM_DEV_ARM_VGIC_GRP_ADDR: {
+ u64 __user *uaddr = (u64 __user *)(long)attr->addr;
+ u64 addr;
+ unsigned long type = (unsigned long)attr->attr;
+
+ r = kvm_vgic_addr(dev->kvm, type, &addr, false);
+ if (r)
+ return (r == -ENODEV) ? -ENXIO : r;
+
+ r = 0;
+ if (copy_to_user(uaddr, &addr, sizeof(addr)))
+ return -EFAULT;
+ }
+ }
+
+ return r;
}
static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
{
+ phys_addr_t offset;
+
+ switch (attr->group) {
+ case KVM_DEV_ARM_VGIC_GRP_ADDR:
+ switch (attr->attr) {
+ case KVM_VGIC_V2_ADDR_TYPE_DIST:
+ case KVM_VGIC_V2_ADDR_TYPE_CPU:
+ return 0;
+ }
+ break;
+ }
return -ENXIO;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/7] KVM: arm-vgic: Set base addr through device API
2013-06-11 4:51 ` [PATCH 2/7] KVM: arm-vgic: Set base addr through device API Christoffer Dall
@ 2013-06-18 13:25 ` Alexander Graf
2013-06-18 15:46 ` Christoffer Dall
0 siblings, 1 reply; 14+ messages in thread
From: Alexander Graf @ 2013-06-18 13:25 UTC (permalink / raw)
To: linux-arm-kernel
Am 11.06.2013 um 06:51 schrieb Christoffer Dall <christoffer.dall@linaro.org>:
> Support setting the distributor and cpu interface base addresses in the
> VM physical address space through the KVM_{SET,GET}_DEVICE_ATTR API
> in addition the ARM specific API.
>
> This has the added benefit of being able to share more code in user
> space and do things in a uniform maner.
>
> Also deprecate the older API at the same time, but backwards
> compatibility will be maintained.
>
> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> ---
> Documentation/virtual/kvm/api.txt | 5 +-
> Documentation/virtual/kvm/devices/arm-vgic.txt | 11 +++
> arch/arm/kvm/arm.c | 2 +-
> include/kvm/arm_vgic.h | 2 +-
> virt/kvm/arm/vgic.c | 90 ++++++++++++++++++++----
> 5 files changed, 95 insertions(+), 15 deletions(-)
>
> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> index 5f91eda..ea5ec4a 100644
> --- a/Documentation/virtual/kvm/api.txt
> +++ b/Documentation/virtual/kvm/api.txt
> @@ -2305,7 +2305,7 @@ This ioctl returns the guest registers that are supported for the
> KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
>
>
> -4.80 KVM_ARM_SET_DEVICE_ADDR
> +4.80 KVM_ARM_SET_DEVICE_ADDR (deprecated)
>
> Capability: KVM_CAP_ARM_SET_DEVICE_ADDR
> Architectures: arm
> @@ -2342,6 +2342,9 @@ and distributor interface, the ioctl must be called after calling
> KVM_CREATE_IRQCHIP, but before calling KVM_RUN on any of the VCPUs. Calling
> this ioctl twice for any of the base addresses will return -EEXIST.
>
> +Note, this IOCTL is deprecated and the more flexible SET/GET_DEVICE_ATTR API
> +should be used instead.
> +
> 4.82 KVM_PPC_RTAS_DEFINE_TOKEN
>
> Capability: KVM_CAP_PPC_RTAS
> diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
> index 25fd2d9..ca83ad8 100644
> --- a/Documentation/virtual/kvm/devices/arm-vgic.txt
> +++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
> @@ -8,3 +8,14 @@ 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.
> +
> +Groups:
Ah, here they are :)
> + KVM_DEV_ARM_VGIC_GRP_ADDR
> + Attributes:
> + KVM_VGIC_V2_ADDR_TYPE_DIST (rw, 64-bit)
> + Base address in the guest physical address space of the GIC distributor
> + register mappings.
> +
> + KVM_VGIC_V2_ADDR_TYPE_CPU (rw, 64-bit)
> + Base address in the guest physical address space of the GIC virtual cpu
> + interface register mappings.
Is this per-cpu or per-vgic? Can different CPUs have their gic interface maps mapped at different offsets?
Alex
> diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
> index b8e3b6e..63ddccb 100644
> --- a/arch/arm/kvm/arm.c
> +++ b/arch/arm/kvm/arm.c
> @@ -768,7 +768,7 @@ static int kvm_vm_ioctl_set_device_addr(struct kvm *kvm,
> case KVM_ARM_DEVICE_VGIC_V2:
> if (!vgic_present)
> return -ENXIO;
> - return kvm_vgic_set_addr(kvm, type, dev_addr->addr);
> + return kvm_vgic_addr(kvm, type, &dev_addr->addr, true);
> default:
> return -ENODEV;
> }
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 343744e..5631cfa 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -144,7 +144,7 @@ struct kvm_run;
> struct kvm_exit_mmio;
>
> #ifdef CONFIG_KVM_ARM_VGIC
> -int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr);
> +int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
> int kvm_vgic_hyp_init(void);
> int kvm_vgic_init(struct kvm *kvm);
> int kvm_vgic_create(struct kvm *kvm);
> diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
> index b3dcd66..8e915b7 100644
> --- a/virt/kvm/arm/vgic.c
> +++ b/virt/kvm/arm/vgic.c
> @@ -1457,6 +1457,12 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
> {
> int ret;
>
> + if (addr & ~KVM_PHYS_MASK)
> + return -E2BIG;
> +
> + if (addr & (SZ_4K - 1))
> + return -EINVAL;
> +
> if (!IS_VGIC_ADDR_UNDEF(*ioaddr))
> return -EEXIST;
> if (addr + size < addr)
> @@ -1469,26 +1475,41 @@ static int vgic_ioaddr_assign(struct kvm *kvm, phys_addr_t *ioaddr,
> return ret;
> }
>
> -int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr)
> +/**
> + * kvm_vgic_addr - set or get vgic VM base addresses
> + * @kvm: pointer to the vm struct
> + * @type: the VGIC addr type, one of KVM_VGIC_V2_ADDR_TYPE_XXX
> + * @addr: pointer to address value
> + * @write: if true set the address in the VM address space, if false read the
> + * address
> + *
> + * Set or get the vgic base addresses for the distributor and the virtual CPU
> + * interface in the VM physical address space. These addresses are properties
> + * of the emulated core/SoC and therefore user space initially knows this
> + * information.
> + */
> +int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
> {
> int r = 0;
> struct vgic_dist *vgic = &kvm->arch.vgic;
>
> - if (addr & ~KVM_PHYS_MASK)
> - return -E2BIG;
> -
> - if (addr & (SZ_4K - 1))
> - return -EINVAL;
> -
> mutex_lock(&kvm->lock);
> switch (type) {
> case KVM_VGIC_V2_ADDR_TYPE_DIST:
> - r = vgic_ioaddr_assign(kvm, &vgic->vgic_dist_base,
> - addr, KVM_VGIC_V2_DIST_SIZE);
> + if (write) {
> + r = vgic_ioaddr_assign(kvm, &vgic->vgic_dist_base,
> + *addr, KVM_VGIC_V2_DIST_SIZE);
> + } else {
> + *addr = vgic->vgic_dist_base;
> + }
> break;
> case KVM_VGIC_V2_ADDR_TYPE_CPU:
> - r = vgic_ioaddr_assign(kvm, &vgic->vgic_cpu_base,
> - addr, KVM_VGIC_V2_CPU_SIZE);
> + if (write) {
> + r = vgic_ioaddr_assign(kvm, &vgic->vgic_cpu_base,
> + *addr, KVM_VGIC_V2_CPU_SIZE);
> + } else {
> + *addr = vgic->vgic_cpu_base;
> + }
> break;
> default:
> r = -ENODEV;
> @@ -1500,16 +1521,61 @@ int kvm_vgic_set_addr(struct kvm *kvm, unsigned long type, u64 addr)
>
> static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
> {
> + int r;
> +
> + switch (attr->group) {
> + case KVM_DEV_ARM_VGIC_GRP_ADDR: {
> + u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> + u64 addr;
> + unsigned long type = (unsigned long)attr->attr;
> +
> + if (copy_from_user(&addr, uaddr, sizeof(addr)))
> + return -EFAULT;
> +
> + r = kvm_vgic_addr(dev->kvm, type, &addr, true);
> + return (r == -ENODEV) ? -ENXIO : r;
> + }
> + }
> +
> return -ENXIO;
> }
>
> static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
> {
> - return -ENXIO;
> + int r = ENXIO;
> +
> + switch (attr->group) {
> + case KVM_DEV_ARM_VGIC_GRP_ADDR: {
> + u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> + u64 addr;
> + unsigned long type = (unsigned long)attr->attr;
> +
> + r = kvm_vgic_addr(dev->kvm, type, &addr, false);
> + if (r)
> + return (r == -ENODEV) ? -ENXIO : r;
> +
> + r = 0;
> + if (copy_to_user(uaddr, &addr, sizeof(addr)))
> + return -EFAULT;
> + }
> + }
> +
> + return r;
> }
>
> static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
> {
> + phys_addr_t offset;
> +
> + switch (attr->group) {
> + case KVM_DEV_ARM_VGIC_GRP_ADDR:
> + switch (attr->attr) {
> + case KVM_VGIC_V2_ADDR_TYPE_DIST:
> + case KVM_VGIC_V2_ADDR_TYPE_CPU:
> + return 0;
> + }
> + break;
> + }
> return -ENXIO;
> }
>
> --
> 1.7.9.5
>
> _______________________________________________
> kvmarm mailing list
> kvmarm at lists.cs.columbia.edu
> https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/7] KVM: arm-vgic: Set base addr through device API
2013-06-18 13:25 ` Alexander Graf
@ 2013-06-18 15:46 ` Christoffer Dall
2013-06-18 15:51 ` Alexander Graf
0 siblings, 1 reply; 14+ messages in thread
From: Christoffer Dall @ 2013-06-18 15:46 UTC (permalink / raw)
To: linux-arm-kernel
On Tue, Jun 18, 2013 at 03:25:04PM +0200, Alexander Graf wrote:
>
>
> Am 11.06.2013 um 06:51 schrieb Christoffer Dall <christoffer.dall@linaro.org>:
>
> > Support setting the distributor and cpu interface base addresses in the
> > VM physical address space through the KVM_{SET,GET}_DEVICE_ATTR API
> > in addition the ARM specific API.
> >
> > This has the added benefit of being able to share more code in user
> > space and do things in a uniform maner.
> >
> > Also deprecate the older API at the same time, but backwards
> > compatibility will be maintained.
> >
> > Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
> > ---
> > Documentation/virtual/kvm/api.txt | 5 +-
> > Documentation/virtual/kvm/devices/arm-vgic.txt | 11 +++
> > arch/arm/kvm/arm.c | 2 +-
> > include/kvm/arm_vgic.h | 2 +-
> > virt/kvm/arm/vgic.c | 90 ++++++++++++++++++++----
> > 5 files changed, 95 insertions(+), 15 deletions(-)
> >
> > diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
> > index 5f91eda..ea5ec4a 100644
> > --- a/Documentation/virtual/kvm/api.txt
> > +++ b/Documentation/virtual/kvm/api.txt
> > @@ -2305,7 +2305,7 @@ This ioctl returns the guest registers that are supported for the
> > KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
> >
> >
> > -4.80 KVM_ARM_SET_DEVICE_ADDR
> > +4.80 KVM_ARM_SET_DEVICE_ADDR (deprecated)
> >
> > Capability: KVM_CAP_ARM_SET_DEVICE_ADDR
> > Architectures: arm
> > @@ -2342,6 +2342,9 @@ and distributor interface, the ioctl must be called after calling
> > KVM_CREATE_IRQCHIP, but before calling KVM_RUN on any of the VCPUs. Calling
> > this ioctl twice for any of the base addresses will return -EEXIST.
> >
> > +Note, this IOCTL is deprecated and the more flexible SET/GET_DEVICE_ATTR API
> > +should be used instead.
> > +
> > 4.82 KVM_PPC_RTAS_DEFINE_TOKEN
> >
> > Capability: KVM_CAP_PPC_RTAS
> > diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
> > index 25fd2d9..ca83ad8 100644
> > --- a/Documentation/virtual/kvm/devices/arm-vgic.txt
> > +++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
> > @@ -8,3 +8,14 @@ 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.
> > +
> > +Groups:
>
> Ah, here they are :)
>
> > + KVM_DEV_ARM_VGIC_GRP_ADDR
> > + Attributes:
> > + KVM_VGIC_V2_ADDR_TYPE_DIST (rw, 64-bit)
> > + Base address in the guest physical address space of the GIC distributor
> > + register mappings.
> > +
> > + KVM_VGIC_V2_ADDR_TYPE_CPU (rw, 64-bit)
> > + Base address in the guest physical address space of the GIC virtual cpu
> > + interface register mappings.
>
> Is this per-cpu or per-vgic? Can different CPUs have their gic interface maps mapped at different offsets?
>
This is per-vgic.
If the _CPU part is confusing, it means it's the address of the CPU
interface, as opposed to the Distributor interface. Individual CPUs
calculate their specific offset from this base address based on a mask,
but the base is common for everyone (and banked depending on the
accessing CPU for a certain region).
-Christoffer
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 2/7] KVM: arm-vgic: Set base addr through device API
2013-06-18 15:46 ` Christoffer Dall
@ 2013-06-18 15:51 ` Alexander Graf
0 siblings, 0 replies; 14+ messages in thread
From: Alexander Graf @ 2013-06-18 15:51 UTC (permalink / raw)
To: linux-arm-kernel
On 18.06.2013, at 17:46, Christoffer Dall wrote:
> On Tue, Jun 18, 2013 at 03:25:04PM +0200, Alexander Graf wrote:
>>
>>
>> Am 11.06.2013 um 06:51 schrieb Christoffer Dall <christoffer.dall@linaro.org>:
>>
>>> Support setting the distributor and cpu interface base addresses in the
>>> VM physical address space through the KVM_{SET,GET}_DEVICE_ATTR API
>>> in addition the ARM specific API.
>>>
>>> This has the added benefit of being able to share more code in user
>>> space and do things in a uniform maner.
>>>
>>> Also deprecate the older API at the same time, but backwards
>>> compatibility will be maintained.
>>>
>>> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
>>> ---
>>> Documentation/virtual/kvm/api.txt | 5 +-
>>> Documentation/virtual/kvm/devices/arm-vgic.txt | 11 +++
>>> arch/arm/kvm/arm.c | 2 +-
>>> include/kvm/arm_vgic.h | 2 +-
>>> virt/kvm/arm/vgic.c | 90 ++++++++++++++++++++----
>>> 5 files changed, 95 insertions(+), 15 deletions(-)
>>>
>>> diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
>>> index 5f91eda..ea5ec4a 100644
>>> --- a/Documentation/virtual/kvm/api.txt
>>> +++ b/Documentation/virtual/kvm/api.txt
>>> @@ -2305,7 +2305,7 @@ This ioctl returns the guest registers that are supported for the
>>> KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
>>>
>>>
>>> -4.80 KVM_ARM_SET_DEVICE_ADDR
>>> +4.80 KVM_ARM_SET_DEVICE_ADDR (deprecated)
>>>
>>> Capability: KVM_CAP_ARM_SET_DEVICE_ADDR
>>> Architectures: arm
>>> @@ -2342,6 +2342,9 @@ and distributor interface, the ioctl must be called after calling
>>> KVM_CREATE_IRQCHIP, but before calling KVM_RUN on any of the VCPUs. Calling
>>> this ioctl twice for any of the base addresses will return -EEXIST.
>>>
>>> +Note, this IOCTL is deprecated and the more flexible SET/GET_DEVICE_ATTR API
>>> +should be used instead.
>>> +
>>> 4.82 KVM_PPC_RTAS_DEFINE_TOKEN
>>>
>>> Capability: KVM_CAP_PPC_RTAS
>>> diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
>>> index 25fd2d9..ca83ad8 100644
>>> --- a/Documentation/virtual/kvm/devices/arm-vgic.txt
>>> +++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
>>> @@ -8,3 +8,14 @@ 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.
>>> +
>>> +Groups:
>>
>> Ah, here they are :)
>>
>>> + KVM_DEV_ARM_VGIC_GRP_ADDR
>>> + Attributes:
>>> + KVM_VGIC_V2_ADDR_TYPE_DIST (rw, 64-bit)
>>> + Base address in the guest physical address space of the GIC distributor
>>> + register mappings.
>>> +
>>> + KVM_VGIC_V2_ADDR_TYPE_CPU (rw, 64-bit)
>>> + Base address in the guest physical address space of the GIC virtual cpu
>>> + interface register mappings.
>>
>> Is this per-cpu or per-vgic? Can different CPUs have their gic interface maps mapped at different offsets?
>>
> This is per-vgic.
>
> If the _CPU part is confusing, it means it's the address of the CPU
> interface, as opposed to the Distributor interface. Individual CPUs
> calculate their specific offset from this base address based on a mask,
> but the base is common for everyone (and banked depending on the
> accessing CPU for a certain region).
Ah, that's perfectly fine then. On the MPIC this is part of the normal address space, so I was merely confused on why it has a separate offset. But I guess you can't argue about how hardware works ;).
Alex
^ permalink raw reply [flat|nested] 14+ messages in thread
* [PATCH 3/7] irqchip: arm-gic: Define additional MMIO offsets and masks
2013-06-11 4:51 [PATCH 0/7] KVM: arm-vgic: Implement save/restore of VGIC state Christoffer Dall
2013-06-11 4:51 ` [PATCH 1/7] KVM: arm-vgic: Support KVM_CREATE_DEVICE for VGIC Christoffer Dall
2013-06-11 4:51 ` [PATCH 2/7] KVM: arm-vgic: Set base addr through device API Christoffer Dall
@ 2013-06-11 4:51 ` Christoffer Dall
2013-06-11 4:51 ` [PATCH 4/7] KVM: arm-vgic: Make vgic mmio functions more generic Christoffer Dall
` (4 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Christoffer Dall @ 2013-06-11 4:51 UTC (permalink / raw)
To: linux-arm-kernel
Define CPU interface offsets for the GICC_ABPR, GICC_APR, and GICC_IIDR
registers. Define distributor registers for the GICD_SPENDSGIR and the
GICD_CPENDSGIR. KVM/ARM needs to know about these definitions to fully
support save/restore of the VGIC.
Also define some masks and shifts for the various GICH_VMCR fields.
Cc: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
include/linux/irqchip/arm-gic.h | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 3e203eb..e95c00e 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -17,6 +17,9 @@
#define GIC_CPU_EOI 0x10
#define GIC_CPU_RUNNINGPRI 0x14
#define GIC_CPU_HIGHPRI 0x18
+#define GIC_CPU_ALIAS_BINPOINT 0x1c
+#define GIC_CPU_ACTIVEPRIO 0xd0
+#define GIC_CPU_IDENT 0xfc
#define GIC_DIST_CTRL 0x000
#define GIC_DIST_CTR 0x004
@@ -31,6 +34,8 @@
#define GIC_DIST_TARGET 0x800
#define GIC_DIST_CONFIG 0xc00
#define GIC_DIST_SOFTINT 0xf00
+#define GIC_DIST_SGI_CLEAR 0xf10
+#define GIC_DIST_SGI_SET 0xf20
#define GICH_HCR 0x0
#define GICH_VTR 0x4
@@ -54,6 +59,15 @@
#define GICH_LR_ACTIVE_BIT (1 << 29)
#define GICH_LR_EOI (1 << 19)
+#define GICH_VMCR_CTRL_SHIFT 0
+#define GICH_VMCR_CTRL_MASK (0x21f << GICH_VMCR_CTRL_SHIFT)
+#define GICH_VMCR_PRIMASK_SHIFT 27
+#define GICH_VMCR_PRIMASK_MASK (0x1f << GICH_VMCR_PRIMASK_SHIFT)
+#define GICH_VMCR_BINPOINT_SHIFT 21
+#define GICH_VMCR_BINPOINT_MASK (0x7 << GICH_VMCR_BINPOINT_SHIFT)
+#define GICH_VMCR_ALIAS_BINPOINT_SHIFT 18
+#define GICH_VMCR_ALIAS_BINPOINT_MASK (0x7 << GICH_VMCR_ALIAS_BINPOINT_SHIFT)
+
#define GICH_MISR_EOI (1 << 0)
#define GICH_MISR_U (1 << 1)
--
1.7.9.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 4/7] KVM: arm-vgic: Make vgic mmio functions more generic
2013-06-11 4:51 [PATCH 0/7] KVM: arm-vgic: Implement save/restore of VGIC state Christoffer Dall
` (2 preceding siblings ...)
2013-06-11 4:51 ` [PATCH 3/7] irqchip: arm-gic: Define additional MMIO offsets and masks Christoffer Dall
@ 2013-06-11 4:51 ` Christoffer Dall
2013-06-11 4:51 ` [PATCH 5/7] KVM: arm-vgic: Add vgic reg access from dev attr Christoffer Dall
` (3 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Christoffer Dall @ 2013-06-11 4:51 UTC (permalink / raw)
To: linux-arm-kernel
Rename the vgic_ranges array to vgic_dist_ranges to be more specific and
to prepare for handling CPU interface register access as well (for
save/restore of VGIC state).
Pass offset from distributor or interface MMIO base to
find_matching_range function instead of the physical address of the
access in the VM memory map. This allows other callers unaware of the
VM specifics, but with generic VGIC knowledge to reuse the function.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
virt/kvm/arm/vgic.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 8e915b7..bfb9985 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -604,7 +604,7 @@ struct mmio_range {
phys_addr_t offset);
};
-static const struct mmio_range vgic_ranges[] = {
+static const struct mmio_range vgic_dist_ranges[] = {
{
.base = GIC_DIST_CTRL,
.len = 12,
@@ -671,14 +671,13 @@ static const struct mmio_range vgic_ranges[] = {
static const
struct mmio_range *find_matching_range(const struct mmio_range *ranges,
struct kvm_exit_mmio *mmio,
- phys_addr_t base)
+ phys_addr_t offset)
{
const struct mmio_range *r = ranges;
- phys_addr_t addr = mmio->phys_addr - base;
while (r->len) {
- if (addr >= r->base &&
- (addr + mmio->len) <= (r->base + r->len))
+ if (offset >= r->base &&
+ (offset + mmio->len) <= (r->base + r->len))
return r;
r++;
}
@@ -715,7 +714,8 @@ bool vgic_handle_mmio(struct kvm_vcpu *vcpu, struct kvm_run *run,
return true;
}
- range = find_matching_range(vgic_ranges, mmio, base);
+ offset = mmio->phys_addr - base;
+ range = find_matching_range(vgic_dist_ranges, mmio, offset);
if (unlikely(!range || !range->handle_mmio)) {
pr_warn("Unhandled access %d %08llx %d\n",
mmio->is_write, mmio->phys_addr, mmio->len);
--
1.7.9.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 5/7] KVM: arm-vgic: Add vgic reg access from dev attr
2013-06-11 4:51 [PATCH 0/7] KVM: arm-vgic: Implement save/restore of VGIC state Christoffer Dall
` (3 preceding siblings ...)
2013-06-11 4:51 ` [PATCH 4/7] KVM: arm-vgic: Make vgic mmio functions more generic Christoffer Dall
@ 2013-06-11 4:51 ` Christoffer Dall
2013-06-11 4:51 ` [PATCH 6/7] KVM: arm-vgic: Add GICD_SPENDSGIR and GICD_CPENDSGIR handlers Christoffer Dall
` (2 subsequent siblings)
7 siblings, 0 replies; 14+ messages in thread
From: Christoffer Dall @ 2013-06-11 4:51 UTC (permalink / raw)
To: linux-arm-kernel
Adds infrastructure to handle distributor and cpu interface register
accesses through the KVM_{GET/SET}_DEVICE_ATTR interface by adding the
KVM_DEV_ARM_VGIC_GRP_DIST_REGS and KVM_DEV_ARM_VGIC_GRP_CPU_REGS groups
and defining the semantics of the attr field to be the MMIO offset as
specified in the GICv2 specs.
This does not actually implement missing register accesses to let the
full VGIC state be accessible from user space, nor does it handle
potential situations where the existing handle_mmio functions are not
handling a save/restore scenario well enough, that will come in the
following patches.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
Documentation/virtual/kvm/devices/arm-vgic.txt | 31 +++++
virt/kvm/arm/vgic.c | 156 ++++++++++++++++++++++++
2 files changed, 187 insertions(+)
diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
index ca83ad8..0e70b2c 100644
--- a/Documentation/virtual/kvm/devices/arm-vgic.txt
+++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
@@ -19,3 +19,34 @@ Groups:
KVM_VGIC_V2_ADDR_TYPE_CPU (rw, 64-bit)
Base address in the guest physical address space of the GIC virtual cpu
interface register mappings.
+
+ KVM_DEV_ARM_VGIC_GRP_DIST_REGS
+ Attributes:
+ The attr field of kvm_device_attr encodes two values:
+ bits: | 63 .... 40 | 39 .. 32 | 31 .... 0 |
+ values: | reserved | cpu id | offset |
+
+ The offset is relative to the "Distributor base address" as defined in the
+ GICv2 specs. Getting or setting such a register has the same effect as
+ reading or writing the register on the actual hardware from the cpu
+ specified with cpu id field. Note that most distributor fields are not
+ banked, but return the same value regardless of the cpu id used to access
+ the register.
+ Limitations:
+ - Priorities are not implemented, and registers are RAZ/WI
+ Errors:
+ - ENODEV: Getting or setting this register is not yet supported
+
+ KVM_DEV_ARM_VGIC_GRP_CPU_REGS
+ Attributes:
+ The attr field of kvm_device_attr encodes two values:
+ bits: | 63 .... 40 | 39 .. 32 | 31 .... 0 |
+ values: | reserved | cpu id | offset |
+
+ The offsetspecifies the offset from the "CPU interface base address" as
+ defined in the GICv2 specs. Getting or setting such a register has the
+ same effect as reading or writing the register on the actual hardware.
+ Limitations:
+ - Priorities are not implemented, and registers are RAZ/WI
+ Errors:
+ - ENODEV: Getting or setting this register is not yet supported
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index bfb9985..4821ce9 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -591,11 +591,29 @@ static bool handle_mmio_sgi_reg(struct kvm_vcpu *vcpu,
return false;
}
+static bool handle_mmio_sgi_clear(struct kvm_vcpu *vcpu,
+ struct kvm_exit_mmio *mmio,
+ phys_addr_t offset)
+{
+ return false;
+}
+
+static bool handle_mmio_sgi_set(struct kvm_vcpu *vcpu,
+ struct kvm_exit_mmio *mmio,
+ phys_addr_t offset)
+{
+ return false;
+}
+
/*
* I would have liked to use the kvm_bus_io_*() API instead, but it
* cannot cope with banked registers (only the VM pointer is passed
* around, and we need the vcpu). One of these days, someone please
* fix it!
+ *
+ * Note that the handle_mmio implementations should not use the phys_addr
+ * field from the kvm_exit_mmio struct as this will not have any sane values
+ * when used to save/restore state from user space.
*/
struct mmio_range {
phys_addr_t base;
@@ -665,6 +683,16 @@ static const struct mmio_range vgic_dist_ranges[] = {
.len = 4,
.handle_mmio = handle_mmio_sgi_reg,
},
+ {
+ .base = GIC_DIST_SGI_CLEAR,
+ .len = VGIC_NR_SGIS / 4,
+ .handle_mmio = handle_mmio_sgi_clear,
+ },
+ {
+ .base = GIC_DIST_SGI_SET,
+ .len = VGIC_NR_SGIS / 4,
+ .handle_mmio = handle_mmio_sgi_set,
+ },
{}
};
@@ -1519,6 +1547,93 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
return r;
}
+static bool handle_cpu_mmio_misc(struct kvm_vcpu *vcpu,
+ struct kvm_exit_mmio *mmio, phys_addr_t offset)
+{
+ return true;
+}
+
+static const struct mmio_range vgic_cpu_ranges[] = {
+ {
+ .base = GIC_CPU_CTRL,
+ .len = 4,
+ .handle_mmio = handle_cpu_mmio_misc,
+ },
+ {
+ .base = GIC_CPU_PRIMASK,
+ .len = 4,
+ .handle_mmio = handle_cpu_mmio_misc,
+ },
+ {
+ .base = GIC_CPU_BINPOINT,
+ .len = 4,
+ .handle_mmio = handle_cpu_mmio_misc,
+ },
+ {
+ .base = GIC_CPU_ALIAS_BINPOINT,
+ .len = 4,
+ .handle_mmio = handle_cpu_mmio_misc,
+ },
+ {
+ .base = GIC_CPU_ACTIVEPRIO,
+ .len = 16,
+ .handle_mmio = handle_cpu_mmio_misc,
+ },
+ {
+ .base = GIC_CPU_IDENT,
+ .len = 4,
+ .handle_mmio = handle_cpu_mmio_misc,
+ },
+};
+
+static struct kvm_exit_mmio dev_attr_mmio = { .len = 4 };
+
+static int vgic_attr_regs_access(struct kvm_device *dev,
+ struct kvm_device_attr *attr,
+ u32 *reg, bool is_write)
+{
+ u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+ const struct mmio_range *r = NULL;
+ phys_addr_t offset;
+ int cpuid;
+ struct kvm_vcpu *vcpu;
+ struct kvm_exit_mmio mmio;
+
+ offset = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+ cpuid = attr->attr & KVM_DEV_ARM_VGIC_CPUID_MASK;
+
+ if (cpuid >= atomic_read(&dev->kvm->online_vcpus))
+ return -EINVAL;
+
+ vcpu = kvm_get_vcpu(dev->kvm, cpuid);
+
+ mmio.len = 4;
+ mmio.is_write = is_write;
+ if (is_write) {
+ if (copy_from_user(mmio.data, uaddr, sizeof(*uaddr)))
+ return -EFAULT;
+ }
+
+ if (attr->group == KVM_DEV_ARM_VGIC_GRP_DIST_REGS)
+ r = find_matching_range(vgic_dist_ranges, &mmio, offset);
+ else if (attr->group == KVM_DEV_ARM_VGIC_GRP_DIST_REGS)
+ r = find_matching_range(vgic_cpu_ranges, &mmio, offset);
+
+ if (unlikely(!r|| !r->handle_mmio))
+ return -ENXIO;
+
+ spin_lock(&vcpu->kvm->arch.vgic.lock);
+ r->handle_mmio(vcpu, &mmio, offset);
+ spin_unlock(&vcpu->kvm->arch.vgic.lock);
+
+ if (!is_write) {
+ if (copy_to_user(uaddr, mmio.data, sizeof(*uaddr)))
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
{
int r;
@@ -1535,6 +1650,18 @@ static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
r = kvm_vgic_addr(dev->kvm, type, &addr, true);
return (r == -ENODEV) ? -ENXIO : r;
}
+
+ case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+ case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
+ u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+ u32 reg;
+
+ if (get_user(reg, uaddr))
+ return -EFAULT;
+
+ return vgic_attr_regs_access(dev, attr, ®, true);
+ }
+
}
return -ENXIO;
@@ -1557,12 +1684,35 @@ static int vgic_get_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
r = 0;
if (copy_to_user(uaddr, &addr, sizeof(addr)))
return -EFAULT;
+ break;
}
+
+ case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+ case KVM_DEV_ARM_VGIC_GRP_CPU_REGS: {
+ u32 __user *uaddr = (u32 __user *)(long)attr->addr;
+ u32 reg = 0;
+
+ r = vgic_attr_regs_access(dev, attr, ®, false);
+ if (r)
+ return r;
+ r = put_user(reg, uaddr);
+ break;
+ }
+
}
return r;
}
+static int vgic_has_attr_regs(const struct mmio_range *ranges,
+ phys_addr_t offset)
+{
+ if (find_matching_range(ranges, &dev_attr_mmio, offset))
+ return 0;
+ else
+ return -ENXIO;
+}
+
static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
{
phys_addr_t offset;
@@ -1575,6 +1725,12 @@ static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
return 0;
}
break;
+ case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
+ offset = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+ return vgic_has_attr_regs(vgic_dist_ranges, offset);
+ case KVM_DEV_ARM_VGIC_GRP_CPU_REGS:
+ offset = attr->attr & KVM_DEV_ARM_VGIC_OFFSET_MASK;
+ return vgic_has_attr_regs(vgic_cpu_ranges, offset);
}
return -ENXIO;
}
--
1.7.9.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 6/7] KVM: arm-vgic: Add GICD_SPENDSGIR and GICD_CPENDSGIR handlers
2013-06-11 4:51 [PATCH 0/7] KVM: arm-vgic: Implement save/restore of VGIC state Christoffer Dall
` (4 preceding siblings ...)
2013-06-11 4:51 ` [PATCH 5/7] KVM: arm-vgic: Add vgic reg access from dev attr Christoffer Dall
@ 2013-06-11 4:51 ` Christoffer Dall
2013-06-11 4:51 ` [PATCH 7/7] KVM: arm-vgic: Support CPU interface reg access Christoffer Dall
2013-06-20 13:54 ` [PATCH 0/7] KVM: arm-vgic: Implement save/restore of VGIC state Alexander Graf
7 siblings, 0 replies; 14+ messages in thread
From: Christoffer Dall @ 2013-06-11 4:51 UTC (permalink / raw)
To: linux-arm-kernel
Handle MMIO accesses to the two registers which should support both the
case where the VMs want to read/write either of these registers and the
case where user space reads/writes these registers to do save/restore of
the VGIC state.
Note that the added complexity compared to simple set/clear enable
registers stems from the bookkeping of source cpu ids. It may be
possible to change the underlying data structure to simplify the
complexity, but since this is not in the critical path, at all, this is
left as an interesting excercise to the reader.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
virt/kvm/arm/vgic.c | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 112 insertions(+), 2 deletions(-)
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 4821ce9..62d0fec 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -591,18 +591,128 @@ static bool handle_mmio_sgi_reg(struct kvm_vcpu *vcpu,
return false;
}
+static void read_sgi_set_clear(struct kvm_vcpu *vcpu,
+ struct kvm_exit_mmio *mmio,
+ phys_addr_t offset)
+{
+ struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+ struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+ int i, sgi, cpu;
+ int min_sgi = (offset & ~0x3) * 4;
+ int max_sgi = min_sgi + 3;
+ int vcpu_id = vcpu->vcpu_id;
+ u32 lr, reg = 0;
+
+ /* Copy source SGIs from distributor side */
+ for (sgi = min_sgi; sgi <= max_sgi; sgi++) {
+ int shift = 8 * (sgi - min_sgi);
+ reg |= (u32)dist->irq_sgi_sources[vcpu_id][sgi] << shift;
+ }
+
+ /* Copy source SGIs already on LRs */
+ for_each_set_bit(i, vgic_cpu->lr_used, vgic_cpu->nr_lr) {
+ lr = vgic_cpu->vgic_lr[i];
+ sgi = lr & GICH_LR_VIRTUALID;
+ cpu = (lr & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT;
+ if (sgi >= min_sgi && sgi <= max_sgi) {
+ if (lr & GICH_LR_STATE)
+ reg |= (1 << cpu) << (8 * (sgi - min_sgi));
+ }
+ }
+
+ memcpy(mmio->data, ®, sizeof(reg));
+}
+
static bool handle_mmio_sgi_clear(struct kvm_vcpu *vcpu,
struct kvm_exit_mmio *mmio,
phys_addr_t offset)
{
- return false;
+ struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+ struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+ int i, sgi, cpu;
+ int min_sgi = (offset & ~0x3) * 4;
+ int max_sgi = min_sgi + 3;
+ int vcpu_id = vcpu->vcpu_id;
+ u32 *lr, reg;
+ bool updated = false;
+
+ if (!mmio->is_write) {
+ read_sgi_set_clear(vcpu, mmio, offset);
+ return false;
+ }
+
+ memcpy(®, mmio->data, sizeof(reg));
+
+ /* Clear pending SGIs on distributor side */
+ for (sgi = min_sgi; sgi <= max_sgi; sgi++) {
+ u8 mask = reg >> (8 * (sgi - min_sgi));
+ if (dist->irq_sgi_sources[vcpu_id][sgi] & mask)
+ updated = true;
+ dist->irq_sgi_sources[vcpu_id][sgi] &= ~mask;
+ }
+
+ /* Clear SGIs already on LRs */
+ for_each_set_bit(i, vgic_cpu->lr_used, vgic_cpu->nr_lr) {
+ lr = &vgic_cpu->vgic_lr[i];
+ sgi = *lr & GICH_LR_VIRTUALID;
+ cpu = (*lr & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT;
+
+ if (sgi >= min_sgi && sgi <= max_sgi) {
+ if (reg & ((1 << cpu) << (8 * (sgi - min_sgi)))) {
+ if (*lr & GICH_LR_PENDING_BIT)
+ updated = true;
+ *lr &= GICH_LR_PENDING_BIT;
+ }
+ }
+ }
+
+ return updated;
}
static bool handle_mmio_sgi_set(struct kvm_vcpu *vcpu,
struct kvm_exit_mmio *mmio,
phys_addr_t offset)
{
- return false;
+ struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
+ struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+ int i, sgi, cpu;
+ int min_sgi = (offset & ~0x3) * 4;
+ int max_sgi = min_sgi + 3;
+ int vcpu_id = vcpu->vcpu_id;
+ u32 *lr, reg;
+ bool updated = false;
+
+ if (!mmio->is_write) {
+ read_sgi_set_clear(vcpu, mmio, offset);
+ return false;
+ }
+
+ memcpy(®, mmio->data, sizeof(reg));
+
+ /* Set pending SGIs on distributor side */
+ for (sgi = min_sgi; sgi <= max_sgi; sgi++) {
+ u8 mask = reg >> (8 * (sgi - min_sgi));
+ if ((dist->irq_sgi_sources[vcpu_id][sgi] & mask) != mask)
+ updated = true;
+ dist->irq_sgi_sources[vcpu_id][sgi] |= mask;
+ }
+
+ /* Set active SGIs already on LRs to pending and active */
+ for_each_set_bit(i, vgic_cpu->lr_used, vgic_cpu->nr_lr) {
+ lr = &vgic_cpu->vgic_lr[i];
+ sgi = *lr & GICH_LR_VIRTUALID;
+ cpu = (*lr & GICH_LR_PHYSID_CPUID) >> GICH_LR_PHYSID_CPUID_SHIFT;
+
+ if (sgi >= min_sgi && sgi <= max_sgi) {
+ if (reg & ((1 << cpu) << (8 * (sgi - min_sgi)))) {
+ if (!(*lr & GICH_LR_PENDING_BIT))
+ updated = true;
+ *lr |= GICH_LR_PENDING_BIT;
+ }
+ }
+ }
+
+ return updated;
}
/*
--
1.7.9.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 7/7] KVM: arm-vgic: Support CPU interface reg access
2013-06-11 4:51 [PATCH 0/7] KVM: arm-vgic: Implement save/restore of VGIC state Christoffer Dall
` (5 preceding siblings ...)
2013-06-11 4:51 ` [PATCH 6/7] KVM: arm-vgic: Add GICD_SPENDSGIR and GICD_CPENDSGIR handlers Christoffer Dall
@ 2013-06-11 4:51 ` Christoffer Dall
2013-06-20 13:54 ` [PATCH 0/7] KVM: arm-vgic: Implement save/restore of VGIC state Alexander Graf
7 siblings, 0 replies; 14+ messages in thread
From: Christoffer Dall @ 2013-06-11 4:51 UTC (permalink / raw)
To: linux-arm-kernel
Implement support for the CPU interface register access driven by MMIO
address offsets from the CPU interface base address. Useful for user
space to support save/restore of the VGIC state.
This commit adds support only for the same logic as the current VGIC
support, and no more. For example, the active priority registers are
handled as RAZ/WI, just like setting priorities on the emulated
distributor.
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
---
virt/kvm/arm/vgic.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++---
1 file changed, 55 insertions(+), 3 deletions(-)
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 62d0fec..64bea93 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1660,9 +1660,61 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write)
static bool handle_cpu_mmio_misc(struct kvm_vcpu *vcpu,
struct kvm_exit_mmio *mmio, phys_addr_t offset)
{
- return true;
+ struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+ u32 reg, mask = 0, shift = 0;
+ bool updated = false;
+
+ switch (offset & ~0x3) {
+ case GIC_CPU_CTRL:
+ mask = GICH_VMCR_CTRL_MASK;
+ shift = GICH_VMCR_CTRL_SHIFT;
+ break;
+ case GIC_CPU_PRIMASK:
+ mask = GICH_VMCR_PRIMASK_MASK;
+ shift = GICH_VMCR_PRIMASK_SHIFT;
+ break;
+ case GIC_CPU_BINPOINT:
+ mask = GICH_VMCR_BINPOINT_MASK;
+ shift = GICH_VMCR_BINPOINT_SHIFT;
+ break;
+ case GIC_CPU_ALIAS_BINPOINT:
+ mask = GICH_VMCR_ALIAS_BINPOINT_MASK;
+ shift = GICH_VMCR_ALIAS_BINPOINT_SHIFT;
+ break;
+ }
+
+ if (!mmio->is_write) {
+ reg = (vgic_cpu->vgic_vmcr & mask) >> 0;
+ memcpy(mmio->data, ®, sizeof(reg));
+ } else {
+ memcpy(®, mmio->data, sizeof(reg));
+ reg = (reg << shift) & mask;
+ if (reg != (vgic_cpu->vgic_vmcr & mask))
+ updated = true;
+ vgic_cpu->vgic_vmcr &= ~mask;
+ vgic_cpu->vgic_vmcr |= reg;
+ }
+ return updated;
}
+static bool handle_cpu_mmio_ident(struct kvm_vcpu *vcpu,
+ struct kvm_exit_mmio *mmio,
+ phys_addr_t offset)
+{
+ u32 reg;
+
+ if (mmio->is_write)
+ return false;
+
+ reg = 0x0002043B;
+ memcpy(mmio->data, ®, sizeof(reg));
+ return false;
+}
+
+/*
+ * CPU Interface Register accesses - these are not accessed by the VM, but by
+ * user space for saving and restoring VGIC state.
+ */
static const struct mmio_range vgic_cpu_ranges[] = {
{
.base = GIC_CPU_CTRL,
@@ -1687,12 +1739,12 @@ static const struct mmio_range vgic_cpu_ranges[] = {
{
.base = GIC_CPU_ACTIVEPRIO,
.len = 16,
- .handle_mmio = handle_cpu_mmio_misc,
+ .handle_mmio = handle_mmio_raz_wi,
},
{
.base = GIC_CPU_IDENT,
.len = 4,
- .handle_mmio = handle_cpu_mmio_misc,
+ .handle_mmio = handle_cpu_mmio_ident,
},
};
--
1.7.9.5
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 0/7] KVM: arm-vgic: Implement save/restore of VGIC state
2013-06-11 4:51 [PATCH 0/7] KVM: arm-vgic: Implement save/restore of VGIC state Christoffer Dall
` (6 preceding siblings ...)
2013-06-11 4:51 ` [PATCH 7/7] KVM: arm-vgic: Support CPU interface reg access Christoffer Dall
@ 2013-06-20 13:54 ` Alexander Graf
7 siblings, 0 replies; 14+ messages in thread
From: Alexander Graf @ 2013-06-20 13:54 UTC (permalink / raw)
To: linux-arm-kernel
On 06/11/2013 06:51 AM, Christoffer Dall wrote:
> This patch series adds support for user space save/restore of the VGIC
> state. Instead of expanding the ONE_REG interface, which works on
> VCPUs, we first introduce support for the new KVM device control API and
> the VGIC. Now, instead of calling KVM_CREATE_IRQCHIP, user space can
> call KVM_CREATE_DEVICE and perform operations on the device fd, such as
> KVM_SET_DEVICE_ATTR to set a device attribute.
>
> We leverage the KVM_{SET/GET}_DEVICE_ATTR API to export the state of the
> VGIC to user space. Instead of coming up with our own custom format for
> exporting the VGIC state, we simply export all the state visible to an
> emulated guest, which must contain the full GIC state to provide
> save/restore of the GIC state for power management purposes. This
> further provides the benefit of being able to re-use the MMIO emulation
> code for the distributor for save/restore.
>
> However, the need to save/restore cpu-specific state demands that user
> space can save/restore state accessible through the CPU interface, and
> we therefore add an emulation interface for the CPU-specific interface.
>
> This is considered a first attempt, and I am not married to the device
> control API. If there are good technical arguments to take another
> approach, I am of course willing to discuss this. However, my attempts
> with the ONE_REG interface did not look very nice.
>
> [ WARINING: The patch set core functionality is completely untested;
> the basic KVM system has been briefly tested on TC2 and it doesn't
> seem like I've broken existing functionality. ]
>
> I wanted to get this out early to get feedback on the overall API and
> idea, and I'm writing some user QEMU for the user space side to test
> the new functionality meanwhile.
>
> Patches are against kvm-arm-next and also available here:
> git://git.linaro.org/people/cdall/linux-kvm-arm.git vgic-migrate
I don't see major glitches :)
Reviewed-by: Alexander Graf <agraf@suse.de>
Alex
^ permalink raw reply [flat|nested] 14+ messages in thread