Skip to contentSkip to conversation

fix qemu-kvm sigsegv at exit

PATCH In review Marcelo Tosatti 3 participants 7 messages Oct 26, 2009 – Nov 1, 2009 KVM

lore
Share & tools
lore
#0 lore raw

Michael reported a qemu-kvm SIGSEGV at shutdown:

Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x411d0940 (LWP 14446)] 0x000000000040afb4 in qemu_mod_timer (ts=0x19f0fd0, expire_time=62275467335)

    at /home/mst/scm/qemu-kvm/vl.c:1009

1009 if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0)
{
(gdb) l
1004 ts->next = *pt;
1005 *pt = ts;
1006
1007 /* Rearm if necessary */
1008 if (pt == &active_timers[ts->clock->type]) {
1009 if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0)
{
1010 qemu_rearm_alarm_timer(alarm_timer);

1011            }
1012            /* Interrupt execution to force deadline
recalculation.  */
1013            if (use_icount)

(gdb) p alarm_timer
$1 = (struct qemu_alarm_timer *) 0x0

Problem is kvm_main_loop_wait(env, 0) can process the stop request (signalling iothread that vcpu is stopped, so its OK to exit) and continue to kvm_cpu_exec.

Make sure cpu is not stopped before proceeding to kvm_cpu_exec.

qemu-kvm.c +2 -1
index 4c13628..ab8f0e4 100644
@@ -1868,7 +1868,8 @@ static int kvm_main_loop_cpu(CPUState *env)
         }
         if (run_cpu) {
             kvm_main_loop_wait(env, 0);
-            kvm_cpu_exec(env);
+            if (!is_cpu_stopped(env))
+                kvm_cpu_exec(env);
         } else {
             kvm_main_loop_wait(env, 1000);
         }
#1 lore raw
Quoted 40 lines · Marcelo Tosatti

Michael reported a qemu-kvm SIGSEGV at shutdown:

Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x411d0940 (LWP 14446)] 0x000000000040afb4 in qemu_mod_timer (ts=0x19f0fd0, expire_time=62275467335)

    at /home/mst/scm/qemu-kvm/vl.c:1009

1009 if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0)
{
(gdb) l
1004 ts->next = *pt;
1005 *pt = ts;
1006
1007 /* Rearm if necessary */
1008 if (pt == &active_timers[ts->clock->type]) {
1009 if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0)
{
1010 qemu_rearm_alarm_timer(alarm_timer);

1011            }
1012            /* Interrupt execution to force deadline
recalculation.  */
1013            if (use_icount)

(gdb) p alarm_timer
$1 = (struct qemu_alarm_timer *) 0x0

Problem is kvm_main_loop_wait(env, 0) can process the stop request (signalling iothread that vcpu is stopped, so its OK to exit) and continue to kvm_cpu_exec.

Make sure cpu is not stopped before proceeding to kvm_cpu_exec.

qemu-kvm.c +0 -0
index 4c13628..ab8f0e4 100644

qemu-kvm.c static int kvm_main_loop_cpu(CPUState *env) · line 1872

Quoted 6 lines
qemu-kvm.c +2 -1
@@ -1868,7 +1868,8 @@ static int kvm_main_loop_cpu(CPUState *env)
         }
         if (run_cpu) {
             kvm_main_loop_wait(env, 0);
-            kvm_cpu_exec(env);
+            if (!is_cpu_stopped(env))
+                kvm_cpu_exec(env);

I wonder if calling kvm_cpu_exec() after kvm_main_loop_wait() will fix the problem?

Quoted 7 lines
qemu-kvm.c +0 -1
         } else {
             kvm_main_loop_wait(env, 1000);
         }
--

To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

--
Gleb.

#2 lore raw
Quoted 36 lines · Gleb Natapov
Quoted 35 lines · Marcelo Tosatti

Michael reported a qemu-kvm SIGSEGV at shutdown:

Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x411d0940 (LWP 14446)] 0x000000000040afb4 in qemu_mod_timer (ts=0x19f0fd0, expire_time=62275467335)

    at /home/mst/scm/qemu-kvm/vl.c:1009

