Juergen Keil
2007-Mar-12 12:23 UTC
[qemu-discuss] [PATCH] target-i386: DR6 single step exception status bit
- qemu CVS, without using the kqemu module - Solaris x86 guest - I''m trying to debug a user program inside the Solaris x86 guest: $ mdb /bin/date > main:b > :r (note: mdb uses a breakpoint inside the target''s dynamic linker ld.so.1 and single steps over that breakpoint during target program startup) When kqemu isn''t available, single stepping a user programm in the /bin/mdb debugger in a Solaris x86 guest doesn''t work. The Solaris x86 kernel verifies that the "BS (single step) flag (bit 14)" in the DR6 debug status register is set when a user program gets an exception #1 (EXCP01_SSTP). qemu currently doesn''t set this bit for exception #1 (EXCP01_SSTP). The Solaris x86 kernel complains with the message: Unexpected INT 1 in user mode, dr6=0 At this point the Solaris x86 guest kernel is stuck in an endless loop with "Unexpected INT 1 in user mode, dr6=0" messages. Workaround: ========== For the x86 platform only: use the kqemu module. Suggested fix: ============= Set the 0x4000 bit in DR6 when single stepping. See the attached patch. With this patch applied, debugging a user program works. -------------- next part -------------- diff -ru /tmp/qemu-cvs/target-i386/exec.h qemu-cvs/target-i386/exec.h --- /tmp/qemu-cvs/target-i386/exec.h 2006-09-25 09:52:23.000000000 +0200 +++ qemu-cvs/target-i386/exec.h 2007-03-10 21:20:22.804313251 +0100 @@ -191,6 +191,7 @@ void helper_idivq_EAX_T0(void); void helper_bswapq_T0(void); void helper_cmpxchg8b(void); +void helper_single_step(void); void helper_cpuid(void); void helper_enter_level(int level, int data32); void helper_enter64_level(int level, int data64); diff -ru /tmp/qemu-cvs/target-i386/helper.c qemu-cvs/target-i386/helper.c --- /tmp/qemu-cvs/target-i386/helper.c 2007-02-09 22:10:08.000000000 +0100 +++ qemu-cvs/target-i386/helper.c 2007-03-10 21:13:09.708272230 +0100 @@ -1591,6 +1591,12 @@ CC_SRC = eflags; } +void helper_single_step() +{ + env->dr[6] |= 0x4000; + raise_exception(EXCP01_SSTP); +} + void helper_cpuid(void) { uint32_t index; diff -ru /tmp/qemu-cvs/target-i386/op.c qemu-cvs/target-i386/op.c --- /tmp/qemu-cvs/target-i386/op.c 2007-02-09 22:10:08.000000000 +0100 +++ qemu-cvs/target-i386/op.c 2007-03-10 21:20:53.276293877 +0100 @@ -730,6 +730,11 @@ helper_cmpxchg8b(); } +void OPPROTO op_single_step(void) +{ + helper_single_step(); +} + void OPPROTO op_movl_T0_0(void) { T0 = 0; diff -ru /tmp/qemu-cvs/target-i386/translate.c qemu-cvs/target-i386/translate.c --- /tmp/qemu-cvs/target-i386/translate.c 2007-01-24 10:07:52.000000000 +0100 +++ qemu-cvs/target-i386/translate.c 2007-03-10 21:49:06.287293924 +0100 @@ -2277,7 +2277,7 @@ if (s->singlestep_enabled) { gen_op_debug(); } else if (s->tf) { - gen_op_raise_exception(EXCP01_SSTP); + gen_op_single_step(); } else { gen_op_movl_T0_0(); gen_op_exit_tb();