Skip to contentSkip to conversation

KVM: arm: Implement software vGICv2 emulation

PATCH In review Pavel Fedin 4 participants 13 messages Jun 29, 2015 – Jun 30, 2015

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover KVM: arm: Implement software vGICv2 emulation

Some hardware (like Raspberry Pi 2) is capable of running KVM, however lacks functional vGIC registers. This series introduces software vGIC emulation for such machines, allowing to fully use virtualization capabilities

Pavel Fedin (3):
KVM: arm: Add basic infrastructure for software vGIC emulation
KVM: arm: Introduce software emulation of vGICv2 CPU interface
KVM: arm: Enable vGICv2 software emulation

 include/kvm/arm_vgic.h      |   4 ++
 virt/kvm/arm/vgic-v2-emul.c |  60 +++++++++++++++--
 virt/kvm/arm/vgic-v2.c      |  29 ++++----
 virt/kvm/arm/vgic.c         | 159 +++++++++++++++++++++++++++++++++-----------
 virt/kvm/arm/vgic.h         |   3 +
 5 files changed, 196 insertions(+), 59 deletions(-)
Signature · 1 line
2.1.4
#1 lore raw

PATCH 1/3 KVM: arm: Add basic infrastructure for software vGIC emulation

Two main functions (vgic_get_pending_irq() and vgic_clear_pending_irq()) are responsible for ACK and EOI respectively. Maintenance code path refactored in order to accommodate these changes. The main problem is that __kvm_vgic_sync_hwstate() is called before I/O emulation takes place, therefore vgic_process_maintenance() cannot be reused.

---
 include/kvm/arm_vgic.h |   3 +
 virt/kvm/arm/vgic.c    | 149 ++++++++++++++++++++++++++++++++++++++-----------
 virt/kvm/arm/vgic.h    |   3 +
 3 files changed, 121 insertions(+), 34 deletions(-)
include/kvm/arm_vgic.h +3 -0
index 133ea00..31cda96 100644
@@ -160,6 +160,9 @@ struct vgic_dist {
 	bool			in_kernel;
 	bool			ready;
 
+	/* Use software emulation of CPU interface */
+	bool			sw_cpuif;
+
 	/* vGIC model the kernel emulates for the guest (GICv2 or GICv3) */
 	u32			vgic_model;
 
virt/kvm/arm/vgic.c +115 -34

183 lines not on this page · raw message

virt/kvm/arm/vgic.h +3 -0
index 0df74cb..75ecfef 100644
@@ -59,6 +59,9 @@ void vgic_set_vmcr(struct kvm_vcpu *vcpu, struct vgic_vmcr *vmcr);
 bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq);
 void vgic_unqueue_irqs(struct kvm_vcpu *vcpu);
 
+int vgic_get_pending_irq(struct kvm_vcpu *vcpu);
+void vgic_clear_pending_irq(struct kvm_vcpu *vcpu, int irq);
+
 struct kvm_exit_mmio {
 	phys_addr_t	phys_addr;
 	void		*data;
Signature · 1 line
2.1.4
#2 lore raw

PATCH 2/3 KVM: arm: Introduce software emulation of vGICv2 CPU interface

In reply to Pavel Fedin

The emulation code is activated by setting params->vcpu_base to zero

---
 include/kvm/arm_vgic.h      |  1 +
 virt/kvm/arm/vgic-v2-emul.c | 60 ++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 55 insertions(+), 6 deletions(-)
include/kvm/arm_vgic.h +1 -0
index 31cda96..fa533e7 100644
@@ -254,6 +254,7 @@ struct vgic_dist {
 
 	struct vgic_vm_ops	vm_ops;
 	struct vgic_io_device	dist_iodev;
+	struct vgic_io_device	cpu_iodev;
 	struct vgic_io_device	*redist_iodevs;
 };
 
virt/kvm/arm/vgic-v2-emul.c +54 -6

84 lines not on this page · raw message

Signature · 1 line
2.1.4
#3 lore raw

PATCH 3/3 KVM: arm: Enable vGICv2 software emulation

In reply to Pavel Fedin

The emulation code is automatically enabled when one of vGIC resources is missing from the device tree

---
 virt/kvm/arm/vgic-v2.c | 29 ++++++++++++++---------------
 virt/kvm/arm/vgic.c    | 10 ++++++----
 2 files changed, 20 insertions(+), 19 deletions(-)
virt/kvm/arm/vgic-v2.c +14 -15
index f9b9c7c..b371a59 100644
@@ -180,22 +180,27 @@ int vgic_v2_probe(struct device_node *vgic_node,
 		  const struct vgic_ops **ops,
 		  const struct vgic_params **params)
 {
-	int ret;
+	int ret = 0;
 	struct resource vctrl_res;
 	struct resource vcpu_res;
 	struct vgic_params *vgic = &vgic_v2_params;
 
+	vgic->nr_lr = VGIC_V2_MAX_LRS;
+
 	vgic->maint_irq = irq_of_parse_and_map(vgic_node, 0);
 	if (!vgic->maint_irq) {
 		kvm_err("error getting vgic maintenance irq from DT\n");
-		ret = -ENXIO;
-		goto out;
+		goto sw_emul;
 	}
 
-	ret = of_address_to_resource(vgic_node, 2, &vctrl_res);
-	if (ret) {
+	if (of_address_to_resource(vgic_node, 2, &vctrl_res)) {
 		kvm_err("Cannot obtain GICH resource\n");
-		goto out;
+		goto sw_emul;
+	}
+
+	if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
+		kvm_err("Cannot obtain GICV resource\n");
+		goto sw_emul;
 	}
 
 	vgic->vctrl_base = of_iomap(vgic_node, 2);
@@ -216,12 +221,6 @@ int vgic_v2_probe(struct device_node *vgic_node,
 		goto out_unmap;
 	}
 
-	if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
-		kvm_err("Cannot obtain GICV resource\n");
-		ret = -ENXIO;
-		goto out_unmap;
-	}
-
 	if (!PAGE_ALIGNED(vcpu_res.start)) {
 		kvm_err("GICV physical address 0x%llx not page aligned\n",
 			(unsigned long long)vcpu_res.start);
@@ -237,13 +236,13 @@ int vgic_v2_probe(struct device_node *vgic_node,
 		goto out_unmap;
 	}
 
-	vgic->can_emulate_gicv2 = true;
-	kvm_register_device_ops(&kvm_arm_vgic_v2_ops, KVM_DEV_TYPE_ARM_VGIC_V2);
-
 	vgic->vcpu_base = vcpu_res.start;
 
 	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
 		 vctrl_res.start, vgic->maint_irq);
+sw_emul:
+	vgic->can_emulate_gicv2 = true;
+	kvm_register_device_ops(&kvm_arm_vgic_v2_ops, KVM_DEV_TYPE_ARM_VGIC_V2);
 
 	vgic->type = VGIC_V2;
 	vgic->max_gic_vcpus = VGIC_V2_MAX_CPUS;
virt/kvm/arm/vgic.c +6 -4
index aec6063..66e0cae 100644
@@ -2196,11 +2196,13 @@ int kvm_vgic_hyp_init(void)
 	if (ret)
 		return ret;
 
-	ret = request_percpu_irq(vgic->maint_irq, vgic_maintenance_handler,
+	if (vgic->maint_irq) {
+		ret = request_percpu_irq(vgic->maint_irq, vgic_maintenance_handler,
 				 "vgic", kvm_get_running_vcpus());
-	if (ret) {
-		kvm_err("Cannot register interrupt %d\n", vgic->maint_irq);
-		return ret;
+		if (ret) {
+			kvm_err("Cannot register interrupt %d\n", vgic->maint_irq);
+			return ret;
+		}
 	}
 
 	ret = __register_cpu_notifier(&vgic_cpu_nb);
Signature · 1 line
2.1.4
#4 lore raw

Re: [PATCH 3/3] KVM: arm: Enable vGICv2 software emulation

Quoted 2 lines · Pavel Fedin

The emulation code is automatically enabled when one of vGIC resources is missing from the device tree

Hold on a second. In your cover letter, your saying "RPi-2". The RPi-2 doesn't have a GIC at all, so I'd really like to know *how* you end-up in the GICv2 probe function?

Thanks,

	M.
Quoted 98 lines
---
 virt/kvm/arm/vgic-v2.c | 29 ++++++++++++++---------------
 virt/kvm/arm/vgic.c    | 10 ++++++----
 2 files changed, 20 insertions(+), 19 deletions(-)
virt/kvm/arm/vgic-v2.c +14 -15
index f9b9c7c..b371a59 100644
@@ -180,22 +180,27 @@ int vgic_v2_probe(struct device_node *vgic_node,
 		  const struct vgic_ops **ops,
 		  const struct vgic_params **params)
 {
-	int ret;
+	int ret = 0;
 	struct resource vctrl_res;
 	struct resource vcpu_res;
 	struct vgic_params *vgic = &vgic_v2_params;
 
+	vgic->nr_lr = VGIC_V2_MAX_LRS;
+
 	vgic->maint_irq = irq_of_parse_and_map(vgic_node, 0);
 	if (!vgic->maint_irq) {
 		kvm_err("error getting vgic maintenance irq from DT\n");
-		ret = -ENXIO;
-		goto out;
+		goto sw_emul;
 	}
 
-	ret = of_address_to_resource(vgic_node, 2, &vctrl_res);
-	if (ret) {
+	if (of_address_to_resource(vgic_node, 2, &vctrl_res)) {
 		kvm_err("Cannot obtain GICH resource\n");
-		goto out;
+		goto sw_emul;
+	}
+
+	if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
+		kvm_err("Cannot obtain GICV resource\n");
+		goto sw_emul;
 	}
 
 	vgic->vctrl_base = of_iomap(vgic_node, 2);
@@ -216,12 +221,6 @@ int vgic_v2_probe(struct device_node *vgic_node,
 		goto out_unmap;
 	}
 
-	if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
-		kvm_err("Cannot obtain GICV resource\n");
-		ret = -ENXIO;
-		goto out_unmap;
-	}
-
 	if (!PAGE_ALIGNED(vcpu_res.start)) {
 		kvm_err("GICV physical address 0x%llx not page aligned\n",
 			(unsigned long long)vcpu_res.start);
@@ -237,13 +236,13 @@ int vgic_v2_probe(struct device_node *vgic_node,
 		goto out_unmap;
 	}
 
-	vgic->can_emulate_gicv2 = true;
-	kvm_register_device_ops(&kvm_arm_vgic_v2_ops, KVM_DEV_TYPE_ARM_VGIC_V2);
-
 	vgic->vcpu_base = vcpu_res.start;
 
 	kvm_info("%s@%llx IRQ%d\n", vgic_node->name,
 		 vctrl_res.start, vgic->maint_irq);
+sw_emul:
+	vgic->can_emulate_gicv2 = true;
+	kvm_register_device_ops(&kvm_arm_vgic_v2_ops, KVM_DEV_TYPE_ARM_VGIC_V2);
 
 	vgic->type = VGIC_V2;
 	vgic->max_gic_vcpus = VGIC_V2_MAX_CPUS;
virt/kvm/arm/vgic.c +6 -4
index aec6063..66e0cae 100644
@@ -2196,11 +2196,13 @@ int kvm_vgic_hyp_init(void)
 	if (ret)
 		return ret;
 
-	ret = request_percpu_irq(vgic->maint_irq, vgic_maintenance_handler,
+	if (vgic->maint_irq) {
+		ret = request_percpu_irq(vgic->maint_irq, vgic_maintenance_handler,
 				 "vgic", kvm_get_running_vcpus());
-	if (ret) {
-		kvm_err("Cannot register interrupt %d\n", vgic->maint_irq);
-		return ret;
+		if (ret) {
+			kvm_err("Cannot register interrupt %d\n", vgic->maint_irq);
+			return ret;
+		}
 	}
 
 	ret = __register_cpu_notifier(&vgic_cpu_nb);
Signature · 1 line
Jazz is not dead. It just smells funny...
#5 lore raw

RE: [PATCH 3/3] KVM: arm: Enable vGICv2 software emulation

Hello!

Quoted 3 lines

Hold on a second. In your cover letter, your saying "RPi-2". The RPi-2 doesn't have a GIC at all, so I'd really like to know *how* you end-up in the GICv2 probe function?

I'm not on RPi-2. I am on some Samsung's proprietary hardware which suffers from this problem.
Actually it has "weird GIC", similar to Exynos-4 (every CPU accesses GIC at its own base), thus hardware vGIC is unusable.
I learned about RPi-2 when i was discussing some related things earlier with Andre over private
mail and we suggested that it could be useful there.

Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia

#6 lore raw

Re: [PATCH 3/3] KVM: arm: Enable vGICv2 software emulation

Quoted 10 lines · Pavel Fedin

Hello!

Quoted 3 lines

Hold on a second. In your cover letter, your saying "RPi-2". The RPi-2 doesn't have a GIC at all, so I'd really like to know *how* you end-up in the GICv2 probe function?

I'm not on RPi-2. I am on some Samsung's proprietary hardware which suffers from this problem. Actually it has "weird GIC", similar to Exynos-4 (every CPU accesses GIC at its own base), thus hardware vGIC is unusable.

Well, I'm sorry you have to work with such broken designs, but this is simply not suitable for KVM. The Franken-GIC has caused us a lot of pain in the past, and papering over it only gives people an incentive to push for more broken HW.

Thanks,

	M.
Signature · 1 line
Jazz is not dead. It just smells funny...
#7 lore raw
In reply to Pavel Fedin

Hi Pavel,

Quoted 3 lines · Pavel Fedin

Some hardware (like Raspberry Pi 2) is capable of running KVM, however lacks functional vGIC registers. This series introduces software vGIC emulation for such machines, allowing to fully use virtualization capabilities

I'm really not keen on any of this. The RPi-2 is mostly unsupported in mainline, and not only lacks the vGIC, but doesn't have a GIC at all. This would break ongoing developments (inability to properly support EOImode=1, to preserve the active state for shared devices like timers).

As far as I'm concerned, this hardware is not architecturally compliant and the solution is to use userspace emulation (QEMU provides a GIC model). Taking these patches would keep us stuck in the past.

I'm sure whoever maintains the RPi kernel will be glad to take these patches on top of the pile of stuff they keep out of tree.

Thanks,

	M.
Quoted 12 lines

Pavel Fedin (3):
KVM: arm: Add basic infrastructure for software vGIC emulation
KVM: arm: Introduce software emulation of vGICv2 CPU interface
KVM: arm: Enable vGICv2 software emulation

 include/kvm/arm_vgic.h      |   4 ++
 virt/kvm/arm/vgic-v2-emul.c |  60 +++++++++++++++--
 virt/kvm/arm/vgic-v2.c      |  29 ++++----
 virt/kvm/arm/vgic.c         | 159 +++++++++++++++++++++++++++++++++-----------
 virt/kvm/arm/vgic.h         |   3 +
 5 files changed, 196 insertions(+), 59 deletions(-)
Signature · 1 line
Jazz is not dead. It just smells funny...
#8 lore raw
In reply to Pavel Fedin

Hi Pavel,

[Please cc the kvm/arm list for such patches according to the MAINTAINERS file in the future]

Quoted 3 lines · Pavel Fedin

Some hardware (like Raspberry Pi 2) is capable of running KVM, however lacks functional vGIC registers. This series introduces software vGIC emulation for such machines, allowing to fully use virtualization capabilities

Is this rather esoteric use case really worth the extra code in the kernel? I really feel that pure emulation should happen in userspace unless there's a very good reason for doing it in the kernel, such as a clearly measureable difference in performance, etc.

I would much rather see a version of this where a userspace provided GIC works with the in-kernel arch timers support.

-Christoffer

#9 lore raw

Hi,

Quoted 5 lines · Christoffer Dall

Hi Pavel,

[Please cc the kvm/arm list for such patches according to the MAINTAINERS file in the future]

Quoted 7 lines
Quoted 3 lines · Pavel Fedin

Some hardware (like Raspberry Pi 2) is capable of running KVM, however lacks functional vGIC registers. This series introduces software vGIC emulation for such machines, allowing to fully use virtualization capabilities

Is this rather esoteric use case really worth the extra code in the kernel?

I wonder if these patches would pave the way to support running GICv2 guests on GICv3s without compat support? Admittedly not a really compelling use case either, but at least worth discussing, I think.

Also if this will make the hack needed to enable KVM on RPi2 smaller, I'd rather embrace this one than letting any random hacks appear on that RPi kernel tree (patches which I have seen already on some other repo). If I get this correctly, there are some efforts currently to get closer to mainline with the RPi tree.

Pavel, is this "broken" GIC you are talking about going to appear in a publicly available SoC? If yes, you could either state this right now or send it later once you can talk publicly.

Marc, Christoffer:
So is this GICv2 CPU interface emulation totally out of question for us or is it worth at least commenting on the patches?

Cheers,
Andre.

Quoted 9 lines

I really feel that pure emulation should happen in userspace unless there's a very good reason for doing it in the kernel, such as a clearly measureable difference in performance, etc.

I would much rather see a version of this where a userspace provided GIC works with the in-kernel arch timers support.

-Christoffer

#10 lore raw
Quoted 26 lines · Andre Przywara

Hi,

Quoted 5 lines · Christoffer Dall

Hi Pavel,

[Please cc the kvm/arm list for such patches according to the MAINTAINERS file in the future]

Quoted 7 lines
Quoted 3 lines · Pavel Fedin

Some hardware (like Raspberry Pi 2) is capable of running KVM, however lacks functional vGIC registers. This series introduces software vGIC emulation for such machines, allowing to fully use virtualization capabilities

Is this rather esoteric use case really worth the extra code in the kernel?

I wonder if these patches would pave the way to support running GICv2 guests on GICv3s without compat support? Admittedly not a really compelling use case either, but at least worth discussing, I think.

Also if this will make the hack needed to enable KVM on RPi2 smaller, I'd rather embrace this one than letting any random hacks appear on that RPi kernel tree (patches which I have seen already on some other repo). If I get this correctly, there are some efforts currently to get closer to mainline with the RPi tree.

Quoted 8 lines

Pavel, is this "broken" GIC you are talking about going to appear in a publicly available SoC? If yes, you could either state this right now or send it later once you can talk publicly.

Marc, Christoffer:
So is this GICv2 CPU interface emulation totally out of question for us or is it worth at least commenting on the patches?

Well, I certainly have a lot of seemingly higher-priority things to look at currently.

I'd like some numbers for the performance benefit of putting this in the kernel before I entertain the idea.

-Christoffer

#11 lore raw
In reply to Andre Przywara
Quoted 13 lines · Andre Przywara

Hi,

Quoted 10 lines · Christoffer Dall

Hi Pavel,

[Please cc the kvm/arm list for such patches according to the MAINTAINERS file in the future]

Quoted 3 lines · Pavel Fedin

Some hardware (like Raspberry Pi 2) is capable of running KVM, however lacks functional vGIC registers. This series introduces software vGIC emulation for such machines, allowing to fully use virtualization capabilities

Quoted 6 lines
Quoted 2 lines

Is this rather esoteric use case really worth the extra code in the kernel?

I wonder if these patches would pave the way to support running GICv2 guests on GICv3s without compat support? Admittedly not a really compelling use case either, but at least worth discussing, I think.

Let's face it: arm64 has no legacy to support. So if you're on a pure GICv3 system, you run a GICv3 guest (oddly enough, pure GICv3 systems are also pure AArch64 systems - see a pattern?). We've made sure the software was available in a timely manner.

Quoted 5 lines

Also if this will make the hack needed to enable KVM on RPi2 smaller, I'd rather embrace this one than letting any random hacks appear on that RPi kernel tree (patches which I have seen already on some other repo). If I get this correctly, there are some efforts currently to get closer to mainline with the RPi tree.

Whatever the RPi people do in their tree is their problem. I don't care. I'm interested in supporting *compliant hardware*, and not doing a quick hack on the side.

Even if RPi-2 was fully supported in mainline, this code would actively prevent us from supporting proper timer deactivation, for example.

Quoted 7 lines

Pavel, is this "broken" GIC you are talking about going to appear in a publicly available SoC? If yes, you could either state this right now or send it later once you can talk publicly.

Marc, Christoffer:
So is this GICv2 CPU interface emulation totally out of question for us or is it worth at least commenting on the patches?

As long as this code is there to support a platform that doesn't exist in a mainline tree, I'm not interested. We have much bigger fish to fry, and supporting what is effectively a broken platform is not exactly high on the agenda.

Thanks,

	M.
Signature · 1 line
Jazz is not dead. It just smells funny...
#12 lore raw
In reply to Andre Przywara

Hello!

Quoted 2 lines

I wonder if these patches would pave the way to support running GICv2 guests on GICv3s without compat support?

Yes, it does. I haven't implemented GICv3 bit for this time, but - yes. And it will be a very small
addition.

Quoted 2 lines

Pavel, is this "broken" GIC you are talking about going to appear in a publicly available SoC?

In kernel documentation it's known as "FrankenGIC".
First of all, it's Exynos 4 (however i don't know whether it implements virtualization extensions). Second, it is present in many consumer electronics products (does this count as "publicly
available"? But you can learn this fact from Samsung's opensource releases). I use one of these boards for my tests because we have lots of them here :)
Third, this code doesn't really depend on hardware GIC, and can be reused on RPi-2 with a little
more hacking.
Fourth, there is at least of one ARM64 machine with broken vGICv3. And you can buy it. I have it
here. And it would also benefit from this code (yes, with GICv3 CPU interface emulation added, which becomes trivial).

Kind regards,
Pavel Fedin
Expert Engineer
Samsung Electronics Research center Russia