1009 if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0)
{
(gdb) l
1004 ts->next = *pt;
1005 *pt = ts;
1006
1007 /* Rearm if necessary */
1008 if (pt == &active_timers[ts->clock->type]) {
1009 if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0)
{
1010 qemu_rearm_alarm_timer(alarm_timer);

1011            }
1012            /* Interrupt execution to force deadline
recalculation.  */
1013            if (use_icount)

(gdb) p alarm_timer
$1 = (struct qemu_alarm_timer *) 0x0

Problem is kvm_main_loop_wait(env, 0) can process the stop request (signalling iothread that vcpu is stopped, so its OK to exit) and continue to kvm_cpu_exec.

Make sure cpu is not stopped before proceeding to kvm_cpu_exec.

Quoted 13 lines

qemu-kvm.c static int kvm_main_loop_cpu(CPUState *env) · line 1872

Quoted 11 lines
qemu-kvm.c +2 -1
index 4c13628..ab8f0e4 100644
@@ -1868,7 +1868,8 @@ static int kvm_main_loop_cpu(CPUState *env)
         }
         if (run_cpu) {
             kvm_main_loop_wait(env, 0);
-            kvm_cpu_exec(env);
+            if (!is_cpu_stopped(env))
+                kvm_cpu_exec(env);

I wonder if calling kvm_cpu_exec() after kvm_main_loop_wait() will fix the problem?

Yeah, that would also do it.

#3 lore raw

PATCH v2 1/1 fix qemu-kvm sigsegv at exit

In reply to Gleb Natapov

Michael reported a qemu-kvm SIGSEGV at shutdown:

Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x411d0940 (LWP 14446)] 0x000000000040afb4 in qemu_mod_timer (ts=0x19f0fd0, expire_time=62275467335)

    at /home/mst/scm/qemu-kvm/vl.c:1009

1009 if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0)
{
(gdb) l
1004 ts->next = *pt;
1005 *pt = ts;
1006
1007 /* Rearm if necessary */
1008 if (pt == &active_timers[ts->clock->type]) {
1009 if ((alarm_timer->flags & ALARM_FLAG_EXPIRED) == 0)
{
1010 qemu_rearm_alarm_timer(alarm_timer);

1011            }
1012            /* Interrupt execution to force deadline
recalculation.  */
1013            if (use_icount)

(gdb) p alarm_timer
$1 = (struct qemu_alarm_timer *) 0x0

Problem is kvm_main_loop_wait(env, 0) can process the stop request (signalling iothread that vcpu is stopped, so its OK to exit) and continue to kvm_cpu_exec.

Reorder kvm_main_loop_wait and kvm_cpu_exec, as suggested by Gleb.

qemu-kvm.c +1 -1
index 4c13628..809fd65 100644
@@ -1867,8 +1867,8 @@ static int kvm_main_loop_cpu(CPUState *env)
             run_cpu = !env->halted;
         }
         if (run_cpu) {
-            kvm_main_loop_wait(env, 0);
             kvm_cpu_exec(env);
+            kvm_main_loop_wait(env, 0);
         } else {
             kvm_main_loop_wait(env, 1000);
         }
#4 lore raw
Quoted 40 lines · Marcelo Tosatti

Michael reported a qemu-kvm SIGSEGV at shutdown:

Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x411d0940 (LWP 14446)] 0x000000000040afb4 in qemu_mod_timer (ts=0x19f0fd0, expire_time=62275467335)

     at /home/mst/scm/qemu-kvm/vl.c:1009

