Skip to contentSkip to conversation

x86: Issue reset on triple faults

PATCH In review Jan Kiszka 5 participants 7 messages Jun 23, 2008 – Jun 24, 2008

lore
Share & tools
lore

Jan Kiszka

author
#0 lore raw

PATCH 2/2 x86: Issue reset on triple faults

As discussed a few times on this list: A triple fault causes a system reset on x86, and some guests make use of this. To keep the chance of tracing unexpected resets, log them if CPU_LOG_RESET is set.

---
 target-i386/op_helper.c |   17 +++++++++++++++--
 1 file changed, 15 insertions(+), 2 deletions(-)
target-i386/op_helper.c +15 -2
Index: b/target-i386/op_helper.c
===================================================================
@@ -1230,6 +1230,9 @@ void do_interrupt(int intno, int is_int,
     }
 }
 
+/* This should come from sysemu.h - if we could include it here... */
+void qemu_system_reset_request(void);
+
 /*
  * Check nested exceptions and change to double or triple fault if
  * needed. It should only be called, if this is not an interrupt.
@@ -1247,8 +1250,18 @@ static int check_exception(int intno, in
         fprintf(logfile, "check_exception old: 0x%x new 0x%x\n",
                 env->old_exception, intno);
 
-    if (env->old_exception == EXCP08_DBLE)
-        cpu_abort(env, "triple fault");
+#if !defined(CONFIG_USER_ONLY)
+    if (env->old_exception == EXCP08_DBLE) {
+        if (env->hflags & HF_SVMI_MASK)
+            helper_vmexit(SVM_EXIT_SHUTDOWN, 0);
+
+        if (loglevel & CPU_LOG_RESET)
+            fprintf(logfile, "Triple fault\n");
+
+        qemu_system_reset_request();
+        return EXCP_HLT;
+    }
+#endif
 
     if ((first_contributory && second_contributory)
         || (env->old_exception == EXCP0E_PAGE &&
#1 lore raw
Quoted 3 lines · Jan Kiszka

As discussed a few times on this list: A triple fault causes a system reset on x86, and some guests make use of this. To keep the chance of tracing unexpected resets, log them if CPU_LOG_RESET is set.

It might be worth distinguishing between triple-fault-used-by-guest-for-context-switch and triple faults which trigger a normal reset, and log only the latter. There's a standardish way of distinguishing them, which the BIOS should check.

target-i386/op_helper.c static int check_exception(int intno, in · line 1264

Quoted 12 lines
target-i386/op_helper.c +12 -0
+#if !defined(CONFIG_USER_ONLY)
+    if (env->old_exception == EXCP08_DBLE) {
+        if (env->hflags & HF_SVMI_MASK)
+            helper_vmexit(SVM_EXIT_SHUTDOWN, 0);
+
+        if (loglevel & CPU_LOG_RESET)
+            fprintf(logfile, "Triple fault\n");
+
+        qemu_system_reset_request();
+        return EXCP_HLT;
+    }
+#endif

When helper(SVM_EXIT_SHUTDOWN, 0) is called, should it still also call qemu_system_reset_request()?

-- Jamie

author
#2 lore raw
Quoted 9 lines · Jamie Lokier
Quoted 3 lines · Jan Kiszka

As discussed a few times on this list: A triple fault causes a system reset on x86, and some guests make use of this. To keep the chance of tracing unexpected resets, log them if CPU_LOG_RESET is set.

It might be worth distinguishing between triple-fault-used-by-guest-for-context-switch and triple faults which trigger a normal reset, and log only the latter. There's a standardish way of distinguishing them, which the BIOS should check.

You refer to setting some return address at some magic BIOS location? Isn't this something the BIOS should handle, not QEMU?

Quoted 16 lines

target-i386/op_helper.c static int check_exception(int intno, in · line 1264

Quoted 13 lines
target-i386/op_helper.c +12 -0
+#if !defined(CONFIG_USER_ONLY)
+    if (env->old_exception == EXCP08_DBLE) {
+        if (env->hflags & HF_SVMI_MASK)
+            helper_vmexit(SVM_EXIT_SHUTDOWN, 0);
+
+        if (loglevel & CPU_LOG_RESET)
+            fprintf(logfile, "Triple fault\n");
+
+        qemu_system_reset_request();
+        return EXCP_HLT;
+    }
+#endif

When helper(SVM_EXIT_SHUTDOWN, 0) is called, should it still also call qemu_system_reset_request()?

helper_vmexit() is not expected to return (cpu_loop_exit).

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT SE 2
Corporate Competence Center Embedded Linux
#3 lore raw
Quoted 6 lines · Jan Kiszka
Quoted 4 lines

It might be worth distinguishing between triple-fault-used-by-guest-for-context-switch and triple faults which trigger a normal reset, and log only the latter. There's a standardish way of distinguishing them, which the BIOS should check.

You refer to setting some return address at some magic BIOS location?

Probably; I forget the details. There might be a CMOS byte, too.

Quoted 1 line

Isn't this something the BIOS should handle, not QEMU?

The BIOS should handle it, yes. But since it is standard behaviour, it might be useful for QEMU to decide whether to _log_ the event as a system reset based on that state.

Same for keyboard controller induced reset - that's also used for context switching, in the same way. (Triple fault is only used because it's faster.)

Same also for deciding whether -no-reboot should close down the QEMU process. Now I think about it, that is the best reason to distinguish them!

Quoted 4 lines
Quoted 2 lines

When helper(SVM_EXIT_SHUTDOWN, 0) is called, should it still also call qemu_system_reset_request()?

helper_vmexit() is not expected to return (cpu_loop_exit).

Ok. It's not clear unless you know the code, which I don't. Just wanted to check :-)

-- Jamie

#4 lore raw

A CMOS byte?

Is there really a way to distinguish between wanted reset-by-triple-fault or a non-wanted-triple-fault?

As far as I know the first guest that used this for context switching (OS/2 1.x) used it as an undocumented but convenient bug/feature of 286 cpu.

Quoted 43 lines · Jamie Lokier
Quoted 7 lines · Jan Kiszka
Quoted 5 lines

It might be worth distinguishing between triple-fault-used-by-guest-for-context-switch and triple faults which trigger a normal reset, and log only the latter. There's a standardish way of distinguishing them, which the BIOS should check.

You refer to setting some return address at some magic BIOS location?

Probably; I forget the details. There might be a CMOS byte, too.

Quoted 2 lines

Isn't this something the BIOS should handle, not QEMU?

The BIOS should handle it, yes. But since it is standard behaviour, it might be useful for QEMU to decide whether to _log_ the event as a system reset based on that state.

Same for keyboard controller induced reset - that's also used for context switching, in the same way. (Triple fault is only used because it's faster.)

Same also for deciding whether -no-reboot should close down the QEMU process. Now I think about it, that is the best reason to distinguish them!

Quoted 5 lines
Quoted 3 lines

When helper(SVM_EXIT_SHUTDOWN, 0) is called, should it still also call qemu_system_reset_request()?

helper_vmexit() is not expected to return (cpu_loop_exit).

Ok. It's not clear unless you know the code, which I don't. Just wanted to check :-)

-- Jamie

#5 lore raw
In reply to Jamie Lokier
Quoted 8 lines · Jamie Lokier
Quoted 5 lines · Jan Kiszka
Quoted 4 lines

It might be worth distinguishing between triple-fault-used-by-guest-for-context-switch and triple faults which trigger a normal reset, and log only the latter. There's a standardish way of distinguishing them, which the BIOS should check.

You refer to setting some return address at some magic BIOS location?

Probably; I forget the details. There might be a CMOS byte, too.

I checked some old documents: It's a combination of both. Some CMOS byte (0x0f) signals the special reset, and a pointer in the BIOS memory (0x40:0x67) describes the desired jump target.

Quoted 6 lines
Quoted 2 lines

Isn't this something the BIOS should handle, not QEMU?

The BIOS should handle it, yes. But since it is standard behaviour, it might be useful for QEMU to decide whether to _log_ the event as a system reset based on that state.

Yeah, meanwhile my brain seems to work again and actually read what you mean.

But I'm still not convinced that we should make a special case about this in the QEMU core. The user is not forced to enable reset logging, and maybe (s)he _does_ want to log also resets due to protected mode exits - what then? Keep it simple, just log what actually happens if logging is enabled.

Quoted 9 lines

Same for keyboard controller induced reset - that's also used for context switching, in the same way. (Triple fault is only used because it's faster.)

Same also for deciding whether -no-reboot should close down the QEMU process. Now I think about it, that is the best reason to distinguish them!

Quoted 6 lines
Quoted 3 lines
Quoted 2 lines

When helper(SVM_EXIT_SHUTDOWN, 0) is called, should it still also call qemu_system_reset_request()?

helper_vmexit() is not expected to return (cpu_loop_exit).

Ok. It's not clear unless you know the code, which I don't. Just wanted to check :-)

Understanding the usage of setjmp/longjmp in QEMU is a key to grasp the control flow - but it took me some time as well to realize this. :)

Jan

#6 lore raw
In reply to Jan Kiszka
Quoted 5 lines · Jan Kiszka
Quoted 4 lines · Jamie Lokier

It might be worth distinguishing between triple-fault-used-by-guest-for-context-switch and triple faults which trigger a normal reset, and log only the latter. There's a standardish way of distinguishing them, which the BIOS should check.

Well, that's certainly possible somehow. But then you need to rename the cpu_reset option to cpu_resets_suspected_to_be_errors. Let's keep it simple and just log all of them.

Quoted 15 lines
Quoted 6 lines
Quoted 6 lines
target-i386/op_helper.c +6 -0
+#if !defined(CONFIG_USER_ONLY)
+    if (env->old_exception == EXCP08_DBLE) {
+        if (env->hflags & HF_SVMI_MASK)
+            helper_vmexit(SVM_EXIT_SHUTDOWN, 0);
+
+        if (loglevel & CPU_LOG_RESET)
Quoted 8 lines

target-i386/op_helper.c static int check_exception(int intno, in · line 1264

Quoted 6 lines
target-i386/op_helper.c +6 -0
+            fprintf(logfile, "Triple fault\n");
+
+        qemu_system_reset_request();
+        return EXCP_HLT;
+    }
+#endif

When helper(SVM_EXIT_SHUTDOWN, 0) is called, should it still also call qemu_system_reset_request()?

Quoted 1 line

helper_vmexit() is not expected to return (cpu_loop_exit).

Maybe a comment then?

Kevin