Register a CPU hotplug notifier that disables/enables the interrupt as requested. Signed-off-by: Marc Zyngier <marc.zyngier@xxxxxxx> --- arch/arm/kvm/vgic.c | 47 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c index e2663a8..451ceec 100644 --- a/arch/arm/kvm/vgic.c +++ b/arch/arm/kvm/vgic.c @@ -16,6 +16,7 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <linux/cpu.h> #include <linux/kvm.h> #include <linux/kvm_host.h> #include <linux/interrupt.h> @@ -93,6 +94,8 @@ static void vgic_dispatch_sgi(struct kvm_vcpu *vcpu, u32 reg); static u32 vgic_nr_lr; +static unsigned int vgic_maint_irq; + static u32 *vgic_bitmap_get_reg(struct vgic_bitmap *x, int cpuid, u32 offset) { @@ -1269,15 +1272,33 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) static void vgic_init_maintenance_interrupt(void *info) { - unsigned int *irqp = info; + enable_percpu_irq(vgic_maint_irq, 0); +} + +static int vgic_cpu_notify(struct notifier_block *self, + unsigned long action, void *cpu) +{ + switch (action) { + case CPU_STARTING: + case CPU_STARTING_FROZEN: + vgic_init_maintenance_interrupt(NULL); + break; + case CPU_DYING: + case CPU_DYING_FROZEN: + disable_percpu_irq(vgic_maint_irq); + break; + } - enable_percpu_irq(*irqp, 0); + return NOTIFY_OK; } +static struct notifier_block vgic_cpu_nb = { + .notifier_call = vgic_cpu_notify, +}; + int kvm_vgic_hyp_init(void) { int ret; - unsigned int irq; struct resource vctrl_res; struct resource vcpu_res; @@ -1285,17 +1306,23 @@ int kvm_vgic_hyp_init(void) if (!vgic_node) return -ENODEV; - irq = irq_of_parse_and_map(vgic_node, 0); - if (!irq) + vgic_maint_irq = irq_of_parse_and_map(vgic_node, 0); + if (!vgic_irq) return -ENXIO; - ret = request_percpu_irq(irq, vgic_maintenance_handler, + ret = request_percpu_irq(vgic_maint_irq, vgic_maintenance_handler, "vgic", kvm_get_running_vcpus()); if (ret) { - kvm_err("Cannot register interrupt %d\n", irq); + kvm_err("Cannot register interrupt %d\n", vgic_maint_irq); return ret; } + ret = register_cpu_notifier(&vgic_cpu_nb); + if (ret) { + kvm_err("Cannot register vgic CPU notifier\n"); + goto out_free_irq; + } + ret = of_address_to_resource(vgic_node, 2, &vctrl_res); if (ret) { kvm_err("Cannot obtain VCTRL resource\n"); @@ -1320,8 +1347,8 @@ int kvm_vgic_hyp_init(void) goto out_unmap; } - kvm_info("%s@%llx IRQ%d\n", vgic_node->name, vctrl_res.start, irq); - on_each_cpu(vgic_init_maintenance_interrupt, &irq, 1); + kvm_info("%s@%llx IRQ%d\n", vgic_node->name, vctrl_res.start, vgic_maint_irq); + on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1); if (of_address_to_resource(vgic_node, 3, &vcpu_res)) { kvm_err("Cannot obtain VCPU resource\n"); @@ -1335,7 +1362,7 @@ int kvm_vgic_hyp_init(void) out_unmap: iounmap(vgic_vctrl_base); out_free_irq: - free_percpu_irq(irq, kvm_get_running_vcpus()); + free_percpu_irq(vgic_maint_irq, kvm_get_running_vcpus()); return ret; } -- 1.8.0.1 _______________________________________________ kvmarm mailing list kvmarm@xxxxxxxxxxxxxxxxxxxxx https://lists.cs.columbia.edu/cucslists/listinfo/kvmarm