|
@@ -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;
|
|
|
}
|