qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH 0/1] possible fix for hw breakpoint crash on x86 32bit host
@ 2010-01-26 22:29 Jason Wessel
  2010-01-26 22:29 ` [Qemu-devel] [PATCH 1/1] target-i386: fix crash on x86 32bit linux host with hw breakpoint exceptions Jason Wessel
  0 siblings, 1 reply; 3+ messages in thread
From: Jason Wessel @ 2010-01-26 22:29 UTC (permalink / raw)
  To: qemu-devel

The aim of this patch is to either fix the problem or at least
describe the circumstances around the crash using a 32 bit x86 linux
host with a 32 bit linux guest making use of hw breakpoints.

I had also seen the same problem reported here:

https://bugs.launchpad.net/qemu/+bug/501177


---- running qemu in gdb with a linux kernel as the guest ----
kgdbts:RUN hw breakpoint test
[New Thread 0xb7f1d700 (LWP 31553)]

Program received signal SIGSEGV, Segmentation fault.
raise_interrupt (intno=1, is_int=0, error_code=0, next_eip_addend=0)
    at /ord-lpggp11/jwessel/git/qemu/target-i386/op_helper.c:1335
1335        env->exception_index = intno;
(gdb) info address env
Symbol "env" is a variable in register ebp.
(gdb) bt
#0  raise_interrupt (intno=1, is_int=0, error_code=0, next_eip_addend=0)
    at /ord-lpggp11/jwessel/git/qemu/target-i386/op_helper.c:1335
#1  0x081380b7 in raise_exception (exception_index=1)
    at /ord-lpggp11/jwessel/git/qemu/target-i386/op_helper.c:1351
#2  0x0814db6e in breakpoint_handler (env=0x9ed8b50)
    at /ord-lpggp11/jwessel/git/qemu/target-i386/helper.c:1551
#3  0x080e1643 in cpu_x86_exec (env1=0x9ed8b50)
    at /ord-lpggp11/jwessel/git/qemu/cpu-exec.c:206
#4  0x08053af9 in main (argc=0, argv=0x0, envp=Cannot access memory at address 0x8
)
    at /ord-lpggp11/jwessel/git/qemu/vl.c:3816
(gdb) 

I concluded that env points to the ebp register and it only has a
valid value while executing from the generated code context.  I
created another function to pass in the valid version of env in order
to set ebp in preparation to eventually execute a longjmp() via the
raise_exception().

It is not clear that this is the right way to fix the problem, but it
does allow the guest hw breakpoint tests to work correctly on a 32 bit
and 64 bit x86 linux host.

If there is a better way to solve this, please let me know.

Thanks,
Jason.

---
Jason Wessel (1):
      target-i386: fix crash on x86 32bit linux host with hw breakpoint exceptions

 target-i386/exec.h      |    1 +
 target-i386/helper.c    |    6 +++---
 target-i386/op_helper.c |    5 +++++
 3 files changed, 9 insertions(+), 3 deletions(-)

^ permalink raw reply	[flat|nested] 3+ messages in thread

* [Qemu-devel] [PATCH 1/1] target-i386: fix crash on x86 32bit linux host with hw breakpoint exceptions
  2010-01-26 22:29 [Qemu-devel] [PATCH 0/1] possible fix for hw breakpoint crash on x86 32bit host Jason Wessel
@ 2010-01-26 22:29 ` Jason Wessel
  2010-02-28 18:23   ` Aurelien Jarno
  0 siblings, 1 reply; 3+ messages in thread
From: Jason Wessel @ 2010-01-26 22:29 UTC (permalink / raw)
  To: qemu-devel

If you make use of hw breakpoints on a 32bit x86 linux host, qemu
will segmentation fault when processing the exception.

The problem is that the value of env is stored in $ebp in the op_helper
raise_exception() function, and it can have the wrong value when
calling it from non generated code.

It is possible to work around the problem by restoring the value of
env before calling raise_exception() using a new helper function that
takes (CPUState *) as one of the arguments.

Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
---
 target-i386/exec.h      |    1 +
 target-i386/helper.c    |    6 +++---
 target-i386/op_helper.c |    5 +++++
 3 files changed, 9 insertions(+), 3 deletions(-)

diff --git a/target-i386/exec.h b/target-i386/exec.h
index 1fd74fd..4ff3c57 100644
--- a/target-i386/exec.h
+++ b/target-i386/exec.h
@@ -73,6 +73,7 @@ void do_interrupt_user(int intno, int is_int, int error_code,
                        target_ulong next_eip);
 void QEMU_NORETURN raise_exception_err(int exception_index, int error_code);
 void QEMU_NORETURN raise_exception(int exception_index);
+void QEMU_NORETURN raise_exception_env(int exception_index, CPUState *nenv);
 void do_smm_enter(void);
 
 /* n must be a constant to be efficient */
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 70762bb..736ef16 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1529,7 +1529,7 @@ int check_hw_breakpoints(CPUState *env, int force_dr6_update)
 
 static CPUDebugExcpHandler *prev_debug_excp_handler;
 
-void raise_exception(int exception_index);
+void raise_exception_env(int exception_index, CPUState *env);
 
 static void breakpoint_handler(CPUState *env)
 {
@@ -1539,7 +1539,7 @@ static void breakpoint_handler(CPUState *env)
         if (env->watchpoint_hit->flags & BP_CPU) {
             env->watchpoint_hit = NULL;
             if (check_hw_breakpoints(env, 0))
-                raise_exception(EXCP01_DB);
+                raise_exception_env(EXCP01_DB, env);
             else
                 cpu_resume_from_signal(env, NULL);
         }
@@ -1548,7 +1548,7 @@ static void breakpoint_handler(CPUState *env)
             if (bp->pc == env->eip) {
                 if (bp->flags & BP_CPU) {
                     check_hw_breakpoints(env, 1);
-                    raise_exception(EXCP01_DB);
+                    raise_exception_env(EXCP01_DB, env);
                 }
                 break;
             }
diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
index 5eea322..4bb4347 100644
--- a/target-i386/op_helper.c
+++ b/target-i386/op_helper.c
@@ -1351,6 +1351,11 @@ void raise_exception(int exception_index)
     raise_interrupt(exception_index, 0, 0, 0);
 }
 
+void raise_exception_env(int exception_index, CPUState *nenv)
+{
+    env = nenv;
+    raise_exception(exception_index);
+}
 /* SMM support */
 
 #if defined(CONFIG_USER_ONLY)
-- 
1.6.3.3

^ permalink raw reply related	[flat|nested] 3+ messages in thread

* Re: [Qemu-devel] [PATCH 1/1] target-i386: fix crash on x86 32bit linux host with hw breakpoint exceptions
  2010-01-26 22:29 ` [Qemu-devel] [PATCH 1/1] target-i386: fix crash on x86 32bit linux host with hw breakpoint exceptions Jason Wessel
