diff options
Diffstat (limited to 'arch/arm/kvm/arm.c')
-rw-r--r-- | arch/arm/kvm/arm.c | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c index 1141d21b7e3c..f1bf41890fca 100644 --- a/arch/arm/kvm/arm.c +++ b/arch/arm/kvm/arm.c @@ -523,10 +523,20 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) if (vcpu->arch.pause) vcpu_pause(vcpu); + /* + * Disarming the background timer must be done in a + * preemptible context, as this call may sleep. + */ kvm_timer_flush_hwstate(vcpu); - kvm_vgic_flush_hwstate(vcpu); + /* + * Preparing the interrupts to be injected also + * involves poking the GIC, which must be done in a + * non-preemptible context. + */ preempt_disable(); + kvm_vgic_flush_hwstate(vcpu); + local_irq_disable(); /* @@ -539,8 +549,8 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) if (ret <= 0 || need_new_vmid_gen(vcpu->kvm)) { local_irq_enable(); - preempt_enable(); kvm_vgic_sync_hwstate(vcpu); + preempt_enable(); kvm_timer_sync_hwstate(vcpu); continue; } @@ -585,9 +595,11 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *run) */ kvm_guest_exit(); trace_kvm_exit(kvm_vcpu_trap_get_class(vcpu), *vcpu_pc(vcpu)); - preempt_enable(); kvm_vgic_sync_hwstate(vcpu); + + preempt_enable(); + kvm_timer_sync_hwstate(vcpu); ret = handle_exit(vcpu, run, ret); |