[Android-virt] [PATCH 12/15] ARM: KVM: Convert VGIC to use device tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Instead of hardcoding the VGIC's base addresses and interrupt,
obtain the values from the device tree. Nicer, safer.

What remains to be fixed is the mapping into the guest. This
should be provided by the platform emulation code.

Signed-off-by: Marc Zyngier <marc.zyngier at arm.com>
---
 arch/arm/kvm/vgic.c |   62 +++++++++++++++++++++++++++++++++++++--------------
 1 files changed, 45 insertions(+), 17 deletions(-)

diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c
index b5e6082..f26b091 100644
--- a/arch/arm/kvm/vgic.c
+++ b/arch/arm/kvm/vgic.c
@@ -20,24 +20,23 @@
 #include <linux/kvm_host.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
 
 #include <asm/hardware/gic.h>
 #include <asm/kvm_arm.h>
 #include <asm/kvm_mmu.h>
 
-/* Temporary hacks, need to probe DT instead */
+/* Temporary hacks, need to be provided by userspace emulation */
 #define VGIC_DIST_BASE		0x2c001000
 #define VGIC_DIST_SIZE		0x1000
 #define VGIC_CPU_BASE		0x2c002000
 #define VGIC_CPU_SIZE		0x2000
-#define VGIC_VCTRL_BASE		0x2c004000
-#define VGIC_VCTRL_SIZE		0x2000
-#define VGIC_VCPU_BASE		0x2c006000
-#define VGIC_VCPU_SIZE		0x2000
-#define VGIC_MAINT_IRQ		25
 
 static struct kvm_vcpu __percpu **vgic_vcpus;
 static void __iomem *vgic_vctrl_base;
+static struct device_node *vgic_node;
 
 #define ACCESS_READ_VALUE	(1 << 0)
 #define ACCESS_READ_RAZ		(0 << 0)
@@ -778,6 +777,12 @@ void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
 int kvm_vgic_hyp_init(void)
 {
 	int ret;
+	unsigned int irq;
+	struct resource vctrl_res;
+
+	vgic_node = of_find_compatible_node(NULL, NULL, "arm,cortex-a15-gic");
+	if (!vgic_node)
+		return -ENODEV;
 
 	vgic_vcpus = alloc_percpu(struct kvm_vcpu *);
 	if (!vgic_vcpus) {
@@ -785,34 +790,47 @@ int kvm_vgic_hyp_init(void)
 		return -ENOMEM;
 	}
 
-	ret = request_percpu_irq(VGIC_MAINT_IRQ, kvm_vgic_maintainance_handler,
+	irq = irq_of_parse_and_map(vgic_node, 0);
+	if (!irq) {
+		ret = -ENXIO;
+		goto out_free_vcpus;
+	}
+
+	ret = request_percpu_irq(irq, kvm_vgic_maintainance_handler,
 				 "vgic", vgic_vcpus);
 	if (ret) {
-		kvm_err("Cannot register interrupt %d\n", VGIC_MAINT_IRQ);
+		kvm_err("Cannot register interrupt %d\n", irq);
 		goto out_free_vcpus;
 	}
 	
-	vgic_vctrl_base = ioremap(VGIC_VCTRL_BASE, VGIC_VCTRL_SIZE);
+	ret = of_address_to_resource(vgic_node, 2, &vctrl_res);
+	if (ret) {
+		kvm_err("Cannot obtain VCTRL resource\n");
+		goto out_free_irq;
+	}
+
+	vgic_vctrl_base = of_iomap(vgic_node, 2);
 	if (!vgic_vctrl_base) {
 		kvm_err("Cannot ioremap VCTRL\n");
+		ret = -ENOMEM;
 		goto out_free_irq;
 	}
 
-	ret = create_hyp_io_mappings(kvm_hyp_pgd,
-				     vgic_vctrl_base,
-				     vgic_vctrl_base + VGIC_VCTRL_SIZE,
-				     VGIC_VCTRL_BASE);
+	ret = create_hyp_io_mappings(vgic_vctrl_base,
+				     vgic_vctrl_base + resource_size(&vctrl_res),
+				     vctrl_res.start);
 	if (ret) {
 		kvm_err("Cannot map VCTRL into hyp\n");
 		goto out_unmap;
 	}
 
+	kvm_info("%s@%llx IRQ%d\n", vgic_node->name, vctrl_res.start, irq);
 	return 0;
 
 out_unmap:
 	iounmap(vgic_vctrl_base);	
 out_free_irq:
-	free_percpu_irq(VGIC_MAINT_IRQ, vgic_vcpus);
+	free_percpu_irq(irq, vgic_vcpus);
 out_free_vcpus:
 	free_percpu(vgic_vcpus);
 
@@ -821,17 +839,27 @@ out_free_vcpus:
 
 int kvm_vgic_init(struct kvm *kvm)
 {
-	int ret = -EEXIST;
+	int ret;
+	struct resource vcpu_res;
 
 	mutex_lock(&kvm->lock);
-	if (atomic_read(&kvm->online_vcpus))
+
+	if (of_address_to_resource(vgic_node, 3, &vcpu_res)) {
+		kvm_err("Cannot obtain VCPU resource\n");
+		ret = -ENXIO;
 		goto out;
+	}
+
+	if (atomic_read(&kvm->online_vcpus)) {
+		ret = -EEXIST;
+		goto out;
+	}
 
 	spin_lock_init(&kvm->arch.vgic.lock);
 	kvm->arch.vgic.vctrl_base = vgic_vctrl_base;
 
 	ret = kvm_phys_addr_ioremap(kvm, VGIC_CPU_BASE,
-				    VGIC_VCPU_BASE, VGIC_CPU_SIZE);
+				    vcpu_res.start, VGIC_CPU_SIZE);
 	if (ret)
 		kvm_err("Unable to remap VGIC CPU to VCPU\n");
 out:
-- 
1.7.7.1





[Index of Archives]     [Linux KVM]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux