KVM: arm64: Simplify the CPUHP logic
authorMarc Zyngier <maz@kernel.org>
Wed, 30 Nov 2022 23:09:00 +0000 (23:09 +0000)
committerPaolo Bonzini <pbonzini@redhat.com>
Thu, 29 Dec 2022 20:41:04 +0000 (15:41 -0500)
For a number of historical reasons, the KVM/arm64 hotplug setup is pretty
complicated, and we have two extra CPUHP notifiers for vGIC and timers.

It looks pretty pointless, and gets in the way of further changes.
So let's just expose some helpers that can be called from the core
CPUHP callback, and get rid of everything else.

This gives us the opportunity to drop a useless notifier entry,
as well as tidy-up the timer enable/disable, which was a bit odd.

Signed-off-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Message-Id: <20221130230934.1014142-17-seanjc@google.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/arm64/kvm/arch_timer.c
arch/arm64/kvm/arm.c
arch/arm64/kvm/vgic/vgic-init.c
include/kvm/arm_arch_timer.h
include/kvm/arm_vgic.h
include/linux/cpuhotplug.h

index bb24a76b4224b3777a7ee82864a845bdb642a1ec..33fca1a691a53c7382015bd6cbd34e02c152da67 100644 (file)
@@ -811,10 +811,18 @@ void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu)
        ptimer->host_timer_irq_flags = host_ptimer_irq_flags;
 }
 
-static void kvm_timer_init_interrupt(void *info)
+void kvm_timer_cpu_up(void)
 {
        enable_percpu_irq(host_vtimer_irq, host_vtimer_irq_flags);
-       enable_percpu_irq(host_ptimer_irq, host_ptimer_irq_flags);
+       if (host_ptimer_irq)
+               enable_percpu_irq(host_ptimer_irq, host_ptimer_irq_flags);
+}
+
+void kvm_timer_cpu_down(void)
+{
+       disable_percpu_irq(host_vtimer_irq);
+       if (host_ptimer_irq)
+               disable_percpu_irq(host_ptimer_irq);
 }
 
 int kvm_arm_timer_set_reg(struct kvm_vcpu *vcpu, u64 regid, u64 value)
@@ -976,18 +984,6 @@ void kvm_arm_timer_write_sysreg(struct kvm_vcpu *vcpu,
        preempt_enable();
 }
 
-static int kvm_timer_starting_cpu(unsigned int cpu)
-{
-       kvm_timer_init_interrupt(NULL);
-       return 0;
-}
-
-static int kvm_timer_dying_cpu(unsigned int cpu)
-{
-       disable_percpu_irq(host_vtimer_irq);
-       return 0;
-}
-
 static int timer_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu)
 {
        if (vcpu)
@@ -1185,9 +1181,6 @@ int kvm_timer_hyp_init(bool has_gic)
                goto out_free_irq;
        }
 
-       cpuhp_setup_state(CPUHP_AP_KVM_ARM_TIMER_STARTING,
-                         "kvm/arm/timer:starting", kvm_timer_starting_cpu,
-                         kvm_timer_dying_cpu);
        return 0;
 out_free_irq:
        free_percpu_irq(host_vtimer_irq, kvm_get_running_vcpus());
index e6c21b804c13aa6b96828b170148c06585e3eda7..b572c78f3c2392c1d0ab0ad2b4311f416d3a7b6c 100644 (file)
@@ -1677,7 +1677,15 @@ static void _kvm_arch_hardware_enable(void *discard)
 
 int kvm_arch_hardware_enable(void)
 {
+       int was_enabled = __this_cpu_read(kvm_arm_hardware_enabled);
+
        _kvm_arch_hardware_enable(NULL);
+
+       if (!was_enabled) {
+               kvm_vgic_cpu_up();
+               kvm_timer_cpu_up();
+       }
+
        return 0;
 }
 
