|
@@ -0,0 +1,83 @@
|
|
|
+/*
|
|
|
+ * Copyright (C) 2017 ARM Ltd.
|
|
|
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
|
|
|
+ *
|
|
|
+ * This program is free software; you can redistribute it and/or modify
|
|
|
+ * it under the terms of the GNU General Public License version 2 as
|
|
|
+ * published by the Free Software Foundation.
|
|
|
+ *
|
|
|
+ * This program is distributed in the hope that it will be useful,
|
|
|
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
+ * GNU General Public License for more details.
|
|
|
+ *
|
|
|
+ * You should have received a copy of the GNU General Public License
|
|
|
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
+ */
|
|
|
+
|
|
|
+#include <linux/interrupt.h>
|
|
|
+#include <linux/irqdomain.h>
|
|
|
+#include <linux/kvm_host.h>
|
|
|
+
|
|
|
+#include "vgic.h"
|
|
|
+
|
|
|
+/**
|
|
|
+ * vgic_v4_init - Initialize the GICv4 data structures
|
|
|
+ * @kvm: Pointer to the VM being initialized
|
|
|
+ *
|
|
|
+ * We may be called each time a vITS is created, or when the
|
|
|
+ * vgic is initialized. This relies on kvm->lock to be
|
|
|
+ * held. In both cases, the number of vcpus should now be
|
|
|
+ * fixed.
|
|
|
+ */
|
|
|
+int vgic_v4_init(struct kvm *kvm)
|
|
|
+{
|
|
|
+ struct vgic_dist *dist = &kvm->arch.vgic;
|
|
|
+ struct kvm_vcpu *vcpu;
|
|
|
+ int i, nr_vcpus, ret;
|
|
|
+
|
|
|
+ if (dist->its_vm.vpes)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ nr_vcpus = atomic_read(&kvm->online_vcpus);
|
|
|
+
|
|
|
+ dist->its_vm.vpes = kzalloc(sizeof(*dist->its_vm.vpes) * nr_vcpus,
|
|
|
+ GFP_KERNEL);
|
|
|
+ if (!dist->its_vm.vpes)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ dist->its_vm.nr_vpes = nr_vcpus;
|
|
|
+
|
|
|
+ kvm_for_each_vcpu(i, vcpu, kvm)
|
|
|
+ dist->its_vm.vpes[i] = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
|
|
|
+
|
|
|
+ ret = its_alloc_vcpu_irqs(&dist->its_vm);
|
|
|
+ if (ret < 0) {
|
|
|
+ kvm_err("VPE IRQ allocation failure\n");
|
|
|
+ kfree(dist->its_vm.vpes);
|
|
|
+ dist->its_vm.nr_vpes = 0;
|
|
|
+ dist->its_vm.vpes = NULL;
|
|
|
+ return ret;
|
|
|
+ }
|
|
|
+
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * vgic_v4_teardown - Free the GICv4 data structures
|
|
|
+ * @kvm: Pointer to the VM being destroyed
|
|
|
+ *
|
|
|
+ * Relies on kvm->lock to be held.
|
|
|
+ */
|
|
|
+void vgic_v4_teardown(struct kvm *kvm)
|
|
|
+{
|
|
|
+ struct its_vm *its_vm = &kvm->arch.vgic.its_vm;
|
|
|
+
|
|
|
+ if (!its_vm->vpes)
|
|
|
+ return;
|
|
|
+
|
|
|
+ its_free_vcpu_irqs(its_vm);
|
|
|
+ kfree(its_vm->vpes);
|
|
|
+ its_vm->nr_vpes = 0;
|
|
|
+ its_vm->vpes = NULL;
|
|
|
+}
|