@ 2010-02-28 18:23   ` Aurelien Jarno
  0 siblings, 0 replies; 3+ messages in thread
From: Aurelien Jarno @ 2010-02-28 18:23 UTC (permalink / raw)
  To: Jason Wessel; +Cc: qemu-devel

On Tue, Jan 26, 2010 at 04:29:50PM -0600, Jason Wessel wrote:
> If you make use of hw breakpoints on a 32bit x86 linux host, qemu
> will segmentation fault when processing the exception.
> 
> The problem is that the value of env is stored in $ebp in the op_helper
> raise_exception() function, and it can have the wrong value when
> calling it from non generated code.
> 
> It is possible to work around the problem by restoring the value of
> env before calling raise_exception() using a new helper function that
> takes (CPUState *) as one of the arguments.

Thanks, applied.

> Signed-off-by: Jason Wessel <jason.wessel@windriver.com>
> ---
>  target-i386/exec.h      |    1 +
>  target-i386/helper.c    |    6 +++---
>  target-i386/op_helper.c |    5 +++++
>  3 files changed, 9 insertions(+), 3 deletions(-)
> 
> diff --git a/target-i386/exec.h b/target-i386/exec.h
> index 1fd74fd..4ff3c57 100644
> --- a/target-i386/exec.h
> +++ b/target-i386/exec.h
> @@ -73,6 +73,7 @@ void do_interrupt_user(int intno, int is_int, int error_code,
>                         target_ulong next_eip);
>  void QEMU_NORETURN raise_exception_err(int exception_index, int error_code);
>  void QEMU_NORETURN raise_exception(int exception_index);
> +void QEMU_NORETURN raise_exception_env(int exception_index, CPUState *nenv);
>  void do_smm_enter(void);
>  
>  /* n must be a constant to be efficient */
> diff --git a/target-i386/helper.c b/target-i386/helper.c
> index 70762bb..736ef16 100644
> --- a/target-i386/helper.c
> +++ b/target-i386/helper.c
> @@ -1529,7 +1529,7 @@ int check_hw_breakpoints(CPUState *env, int force_dr6_update)
>  
>  static CPUDebugExcpHandler *prev_debug_excp_handler;
>  
> -void raise_exception(int exception_index);
> +void raise_exception_env(int exception_index, CPUState *env);
>  
>  static void breakpoint_handler(CPUState *env)
>  {
> @@ -1539,7 +1539,7 @@ static void breakpoint_handler(CPUState *env)
>          if (env->watchpoint_hit->flags & BP_CPU) {
>              env->watchpoint_hit = NULL;
>              if (check_hw_breakpoints(env, 0))
> -                raise_exception(EXCP01_DB);
> +                raise_exception_env(EXCP01_DB, env);
>              else
>                  cpu_resume_from_signal(env, NULL);
>          }
> @@ -1548,7 +1548,7 @@ static void breakpoint_handler(CPUState *env)
>              if (bp->pc == env->eip) {
>                  if (bp->flags & BP_CPU) {
>                      check_hw_breakpoints(env, 1);
> -                    raise_exception(EXCP01_DB);
> +                    raise_exception_env(EXCP01_DB, env);
>                  }
>                  break;
>              }
> diff --git a/target-i386/op_helper.c b/target-i386/op_helper.c
> index 5eea322..4bb4347 100644
> --- a/target-i386/op_helper.c
> +++ b/target-i386/op_helper.c
> @@ -1351,6 +1351,11 @@ void raise_exception(int exception_index)
>      raise_interrupt(exception_index, 0, 0, 0);
>  }
>  
> +void raise_exception_env(int exception_index, CPUState *nenv)
> +{
> +    env = nenv;
> +    raise_exception(exception_index);
> +}
>  /* SMM support */
>  
>  #if defined(CONFIG_USER_ONLY)
> -- 
> 1.6.3.3
> 
> 
> 
> 

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2010-02-28 18:23 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2010-01-26 22:29 [Qemu-devel] [PATCH 0/1] possible fix for hw breakpoint crash on x86 32bit host Jason Wessel
2010-01-26 22:29 ` [Qemu-devel] [PATCH 1/1] target-i386: fix crash on x86 32bit linux host with hw breakpoint exceptions Jason Wessel
2010-02-28 18:23   ` Aurelien Jarno

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).