diff options
author | Julien Grall <julien.grall@arm.com> | 2016-04-11 18:32:59 +0300 |
---|---|---|
committer | Christoffer Dall <christoffer.dall@linaro.org> | 2016-05-03 13:54:21 +0300 |
commit | 503a62862e8fc08b2d4c0db06ba3adae3bbd61bc (patch) | |
tree | 7a0ea075e41fa405b25eba35d7a86f305575856f /virt/kvm/arm/vgic-v2.c | |
parent | 29c2d6ff4cf9af6bcbba3a76aae1d5cacd5da16b (diff) | |
download | linux-503a62862e8fc08b2d4c0db06ba3adae3bbd61bc.tar.xz |
KVM: arm/arm64: vgic: Rely on the GIC driver to parse the firmware tables
Currently, the firmware tables are parsed 2 times: once in the GIC
drivers, the other time when initializing the vGIC. It means code
duplication and make more tedious to add the support for another
firmware table (like ACPI).
Use the recently introduced helper gic_get_kvm_info() to get
information about the virtual GIC.
With this change, the virtual GIC becomes agnostic to the firmware
table and KVM will be able to initialize the vGIC on ACPI.
Signed-off-by: Julien Grall <julien.grall@arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'virt/kvm/arm/vgic-v2.c')
-rw-r--r-- | virt/kvm/arm/vgic-v2.c | 61 |
1 files changed, 26 insertions, 35 deletions
diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c index 67ec334ce1d0..7e826c9b2b0a 100644 --- a/virt/kvm/arm/vgic-v2.c +++ b/virt/kvm/arm/vgic-v2.c @@ -20,9 +20,6 @@ #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 <linux/irqchip/arm-gic.h> @@ -186,38 +183,39 @@ static void vgic_cpu_init_lrs(void *params) } /** - * vgic_v2_probe - probe for a GICv2 compatible interrupt controller in DT - * @node: pointer to the DT node - * @ops: address of a pointer to the GICv2 operations - * @params: address of a pointer to HW-specific parameters + * vgic_v2_probe - probe for a GICv2 compatible interrupt controller + * @gic_kvm_info: pointer to the GIC description + * @ops: address of a pointer to the GICv2 operations + * @params: address of a pointer to HW-specific parameters * * Returns 0 if a GICv2 has been found, with the low level operations * in *ops and the HW parameters in *params. Returns an error code * otherwise. */ -int vgic_v2_probe(struct device_node *vgic_node, - const struct vgic_ops **ops, - const struct vgic_params **params) +int vgic_v2_probe(const struct gic_kvm_info *gic_kvm_info, + const struct vgic_ops **ops, + const struct vgic_params **params) { int ret; - struct resource vctrl_res; - struct resource vcpu_res; struct vgic_params *vgic = &vgic_v2_params; + const struct resource *vctrl_res = &gic_kvm_info->vctrl; + const struct resource *vcpu_res = &gic_kvm_info->vcpu; - 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"); + if (!gic_kvm_info->maint_irq) { + kvm_err("error getting vgic maintenance irq\n"); ret = -ENXIO; goto out; } + vgic->maint_irq = gic_kvm_info->maint_irq; - ret = of_address_to_resource(vgic_node, 2, &vctrl_res); - if (ret) { - kvm_err("Cannot obtain GICH resource\n"); + if (!gic_kvm_info->vctrl.start) { + kvm_err("GICH not present in the firmware table\n"); + ret = -ENXIO; goto out; } - vgic->vctrl_base = of_iomap(vgic_node, 2); + vgic->vctrl_base = ioremap(gic_kvm_info->vctrl.start, + resource_size(&gic_kvm_info->vctrl)); if (!vgic->vctrl_base) { kvm_err("Cannot ioremap GICH\n"); ret = -ENOMEM; @@ -228,29 +226,23 @@ int vgic_v2_probe(struct device_node *vgic_node, vgic->nr_lr = (vgic->nr_lr & 0x3f) + 1; ret = create_hyp_io_mappings(vgic->vctrl_base, - vgic->vctrl_base + resource_size(&vctrl_res), - vctrl_res.start); + vgic->vctrl_base + resource_size(vctrl_res), + vctrl_res->start); if (ret) { kvm_err("Cannot map VCTRL into hyp\n"); 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)) { + if (!PAGE_ALIGNED(vcpu_res->start)) { kvm_err("GICV physical address 0x%llx not page aligned\n", - (unsigned long long)vcpu_res.start); + (unsigned long long)vcpu_res->start); ret = -ENXIO; goto out_unmap; } - if (!PAGE_ALIGNED(resource_size(&vcpu_res))) { + if (!PAGE_ALIGNED(resource_size(vcpu_res))) { kvm_err("GICV size 0x%llx not a multiple of page size 0x%lx\n", - (unsigned long long)resource_size(&vcpu_res), + (unsigned long long)resource_size(vcpu_res), PAGE_SIZE); ret = -ENXIO; goto out_unmap; @@ -259,10 +251,10 @@ int vgic_v2_probe(struct device_node *vgic_node, 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; + vgic->vcpu_base = vcpu_res->start; - kvm_info("%s@%llx IRQ%d\n", vgic_node->name, - vctrl_res.start, vgic->maint_irq); + kvm_info("GICH base=0x%llx, GICV base=0x%llx, IRQ=%d\n", + gic_kvm_info->vctrl.start, vgic->vcpu_base, vgic->maint_irq); vgic->type = VGIC_V2; vgic->max_gic_vcpus = VGIC_V2_MAX_CPUS; @@ -276,6 +268,5 @@ int vgic_v2_probe(struct device_node *vgic_node, out_unmap: iounmap(vgic->vctrl_base); out: - of_node_put(vgic_node); return ret; } |