Since the advent of dynamic initialization of VGIC, this latter is
initialized very late, on the first vcpu run. This initialization
could be initiated much earlier by the user-space, as soon as it has
set the requested dimensioning parameters: number of IRQs, number of
vCPUs, base addresses.
One motivation behind being able to initialize the VGIC sooner is
related to the setup of IRQ injection in VFIO use case. The VFIO
signaling, especially when used along with irqfd must be set *after*
vgic initialization to prevent any virtual IRQ injection before
vgic initialization. If virtual IRQ injection occurs before the VGIC
init, the IRQ cannot be injected and subsequent injection is blocked
due to VFIO completion mechanism (unmask/mask or forward/unforward).
The series includes the following patch files:
[1] changes the error returned by vgic_init_maps when no online vcpu
can be found
[2] adds a new entry to the VGIC KVM device that allows
the user to manually request the VGIC init:
- a new KVM_DEV_ARM_VGIC_GRP_CTRL group is introduced.
- its first attribute is KVM_DEV_ARM_VGIC_CTRL_INIT
[3] prevents the user-space from creating a new vcpu while the vgic
already is initialized
[4] prevents the user-space from changing VGIC base addresses if the
vgic is already initialized
- can be found at:
http://git.linaro.org/people/eric.auger/linux.git,
branch 3.18-rc7-vgic-early-init-MLv2
v1 -> v2:
- 1, 3, 4 patch files added
- some rewording in vgic device documentation
Eric Auger (4):
KVM: arm/arm64: vgic: vgic_init_maps returns -ENODEV when no online
vcpu
KVM: arm/arm64: vgic: add init entry to VGIC KVM device
KVM: arm/arm64: check vgic_initialized before VCPU creation
KVM: arm/arm64: vgic: check vgic_initialized in
KVM_DEV_ARM_VGIC_GRP_ADDR
Documentation/virtual/kvm/devices/arm-vgic.txt | 13 +++++++++++++
arch/arm/include/uapi/asm/kvm.h | 2 ++
arch/arm/kvm/arm.c | 5 +++++
arch/arm64/include/uapi/asm/kvm.h | 2 ++
virt/kvm/arm/vgic.c | 19 +++++++++++++++++--
5 files changed, 39 insertions(+), 2 deletions(-)
--
1.9.1
To be more explicit upon vgic initialization failure, -ENODEV is
returned by vgic_init_maps when no online vcpus can be found at
init.
Signed-off-by: Eric Auger <[email protected]>
---
virt/kvm/arm/vgic.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index b76c38c..907ba0e 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1991,7 +1991,7 @@ static int vgic_init_maps(struct kvm *kvm)
nr_cpus = dist->nr_cpus = atomic_read(&kvm->online_vcpus);
if (!nr_cpus) /* No vcpus? Can't be good... */
- return -EINVAL;
+ return -ENODEV;
/*
* If nobody configured the number of interrupts, use the
--
1.9.1
This patch prevents user-space from changing VGIC base addresses
if the vgic already is initialized.
Signed-off-by: Eric Auger <[email protected]>
---
Documentation/virtual/kvm/devices/arm-vgic.txt | 2 ++
virt/kvm/arm/vgic.c | 3 +++
2 files changed, 5 insertions(+)
diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
index 30f5427..8492715 100644
--- a/Documentation/virtual/kvm/devices/arm-vgic.txt
+++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
@@ -19,6 +19,8 @@ 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.
+ Errors:
+ -EBUSY: VGIC already is initialized
KVM_DEV_ARM_VGIC_GRP_DIST_REGS
Attributes:
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 89dca86..652e0bb 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -2427,6 +2427,9 @@ static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
u64 addr;
unsigned long type = (unsigned long)attr->attr;
+ if (vgic_initialized(dev->kvm))
+ return -EBUSY;
+
if (copy_from_user(&addr, uaddr, sizeof(addr)))
return -EFAULT;
--
1.9.1
Since the advent of dynamic initialization of VGIC, this latter is
initialized very late, on the first vcpu run. This initialization
could be initiated much earlier by the user, as soon as it has
provided the requested dimensioning parameters:
- number of IRQs and number of vCPUs,
- DIST and CPU interface base address.
This patch adds a new entry to the VGIC KVM device that allows
the user to manually request the VGIC init:
- a new KVM_DEV_ARM_VGIC_GRP_CTRL group is introduced.
- Its first attribute is KVM_DEV_ARM_VGIC_CTRL_INIT
The rationale behind introducing a group is to be able to add other
controls later on, if needed.
Obviously, as soon as the init is done, the dimensioning parameters
cannot be changed.
Signed-off-by: Eric Auger <[email protected]>
v1 -> v2:
- some rewording in arm-vgic.txt and in the commit message
---
Documentation/virtual/kvm/devices/arm-vgic.txt | 11 +++++++++++
arch/arm/include/uapi/asm/kvm.h | 2 ++
arch/arm64/include/uapi/asm/kvm.h | 2 ++
virt/kvm/arm/vgic.c | 14 +++++++++++++-
4 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/Documentation/virtual/kvm/devices/arm-vgic.txt b/Documentation/virtual/kvm/devices/arm-vgic.txt
index df8b0c7..30f5427 100644
--- a/Documentation/virtual/kvm/devices/arm-vgic.txt
+++ b/Documentation/virtual/kvm/devices/arm-vgic.txt
@@ -81,3 +81,14 @@ Groups:
-EINVAL: Value set is out of the expected range
-EBUSY: Value has already be set, or GIC has already been initialized
with default values.
+
+ 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.
+ Errors:
+ -ENXIO: VGIC not properly configured as required prior to calling
+ this attribute
+ -ENODEV: no online VCPU
+ -ENOMEM: memory shortage when allocating vgic internal data
diff --git a/arch/arm/include/uapi/asm/kvm.h b/arch/arm/include/uapi/asm/kvm.h
index 77547bb..2499867 100644
--- a/arch/arm/include/uapi/asm/kvm.h
+++ b/arch/arm/include/uapi/asm/kvm.h
@@ -175,6 +175,8 @@ struct kvm_arch_memory_slot {
#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
+#define KVM_DEV_ARM_VGIC_GRP_CTRL 4
+#define KVM_DEV_ARM_VGIC_CTRL_INIT 0
/* KVM_IRQ_LINE irq field index values */
#define KVM_ARM_IRQ_TYPE_SHIFT 24
diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
index 1ed4417..b35c95a 100644
--- a/arch/arm64/include/uapi/asm/kvm.h
+++ b/arch/arm64/include/uapi/asm/kvm.h
@@ -161,6 +161,8 @@ struct kvm_arch_memory_slot {
#define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
#define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
#define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
+#define KVM_DEV_ARM_VGIC_GRP_CTRL 4
+#define KVM_DEV_ARM_VGIC_CTRL_INIT 0
/* KVM_IRQ_LINE irq field index values */
#define KVM_ARM_IRQ_TYPE_SHIFT 24
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 907ba0e..89dca86 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -2474,7 +2474,14 @@ static int vgic_set_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
return ret;
}
-
+ case KVM_DEV_ARM_VGIC_GRP_CTRL: {
+ switch (attr->attr) {
+ case KVM_DEV_ARM_VGIC_CTRL_INIT:
+ r = kvm_vgic_init(dev->kvm);
+ return r;
+ }
+ break;
+ }
}
return -ENXIO;
@@ -2553,6 +2560,11 @@ static int vgic_has_attr(struct kvm_device *dev, struct kvm_device_attr *attr)
return vgic_has_attr_regs(vgic_cpu_ranges, offset);
case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
return 0;
+ case KVM_DEV_ARM_VGIC_GRP_CTRL:
+ switch (attr->attr) {
+ case KVM_DEV_ARM_VGIC_CTRL_INIT:
+ return 0;
+ }
}
return -ENXIO;
}
--
1.9.1
Now that user-space can initiate VGIC initialization independently
on the first vcpu run, let's check the user-space does not attempt
to create a VCPU after this initialization.
Signed-off-by: Eric Auger <[email protected]>
---
arch/arm/kvm/arm.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index b5401f7..edcc66b 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -216,6 +216,11 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
int err;
struct kvm_vcpu *vcpu;
+ if (unlikely(vgic_initialized(kvm))) {
+ err = -EBUSY;
+ goto out;
+ }
+
vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
if (!vcpu) {
err = -ENOMEM;
--
1.9.1
On Thu, Dec 04, 2014 at 10:48:00AM +0100, Eric Auger wrote:
> Since the advent of dynamic initialization of VGIC, this latter is
> initialized very late, on the first vcpu run. This initialization
> could be initiated much earlier by the user-space, as soon as it has
> set the requested dimensioning parameters: number of IRQs, number of
> vCPUs, base addresses.
>
> One motivation behind being able to initialize the VGIC sooner is
> related to the setup of IRQ injection in VFIO use case. The VFIO
> signaling, especially when used along with irqfd must be set *after*
> vgic initialization to prevent any virtual IRQ injection before
> vgic initialization. If virtual IRQ injection occurs before the VGIC
> init, the IRQ cannot be injected and subsequent injection is blocked
> due to VFIO completion mechanism (unmask/mask or forward/unforward).
>
The series looks overall pretty good to me.
-Christoffer