Commit fdd26ecb authored by Julien Thierry's avatar Julien Thierry Committed by Will Deacon
Browse files

kvm-cpu: Pause vCPU in signal handler

Currently, the handling a pause signal only sets a state that will be
checked at the begining of the CPU run loop. At the checking point the vCPU
sends the notification that it is actually paused allowing the pause
requester to confirm all vCPUs are paused.

Receiving the pause signal during a KVM_RUN ioctl will make KVM exit to
userspace. However, there is a small window between that check on
cpu->paused and the execution of KVM_RUN where the signal has been received
but the vCPU does not go back through the notification and starts KVM_RUN.
Since there is no guarantee the vCPU will come back to userspace, the
pause requester might deadlock.

Perform the pause directly from the signal handler. This relies on a vCPU
thread never receiving a pause signal while being pause, but such scenario
would have caused a deadlock for the pause requester anyway.
Signed-off-by: default avatarJulien Thierry <>
Signed-off-by: default avatarWill Deacon <>
parent 29f4ec31
...@@ -51,7 +51,19 @@ static void kvm_cpu_signal_handler(int signum) ...@@ -51,7 +51,19 @@ static void kvm_cpu_signal_handler(int signum)
if (current_kvm_cpu && current_kvm_cpu->is_running) if (current_kvm_cpu && current_kvm_cpu->is_running)
current_kvm_cpu->is_running = false; current_kvm_cpu->is_running = false;
} else if (signum == SIGKVMPAUSE) { } else if (signum == SIGKVMPAUSE) {
if (current_kvm_cpu->paused)
die("Pause signaled for already paused CPU\n");
/* pause_lock is held by kvm__pause() */
current_kvm_cpu->paused = 1; current_kvm_cpu->paused = 1;
* This is a blocking function and uses locks. It is safe
* to call it for this signal as a second pause event should
* not be send to this thread until it acquires and releases
* the pause_lock.
} }
/* For SIGKVMTASK cpu->task is already set */ /* For SIGKVMTASK cpu->task is already set */
...@@ -148,9 +160,6 @@ int kvm_cpu__start(struct kvm_cpu *cpu) ...@@ -148,9 +160,6 @@ int kvm_cpu__start(struct kvm_cpu *cpu)
kvm_cpu__enable_singlestep(cpu); kvm_cpu__enable_singlestep(cpu);
while (cpu->is_running) { while (cpu->is_running) {
if (cpu->paused)
if (cpu->needs_nmi) { if (cpu->needs_nmi) {
kvm_cpu__arch_nmi(cpu); kvm_cpu__arch_nmi(cpu);
cpu->needs_nmi = 0; cpu->needs_nmi = 0;
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment