diff options
Diffstat (limited to 'virt/kvm')
| -rw-r--r-- | virt/kvm/arm/arch_timer.c | 35 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic.c | 39 | ||||
| -rw-r--r-- | virt/kvm/arm/vgic/vgic-init.c | 31 | ||||
| -rw-r--r-- | virt/kvm/kvm_main.c | 32 |
4 files changed, 36 insertions, 101 deletions
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c index e2d5b6f988fb..4fde8c7dfcfe 100644 --- a/virt/kvm/arm/arch_timer.c +++ b/virt/kvm/arm/arch_timer.c | |||
| @@ -405,26 +405,17 @@ u64 kvm_arm_timer_get_reg(struct kvm_vcpu *vcpu, u64 regid) | |||
| 405 | return (u64)-1; | 405 | return (u64)-1; |
| 406 | } | 406 | } |
| 407 | 407 | ||
| 408 | static int kvm_timer_cpu_notify(struct notifier_block *self, | 408 | static int kvm_timer_starting_cpu(unsigned int cpu) |
| 409 | unsigned long action, void *cpu) | ||
| 410 | { | 409 | { |
| 411 | switch (action) { | 410 | kvm_timer_init_interrupt(NULL); |
| 412 | case CPU_STARTING: | 411 | return 0; |
| 413 | case CPU_STARTING_FROZEN: | ||
| 414 | kvm_timer_init_interrupt(NULL); | ||
| 415 | break; | ||
| 416 | case CPU_DYING: | ||
| 417 | case CPU_DYING_FROZEN: | ||
| 418 | disable_percpu_irq(host_vtimer_irq); | ||
| 419 | break; | ||
| 420 | } | ||
| 421 | |||
| 422 | return NOTIFY_OK; | ||
| 423 | } | 412 | } |
| 424 | 413 | ||
| 425 | static struct notifier_block kvm_timer_cpu_nb = { | 414 | static int kvm_timer_dying_cpu(unsigned int cpu) |
| 426 | .notifier_call = kvm_timer_cpu_notify, | 415 | { |
| 427 | }; | 416 | disable_percpu_irq(host_vtimer_irq); |
| 417 | return 0; | ||
| 418 | } | ||
| 428 | 419 | ||
| 429 | int kvm_timer_hyp_init(void) | 420 | int kvm_timer_hyp_init(void) |
| 430 | { | 421 | { |
| @@ -449,12 +440,6 @@ int kvm_timer_hyp_init(void) | |||
| 449 | goto out; | 440 | goto out; |
| 450 | } | 441 | } |
| 451 | 442 | ||
| 452 | err = __register_cpu_notifier(&kvm_timer_cpu_nb); | ||
| 453 | if (err) { | ||
| 454 | kvm_err("Cannot register timer CPU notifier\n"); | ||
| 455 | goto out_free; | ||
| 456 | } | ||
| 457 | |||
| 458 | wqueue = create_singlethread_workqueue("kvm_arch_timer"); | 443 | wqueue = create_singlethread_workqueue("kvm_arch_timer"); |
| 459 | if (!wqueue) { | 444 | if (!wqueue) { |
| 460 | err = -ENOMEM; | 445 | err = -ENOMEM; |
| @@ -462,8 +447,10 @@ int kvm_timer_hyp_init(void) | |||
| 462 | } | 447 | } |
| 463 | 448 | ||
| 464 | kvm_info("virtual timer IRQ%d\n", host_vtimer_irq); | 449 | kvm_info("virtual timer IRQ%d\n", host_vtimer_irq); |
| 465 | on_each_cpu(kvm_timer_init_interrupt, NULL, 1); | ||
| 466 | 450 | ||
| 451 | cpuhp_setup_state(CPUHP_AP_KVM_ARM_TIMER_STARTING, | ||
| 452 | "AP_KVM_ARM_TIMER_STARTING", kvm_timer_starting_cpu, | ||
| 453 | kvm_timer_dying_cpu); | ||
| 467 | goto out; | 454 | goto out; |
| 468 | out_free: | 455 | out_free: |
| 469 | free_percpu_irq(host_vtimer_irq, kvm_get_running_vcpus()); | 456 | free_percpu_irq(host_vtimer_irq, kvm_get_running_vcpus()); |
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c index c3bfbb981e73..67cb5e948be2 100644 --- a/virt/kvm/arm/vgic.c +++ b/virt/kvm/arm/vgic.c | |||
| @@ -2326,32 +2326,18 @@ int vgic_has_attr_regs(const struct vgic_io_range *ranges, phys_addr_t offset) | |||
| 2326 | return -ENXIO; | 2326 | return -ENXIO; |
| 2327 | } | 2327 | } |
| 2328 | 2328 | ||
| 2329 | static void vgic_init_maintenance_interrupt(void *info) | 2329 | static int vgic_starting_cpu(unsigned int cpu) |
| 2330 | { | 2330 | { |
| 2331 | enable_percpu_irq(vgic->maint_irq, 0); | 2331 | enable_percpu_irq(vgic->maint_irq, 0); |
| 2332 | return 0; | ||
| 2332 | } | 2333 | } |
| 2333 | 2334 | ||
| 2334 | static int vgic_cpu_notify(struct notifier_block *self, | 2335 | static int vgic_dying_cpu(unsigned int cpu) |
| 2335 | unsigned long action, void *cpu) | ||
| 2336 | { | 2336 | { |
| 2337 | switch (action) { | 2337 | disable_percpu_irq(vgic->maint_irq); |
| 2338 | case CPU_STARTING: | 2338 | return 0; |
| 2339 | case CPU_STARTING_FROZEN: | ||
| 2340 | vgic_init_maintenance_interrupt(NULL); | ||
| 2341 | break; | ||
| 2342 | case CPU_DYING: | ||
| 2343 | case CPU_DYING_FROZEN: | ||
| 2344 | disable_percpu_irq(vgic->maint_irq); | ||
| 2345 | break; | ||
| 2346 | } | ||
| 2347 | |||
| 2348 | return NOTIFY_OK; | ||
| 2349 | } | 2339 | } |
| 2350 | 2340 | ||
| 2351 | static struct notifier_block vgic_cpu_nb = { | ||
| 2352 | .notifier_call = vgic_cpu_notify, | ||
| 2353 | }; | ||
| 2354 | |||
| 2355 | static int kvm_vgic_probe(void) | 2341 | static int kvm_vgic_probe(void) |
| 2356 | { | 2342 | { |
| 2357 | const struct gic_kvm_info *gic_kvm_info; | 2343 | const struct gic_kvm_info *gic_kvm_info; |
| @@ -2392,19 +2378,10 @@ int kvm_vgic_hyp_init(void) | |||
| 2392 | return ret; | 2378 | return ret; |
| 2393 | } | 2379 | } |
| 2394 | 2380 | ||
| 2395 | ret = __register_cpu_notifier(&vgic_cpu_nb); | 2381 | cpuhp_setup_state(CPUHP_AP_KVM_ARM_VGIC_STARTING, |
| 2396 | if (ret) { | 2382 | "AP_KVM_ARM_VGIC_STARTING", vgic_starting_cpu, |
| 2397 | kvm_err("Cannot register vgic CPU notifier\n"); | 2383 | vgic_dying_cpu); |
| 2398 | goto out_free_irq; | ||
| 2399 | } | ||
| 2400 | |||
| 2401 | on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1); | ||
| 2402 | |||
| 2403 | return 0; | 2384 | return 0; |
| 2404 | |||
| 2405 | out_free_irq: | ||
| 2406 | free_percpu_irq(vgic->maint_irq, kvm_get_running_vcpus()); | ||
| 2407 | return ret; | ||
| 2408 | } | 2385 | } |
| 2409 | 2386 | ||
| 2410 | int kvm_irq_map_gsi(struct kvm *kvm, | 2387 | int kvm_irq_map_gsi(struct kvm *kvm, |
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c index a1442f7c9c4d..2c7f0d5a62ea 100644 --- a/virt/kvm/arm/vgic/vgic-init.c +++ b/virt/kvm/arm/vgic/vgic-init.c | |||
| @@ -353,32 +353,19 @@ out: | |||
| 353 | 353 | ||
| 354 | /* GENERIC PROBE */ | 354 | /* GENERIC PROBE */ |
| 355 | 355 | ||
| 356 | static void vgic_init_maintenance_interrupt(void *info) | 356 | static int vgic_init_cpu_starting(unsigned int cpu) |
| 357 | { | 357 | { |
| 358 | enable_percpu_irq(kvm_vgic_global_state.maint_irq, 0); | 358 | enable_percpu_irq(kvm_vgic_global_state.maint_irq, 0); |
| 359 | return 0; | ||
| 359 | } | 360 | } |
| 360 | 361 | ||
| 361 | static int vgic_cpu_notify(struct notifier_block *self, | ||
| 362 | unsigned long action, void *cpu) | ||
| 363 | { | ||
| 364 | switch (action) { | ||
| 365 | case CPU_STARTING: | ||
| 366 | case CPU_STARTING_FROZEN: | ||
| 367 | vgic_init_maintenance_interrupt(NULL); | ||
| 368 | break; | ||
| 369 | case CPU_DYING: | ||
| 370 | case CPU_DYING_FROZEN: | ||
| 371 | disable_percpu_irq(kvm_vgic_global_state.maint_irq); | ||
| 372 | break; | ||
| 373 | } | ||
| 374 | 362 | ||
| 375 | return NOTIFY_OK; | 363 | static int vgic_init_cpu_dying(unsigned int cpu) |
| 364 | { | ||
| 365 | disable_percpu_irq(kvm_vgic_global_state.maint_irq); | ||
| 366 | return 0; | ||
| 376 | } | 367 | } |
| 377 | 368 | ||
| 378 | static struct notifier_block vgic_cpu_nb = { | ||
| 379 | .notifier_call = vgic_cpu_notify, | ||
| 380 | }; | ||
| 381 | |||
| 382 | static irqreturn_t vgic_maintenance_handler(int irq, void *data) | 369 | static irqreturn_t vgic_maintenance_handler(int irq, void *data) |
| 383 | { | 370 | { |
| 384 | /* | 371 | /* |
| @@ -434,14 +421,14 @@ int kvm_vgic_hyp_init(void) | |||
| 434 | return ret; | 421 | return ret; |
| 435 | } | 422 | } |
| 436 | 423 | ||
| 437 | ret = __register_cpu_notifier(&vgic_cpu_nb); | 424 | ret = cpuhp_setup_state(CPUHP_AP_KVM_ARM_VGIC_INIT_STARTING, |
| 425 | "AP_KVM_ARM_VGIC_INIT_STARTING", | ||
| 426 | vgic_init_cpu_starting, vgic_init_cpu_dying); | ||
| 438 | if (ret) { | 427 | if (ret) { |
| 439 | kvm_err("Cannot register vgic CPU notifier\n"); | 428 | kvm_err("Cannot register vgic CPU notifier\n"); |
| 440 | goto out_free_irq; | 429 | goto out_free_irq; |
| 441 | } | 430 | } |
| 442 | 431 | ||
| 443 | on_each_cpu(vgic_init_maintenance_interrupt, NULL, 1); | ||
| 444 | |||
| 445 | kvm_info("vgic interrupt IRQ%d\n", kvm_vgic_global_state.maint_irq); | 432 | kvm_info("vgic interrupt IRQ%d\n", kvm_vgic_global_state.maint_irq); |
| 446 | return 0; | 433 | return 0; |
| 447 | 434 | ||
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index ce3d8e5be73e..2e791367c576 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c | |||
| @@ -3155,12 +3155,13 @@ static void hardware_enable_nolock(void *junk) | |||
| 3155 | } | 3155 | } |
| 3156 | } | 3156 | } |
| 3157 | 3157 | ||
| 3158 | static void hardware_enable(void) | 3158 | static int kvm_starting_cpu(unsigned int cpu) |
| 3159 | { | 3159 | { |
| 3160 | raw_spin_lock(&kvm_count_lock); | 3160 | raw_spin_lock(&kvm_count_lock); |
| 3161 | if (kvm_usage_count) | 3161 | if (kvm_usage_count) |
| 3162 | hardware_enable_nolock(NULL); | 3162 | hardware_enable_nolock(NULL); |
| 3163 | raw_spin_unlock(&kvm_count_lock); | 3163 | raw_spin_unlock(&kvm_count_lock); |
| 3164 | return 0; | ||
| 3164 | } | 3165 | } |
| 3165 | 3166 | ||
| 3166 | static void hardware_disable_nolock(void *junk) | 3167 | static void hardware_disable_nolock(void *junk) |
| @@ -3173,12 +3174,13 @@ static void hardware_disable_nolock(void *junk) | |||
| 3173 | kvm_arch_hardware_disable(); | 3174 | kvm_arch_hardware_disable(); |
| 3174 | } | 3175 | } |
| 3175 | 3176 | ||
| 3176 | static void hardware_disable(void) | 3177 | static int kvm_dying_cpu(unsigned int cpu) |
| 3177 | { | 3178 | { |
| 3178 | raw_spin_lock(&kvm_count_lock); | 3179 | raw_spin_lock(&kvm_count_lock); |
| 3179 | if (kvm_usage_count) | 3180 | if (kvm_usage_count) |
| 3180 | hardware_disable_nolock(NULL); | 3181 | hardware_disable_nolock(NULL); |
| 3181 | raw_spin_unlock(&kvm_count_lock); | 3182 | raw_spin_unlock(&kvm_count_lock); |
| 3183 | return 0; | ||
| 3182 | } | 3184 | } |
| 3183 | 3185 | ||
| 3184 | static void hardware_disable_all_nolock(void) | 3186 | static void hardware_disable_all_nolock(void) |
| @@ -3219,21 +3221,6 @@ static int hardware_enable_all(void) | |||
| 3219 | return r; | 3221 | return r; |
| 3220 | } | 3222 | } |
| 3221 | 3223 | ||
| 3222 | static int kvm_cpu_hotplug(struct notifier_block *notifier, unsigned long val, | ||
| 3223 | void *v) | ||
| 3224 | { | ||
| 3225 | val &= ~CPU_TASKS_FROZEN; | ||
| 3226 | switch (val) { | ||
| 3227 | case CPU_DYING: | ||
| 3228 | hardware_disable(); | ||
| 3229 | break; | ||
| 3230 | case CPU_STARTING: | ||
| 3231 | hardware_enable(); | ||
| 3232 | break; | ||
| 3233 | } | ||
| 3234 | return NOTIFY_OK; | ||
| 3235 | } | ||
| 3236 | |||
| 3237 | static int kvm_reboot(struct notifier_block *notifier, unsigned long val, | 3224 | static int kvm_reboot(struct notifier_block *notifier, unsigned long val, |
| 3238 | void *v) | 3225 | void *v) |
| 3239 | { | 3226 | { |
| @@ -3500,10 +3487,6 @@ int kvm_io_bus_unregister_dev(struct kvm *kvm, enum kvm_bus bus_idx, | |||
| 3500 | return r; | 3487 | return r; |
| 3501 | } | 3488 | } |
| 3502 | 3489 | ||
| 3503 | static struct notifier_block kvm_cpu_notifier = { | ||
| 3504 | .notifier_call = kvm_cpu_hotplug, | ||
| 3505 | }; | ||
| 3506 | |||
| 3507 | static int kvm_debugfs_open(struct inode *inode, struct file *file, | 3490 | static int kvm_debugfs_open(struct inode *inode, struct file *file, |
| 3508 | int (*get)(void *, u64 *), int (*set)(void *, u64), | 3491 | int (*get)(void *, u64 *), int (*set)(void *, u64), |
| 3509 | const char *fmt) | 3492 | const char *fmt) |
| @@ -3754,7 +3737,8 @@ int kvm_init(void *opaque, unsigned vcpu_size, unsigned vcpu_align, | |||
| 3754 | goto out_free_1; | 3737 | goto out_free_1; |
| 3755 | } | 3738 | } |
| 3756 | 3739 | ||
| 3757 | r = register_cpu_notifier(&kvm_cpu_notifier); | 3740 | r = cpuhp_setup_state_nocalls(CPUHP_AP_KVM_STARTING, "AP_KVM_STARTING", |
| 3741 | kvm_starting_cpu, kvm_dying_cpu); | ||
| 3758 | if (r) | 3742 | if (r) |
| 3759 | goto out_free_2; | 3743 | goto out_free_2; |
| 3760 | register_reboot_notifier(&kvm_reboot_notifier); | 3744 | register_reboot_notifier(&kvm_reboot_notifier); |
| @@ -3808,7 +3792,7 @@ out_free: | |||
| 3808 | kmem_cache_destroy(kvm_vcpu_cache); | 3792 | kmem_cache_destroy(kvm_vcpu_cache); |
| 3809 | out_free_3: | 3793 | out_free_3: |
| 3810 | unregister_reboot_notifier(&kvm_reboot_notifier); | 3794 | unregister_reboot_notifier(&kvm_reboot_notifier); |
| 3811 | unregister_cpu_notifier(&kvm_cpu_notifier); | 3795 | cpuhp_remove_state_nocalls(CPUHP_AP_KVM_STARTING); |
| 3812 | out_free_2: | 3796 | out_free_2: |
| 3813 | out_free_1: | 3797 | out_free_1: |
| 3814 | kvm_arch_hardware_unsetup(); | 3798 | kvm_arch_hardware_unsetup(); |
| @@ -3831,7 +3815,7 @@ void kvm_exit(void) | |||
| 3831 | kvm_async_pf_deinit(); | 3815 | kvm_async_pf_deinit(); |
| 3832 | unregister_syscore_ops(&kvm_syscore_ops); | 3816 | unregister_syscore_ops(&kvm_syscore_ops); |
| 3833 | unregister_reboot_notifier(&kvm_reboot_notifier); | 3817 | unregister_reboot_notifier(&kvm_reboot_notifier); |
| 3834 | unregister_cpu_notifier(&kvm_cpu_notifier); | 3818 | cpuhp_remove_state_nocalls(CPUHP_AP_KVM_STARTING); |
| 3835 | on_each_cpu(hardware_disable_nolock, NULL, 1); | 3819 | on_each_cpu(hardware_disable_nolock, NULL, 1); |
| 3836 | kvm_arch_hardware_unsetup(); | 3820 | kvm_arch_hardware_unsetup(); |
| 3837 | kvm_arch_exit(); | 3821 | kvm_arch_exit(); |