1009 if ((alarm_timer->flags& ALARM_FLAG_EXPIRED) == 0)
{
(gdb) l
1004 ts->next = *pt;
1005 *pt = ts;
1006
1007 /* Rearm if necessary */
1008 if (pt ==&active_timers[ts->clock->type]) {
1009 if ((alarm_timer->flags& ALARM_FLAG_EXPIRED) == 0)
{
1010 qemu_rearm_alarm_timer(alarm_timer);

1011            }
1012            /* Interrupt execution to force deadline
recalculation.  */
1013            if (use_icount)

(gdb) p alarm_timer
$1 = (struct qemu_alarm_timer *) 0x0

Problem is kvm_main_loop_wait(env, 0) can process the stop request (signalling iothread that vcpu is stopped, so its OK to exit) and continue to kvm_cpu_exec.

Reorder kvm_main_loop_wait and kvm_cpu_exec, as suggested by Gleb.

qemu-kvm.c +0 -0
index 4c13628..809fd65 100644

qemu-kvm.c static int kvm_main_loop_cpu(CPUState *env) · line 1874

Quoted 9 lines
qemu-kvm.c +1 -1
@@ -1867,8 +1867,8 @@ static int kvm_main_loop_cpu(CPUState *env)
              run_cpu = !env->halted;
          }
          if (run_cpu) {
-            kvm_main_loop_wait(env, 0);
              kvm_cpu_exec(env);
+            kvm_main_loop_wait(env, 0);
          } else {
              kvm_main_loop_wait(env, 1000);
          }

This will miss an event at the very beginning of the loop (powerdown requested before we had a chance to spin up?). I think it should be fine since there will be a pending signal which will break us out of kvm_cpu_exec() before it has a chance to do anything (i.e. spin in the guest).

So, I think it's fine, but please double check the above.

Signature · 1 line
error compiling committee.c: too many arguments to function
#5 lore raw
Quoted 57 lines · Avi Kivity
Quoted 40 lines · Marcelo Tosatti

Michael reported a qemu-kvm SIGSEGV at shutdown:

Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 0x411d0940 (LWP 14446)] 0x000000000040afb4 in qemu_mod_timer (ts=0x19f0fd0, expire_time=62275467335)

     at /home/mst/scm/qemu-kvm/vl.c:1009

1009 if ((alarm_timer->flags& ALARM_FLAG_EXPIRED) == 0)
{
(gdb) l
1004 ts->next = *pt;
1005 *pt = ts;
1006
1007 /* Rearm if necessary */
1008 if (pt ==&active_timers[ts->clock->type]) {
1009 if ((alarm_timer->flags& ALARM_FLAG_EXPIRED) == 0)
{
1010 qemu_rearm_alarm_timer(alarm_timer);

1011            }
1012            /* Interrupt execution to force deadline
recalculation.  */
1013            if (use_icount)

(gdb) p alarm_timer
$1 = (struct qemu_alarm_timer *) 0x0

Problem is kvm_main_loop_wait(env, 0) can process the stop request (signalling iothread that vcpu is stopped, so its OK to exit) and continue to kvm_cpu_exec.

Reorder kvm_main_loop_wait and kvm_cpu_exec, as suggested by Gleb.

qemu-kvm.c +0 -0
index 4c13628..809fd65 100644

qemu-kvm.c static int kvm_main_loop_cpu(CPUState *env) · line 1874

Quoted 9 lines
qemu-kvm.c +1 -1
@@ -1867,8 +1867,8 @@ static int kvm_main_loop_cpu(CPUState *env)
              run_cpu = !env->halted;
          }
          if (run_cpu) {
-            kvm_main_loop_wait(env, 0);
              kvm_cpu_exec(env);
+            kvm_main_loop_wait(env, 0);
          } else {
              kvm_main_loop_wait(env, 1000);
          }

This will miss an event at the very beginning of the loop (powerdown requested before we had a chance to spin up?). I think it should be fine since there will be a pending signal which will break us out of kvm_cpu_exec() before it has a chance to do anything (i.e. spin in the guest).

Quoted 1 line

So, I think it's fine, but please double check the above.

That can happen but only with the unpatched version, where kvm_main_loop_wait eats the signal, sets env->stopped = 1, and proceeds to kvm_cpu_exec.
With the patch, this is not the case.

As before, the signal sender will send an IPI with smp_send_reschedule (and vcpu_enter_guest checks sigpending after disabling interrupts).

#6 lore raw
Quoted 9 lines · Marcelo Tosatti
Quoted 9 lines

This will miss an event at the very beginning of the loop (powerdown requested before we had a chance to spin up?). I think it should be fine since there will be a pending signal which will break us out of kvm_cpu_exec() before it has a chance to do anything (i.e. spin in the guest).

So, I think it's fine, but please double check the above.

Quoted 8 lines

That can happen but only with the unpatched version, where kvm_main_loop_wait eats the signal, sets env->stopped = 1, and proceeds to kvm_cpu_exec.
With the patch, this is not the case.

As before, the signal sender will send an IPI with smp_send_reschedule (and vcpu_enter_guest checks sigpending after disabling interrupts).

Fair enough, double bugfix; applied, thanks.

Signature · 1 line
error compiling committee.c: too many arguments to function