Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: arm/arm64: implement kvm_arm_[halt,resume]_guest

We introduce kvm_arm_halt_guest and resume functions. They
will be used for IRQ forward state change.

Halt is synchronous and prevents the guest from being re-entered.
We use the same mechanism put in place for PSCI former pause,
now renamed power_off. A new flag is introduced in arch vcpu state,
pause, only meant to be used by those functions.

Signed-off-by: Eric Auger <eric.auger@linaro.org>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>

authored by

Eric Auger and committed by
Christoffer Dall
3b92830a 101d3da0

+37 -4
+3
arch/arm/include/asm/kvm_host.h
··· 129 129 /* vcpu power-off state */ 130 130 bool power_off; 131 131 132 + /* Don't run the guest (internal implementation need) */ 133 + bool pause; 134 + 132 135 /* IO related fields */ 133 136 struct kvm_decode mmio_decode; 134 137
+31 -4
arch/arm/kvm/arm.c
··· 353 353 int kvm_arch_vcpu_runnable(struct kvm_vcpu *v) 354 354 { 355 355 return ((!!v->arch.irq_lines || kvm_vgic_vcpu_pending_irq(v)) 356 - && !v->arch.power_off); 356 + && !v->arch.power_off && !v->arch.pause); 357 357 } 358 358 359 359 /* Just ensure a guest exit from a particular CPU */ ··· 479 479 return vgic_initialized(kvm); 480 480 } 481 481 482 + static void kvm_arm_halt_guest(struct kvm *kvm) __maybe_unused; 483 + static void kvm_arm_resume_guest(struct kvm *kvm) __maybe_unused; 484 + 485 + static void kvm_arm_halt_guest(struct kvm *kvm) 486 + { 487 + int i; 488 + struct kvm_vcpu *vcpu; 489 + 490 + kvm_for_each_vcpu(i, vcpu, kvm) 491 + vcpu->arch.pause = true; 492 + force_vm_exit(cpu_all_mask); 493 + } 494 + 495 + static void kvm_arm_resume_guest(struct kvm *kvm) 496 + { 497 + int i; 498 + struct kvm_vcpu *vcpu; 499 + 500 + kvm_for_each_vcpu(i, vcpu, kvm) { 501 + wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu); 502 + 503 + vcpu->arch.pause = false; 504 + wake_up_interruptible(wq); 505 + } 506 + } 507 + 482 508 static void vcpu_sleep(struct kvm_vcpu *vcpu) 483 509 { 484 510 wait_queue_head_t *wq = kvm_arch_vcpu_wq(vcpu); 485 511 486 - wait_event_interruptible(*wq, !vcpu->arch.power_off); 512 + wait_event_interruptible(*wq, ((!vcpu->arch.power_off) && 513 + (!vcpu->arch.pause))); 487 514 } 488 515 489 516 static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu) ··· 560 533 561 534 update_vttbr(vcpu->kvm); 562 535 563 - if (vcpu->arch.power_off) 536 + if (vcpu->arch.power_off || vcpu->arch.pause) 564 537 vcpu_sleep(vcpu); 565 538 566 539 /* ··· 588 561 } 589 562 590 563 if (ret <= 0 || need_new_vmid_gen(vcpu->kvm) || 591 - vcpu->arch.power_off) { 564 + vcpu->arch.power_off || vcpu->arch.pause) { 592 565 local_irq_enable(); 593 566 kvm_timer_sync_hwstate(vcpu); 594 567 kvm_vgic_sync_hwstate(vcpu);
+3
arch/arm64/include/asm/kvm_host.h
··· 152 152 /* vcpu power-off state */ 153 153 bool power_off; 154 154 155 + /* Don't run the guest (internal implementation need) */ 156 + bool pause; 157 + 155 158 /* IO related fields */ 156 159 struct kvm_decode mmio_decode; 157 160