@@ -1691,6 +1699,11 @@ static void _kvm_arch_hardware_disable(void *discard)
 
 void kvm_arch_hardware_disable(void)
 {
+       if (__this_cpu_read(kvm_arm_hardware_enabled)) {
+               kvm_timer_cpu_down();
+               kvm_vgic_cpu_down();
+       }
+
        if (!is_protected_kvm_enabled())
                _kvm_arch_hardware_disable(NULL);
 }
index f6d4f4052555c79aef58f3d7b87440dbe9c7c276..6c7f6ae21ec056987a770494abaf7cb97d8967d0 100644 (file)
@@ -465,17 +465,15 @@ out:
 
 /* GENERIC PROBE */
 
-static int vgic_init_cpu_starting(unsigned int cpu)
+void kvm_vgic_cpu_up(void)
 {
        enable_percpu_irq(kvm_vgic_global_state.maint_irq, 0);
-       return 0;
 }
 
 
-static int vgic_init_cpu_dying(unsigned int cpu)
+void kvm_vgic_cpu_down(void)
 {
        disable_percpu_irq(kvm_vgic_global_state.maint_irq);
-       return 0;
 }
 
 static irqreturn_t vgic_maintenance_handler(int irq, void *data)
@@ -584,19 +582,6 @@ int kvm_vgic_hyp_init(void)
                return ret;
        }
 
-       ret = cpuhp_setup_state(CPUHP_AP_KVM_ARM_VGIC_INIT_STARTING,
-                               "kvm/arm/vgic:starting",
-                               vgic_init_cpu_starting, vgic_init_cpu_dying);
-       if (ret) {
-               kvm_err("Cannot register vgic CPU notifier\n");
-               goto out_free_irq;
-       }
-
        kvm_info("vgic interrupt IRQ%d\n", kvm_vgic_global_state.maint_irq);
        return 0;
-
-out_free_irq:
-       free_percpu_irq(kvm_vgic_global_state.maint_irq,
-                       kvm_get_running_vcpus());
-       return ret;
 }
index cd6d8f260eab1415dad7feec0ebf5c868b5275b1..1638418f72dd9b55e0c7ef7616613ade6c1c7c8d 100644 (file)
@@ -104,4 +104,8 @@ void kvm_arm_timer_write_sysreg(struct kvm_vcpu *vcpu,
 u32 timer_get_ctl(struct arch_timer_context *ctxt);
 u64 timer_get_cval(struct arch_timer_context *ctxt);
 
+/* CPU HP callbacks */
+void kvm_timer_cpu_up(void);
+void kvm_timer_cpu_down(void);
+
 #endif
index 9270cd87da3fc806319bd1df08246b4879497582..0629e3532ad0442427beca2b4d7cfdaa5e49a04b 100644 (file)
@@ -432,4 +432,8 @@ int vgic_v4_load(struct kvm_vcpu *vcpu);
 void vgic_v4_commit(struct kvm_vcpu *vcpu);
 int vgic_v4_put(struct kvm_vcpu *vcpu, bool need_db);
 
+/* CPU HP callbacks */
+void kvm_vgic_cpu_up(void);
+void kvm_vgic_cpu_down(void);
+
 #endif /* __KVM_ARM_VGIC_H */
index 6c6859bfc454cfa333d89924991d9e1fc40419b7..5cae6bd22f7faf73bbcc444760071774180dd39d 100644 (file)
@@ -188,9 +188,6 @@ enum cpuhp_state {
        CPUHP_AP_TI_GP_TIMER_STARTING,
        CPUHP_AP_HYPERV_TIMER_STARTING,
        CPUHP_AP_KVM_STARTING,
-       CPUHP_AP_KVM_ARM_VGIC_INIT_STARTING,
-       CPUHP_AP_KVM_ARM_VGIC_STARTING,
-       CPUHP_AP_KVM_ARM_TIMER_STARTING,
        /* Must be the last timer callback */
        CPUHP_AP_DUMMY_TIMER_STARTING,
        CPUHP_AP_ARM_XEN_STARTING,