qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] linux-user exception handling
@ 2008-08-25 20:26 Vince Weaver
  2008-08-25 20:34 ` Blue Swirl
  0 siblings, 1 reply; 8+ messages in thread
From: Vince Weaver @ 2008-08-25 20:26 UTC (permalink / raw)
  To: qemu-devel

Hello

so I'm tracking down a problem on sparc32plus-linux-user.
SPARC has register windows, and when it tried to save another register 
context, but all available ones are full, it causes a TT_SPILL exception. 
In theory the OS would handle this and move some of the registers to RAM 
somewhere.

In any case, this doesn't seem to be working properly.  I've traced 
through the code, and I find in cpu-exec.c where userspace exceptions are 
handled.

The code involved in listed below.

Am I correct in reading that user-mode exceptions are only implemented for 
x86?  If so that makes me sad, because it means that pretty much any SPARC 
program that has more than 8 nested function calls won't work until a lot 
more code is implemented.

Vince



                } else if (env->user_mode_only) {
                     /* if user mode only, we simulate a fake exception
                        which will be handled outside the cpu execution
                        loop */
#if defined(TARGET_I386)
                     do_interrupt_user(env->exception_index,
                                       env->exception_is_int,
                                       env->error_code,
                                       env->exception_next_eip);
                     /* successfully delivered */
                     env->old_exception = -1;
#endif
                     ret = env->exception_index;
                     break;

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

* Re: [Qemu-devel] linux-user exception handling
  2008-08-25 20:26 [Qemu-devel] linux-user exception handling Vince Weaver
@ 2008-08-25 20:34 ` Blue Swirl
  2008-08-27 16:58   ` Vince Weaver
  0 siblings, 1 reply; 8+ messages in thread
From: Blue Swirl @ 2008-08-25 20:34 UTC (permalink / raw)
  To: qemu-devel

On 8/25/08, Vince Weaver <vince@csl.cornell.edu> wrote:
> Hello
>
>  so I'm tracking down a problem on sparc32plus-linux-user.
>  SPARC has register windows, and when it tried to save another register
> context, but all available ones are full, it causes a TT_SPILL exception. In
> theory the OS would handle this and move some of the registers to RAM
> somewhere.
>
>  In any case, this doesn't seem to be working properly.  I've traced through
> the code, and I find in cpu-exec.c where userspace exceptions are handled.

No, register window handling and other exceptions are handled in
linux-user/main.c.

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

* Re: [Qemu-devel] linux-user exception handling
  2008-08-25 20:34 ` Blue Swirl
@ 2008-08-27 16:58   ` Vince Weaver
  2008-08-27 17:14     ` Blue Swirl
  0 siblings, 1 reply; 8+ messages in thread
From: Vince Weaver @ 2008-08-27 16:58 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 1386 bytes --]

On Mon, 25 Aug 2008, Blue Swirl wrote:
>
> No, register window handling and other exceptions are handled in
> linux-user/main.c.

You are right.  It can be frustrating tracing through the code trying to 
find out what is being called when.

In any case, I think I've found a bug with register-window handling.
When using sparc32plus, the "wim" value isn't being updated on a 
save_window() call.  Thus when later a "ta 3" (flush register windows) 
call happens, the wrong windows get written out to memory.

I've attached some sample code that shows this problem.

The patch below fixes this for me, but it should be looked over carefully 
because the register window code in qemu is deep magic.

This fix allows the spec2k gcc.scilab and fma3d benchmarks to progress 
further.

Vince

--- linux-user/main.c.orig	2008-08-27 12:48:52.000000000 -0400
+++ linux-user/main.c	2008-08-27 12:49:41.000000000 -0400
@@ -793,14 +793,12 @@

  static void save_window(CPUSPARCState *env)
  {
-#ifndef TARGET_SPARC64
      unsigned int new_wim;
      new_wim = ((env->wim >> 1) | (env->wim << (env->nwindows - 1))) &
          ((1LL << env->nwindows) - 1);
      save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
      env->wim = new_wim;
-#else
-    save_window_offset(env, cpu_cwp_dec(env, env->cwp - 2));
+#if defined(TARGET_SPARC64)
      env->cansave++;
      env->canrestore--;
  #endif

[-- Attachment #2: Type: TEXT/PLAIN, Size: 3581 bytes --]

!     + Syscalls have number in %g1, options in %o0,%o1,...
!	Result returned in %o0
!	Linux syscall is called by "ta 0x10"

.equ SYSCALL_EXIT,1	
.equ SYSCALL_WRITE,4

.equ STDOUT,1

	.globl _start
_start:
	nop
	
label:
	set	0x41410a00,%l0
	set	out_string,%o1
	st	%l0,[%o1]
	call	write_stdout		! AA
	nop
	
	save	%sp,-96,%sp

	set	0x42420a00,%l0
	set	out_string,%o1
	st	%l0,[%o1]
	call	write_stdout		! BB
	nop

	save	%sp,-96,%sp

	set	0x43430a00,%l0
	set	out_string,%o1
	st	%l0,[%o1]
	call	write_stdout		! CC
	nop
	
	save	%sp,-96,%sp

	set	0x44440a00,%l0
	set	out_string,%o1
	st	%l0,[%o1]
	call	write_stdout		! DD
	nop

	save	%sp,-96,%sp

	set	0x45450a00,%l0
	set	out_string,%o1
	st	%l0,[%o1]
	call	write_stdout		! EE
	nop
	
	save	%sp,-96,%sp

	set	0x46460a00,%l0
	set	out_string,%o1
	st	%l0,[%o1]
	call	write_stdout		! FF
	nop
	
	save	%sp,-96,%sp

	set	0x47470a00,%l0
	set	out_string,%o1
	st	%l0,[%o1]
	call	write_stdout		! GG
	nop
	
	save	%sp,-96,%sp

	set	0x48480a00,%l0
	set	out_string,%o1
	st	%l0,[%o1]
	call	write_stdout		! HH
	nop
	
	save	%sp,-96,%sp

	set	0x49490a00,%l0
	set	out_string,%o1
	st	%l0,[%o1]
	call	write_stdout		! II
	nop
	
	save	%sp,-96,%sp

	set	0x4a4a0a00,%l0
	set	out_string,%o1
	st	%l0,[%o1]
	call	write_stdout		! JJ
	nop

	save	%sp,-96,%sp

	set	0x4b4b0a00,%l0
	set	out_string,%o1
	st	%l0,[%o1]
	call	write_stdout		! KK
	nop

	save	%sp,-96,%sp

	set	0x4c4c0a00,%l0
	set	out_string,%o1
	st	%l0,[%o1]
	call	write_stdout		! LL
	nop

	save	%sp,-96,%sp

	set	0x4d4d0a00,%l0
	set	out_string,%o1
	st	%l0,[%o1]
	call	write_stdout		! MM
	nop	
	
!	flushw sparc9 only

	

	restore

	set	out_string,%o1	
	st	%l0,[%o1]
	call	write_stdout		! LL
	nop

	restore

	set	out_string,%o1	
	st	%l0,[%o1]
	call	write_stdout		! KK
	nop

	restore

	set	out_string,%o1	
	st	%l0,[%o1]
	call	write_stdout		! JJ
	nop

	restore

	set	out_string,%o1	
	st	%l0,[%o1]
	call	write_stdout		! II
	nop
	
	ta 3
	
	restore

	set	out_string,%o1		
	st	%l0,[%o1]
	call	write_stdout
	nop	
	
	restore
	
	set	out_string,%o1	
	st	%l0,[%o1]
	call	write_stdout
	nop	

	restore

	set	out_string,%o1		
	st	%l0,[%o1]	
	call	write_stdout
	nop	
	
	restore

	set	out_string,%o1		
	st	%l0,[%o1]
	call	write_stdout
	nop	
	
	restore

	set	out_string,%o1		
	st	%l0,[%o1]
	call	write_stdout
	nop	

	restore

	set	out_string,%o1		
	st	%l0,[%o1]
	call	write_stdout
	nop	

	restore

	set	out_string,%o1		
	st	%l0,[%o1]
	call	write_stdout
	nop	
	
	restore

	set	out_string,%o1		
	st	%l0,[%o1]
	call	write_stdout
	nop		

	nop
	nop
	nop
	
exit:		
        mov	0,%o0			! exit value
        mov	SYSCALL_EXIT,%g1        ! put the exit syscall number in g1
        ta      0x10			! and exit
	
	#================================
	# WRITE_STDOUT
	#================================
	# %o1 has string

write_stdout:

	set	SYSCALL_WRITE,%g1	! Write syscall in %g1
	set	STDOUT,%o0		! 1 in %o0 (stdout)
	set	0,%o2			! 0 (count) in %o2

str_loop1:
	ldub	[%o1+%o2],%l1		! load byte
	cmp	%l1,%g0			! compare against zero
	bnz	str_loop1		! if not nul, repeat
	# BRANCH DELAY SLOT
	inc	%o2			! increment count

	dec	%o2			! correct count	
	ta	0x10			! run the syscall

	retl
	nop




!===========================================================================
.data
!===========================================================================

data_region:		.int -1,-1
out_string:		.int 0

[-- Attachment #3: Type: APPLICATION/octet-stream, Size: 1563 bytes --]

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

* Re: [Qemu-devel] linux-user exception handling
  2008-08-27 16:58   ` Vince Weaver
@ 2008-08-27 17:14     ` Blue Swirl
  2008-08-27 17:30       ` Vince Weaver
  0 siblings, 1 reply; 8+ messages in thread
From: Blue Swirl @ 2008-08-27 17:14 UTC (permalink / raw)
  To: qemu-devel

On 8/27/08, Vince Weaver <vince@csl.cornell.edu> wrote:
> On Mon, 25 Aug 2008, Blue Swirl wrote:
>
> >
> > No, register window handling and other exceptions are handled in
> > linux-user/main.c.
> >
>
>  You are right.  It can be frustrating tracing through the code trying to
> find out what is being called when.
>
>  In any case, I think I've found a bug with register-window handling.
>  When using sparc32plus, the "wim" value isn't being updated on a
> save_window() call.  Thus when later a "ta 3" (flush register windows) call
> happens, the wrong windows get written out to memory.
>
>  I've attached some sample code that shows this problem.
>
>  The patch below fixes this for me, but it should be looked over carefully
> because the register window code in qemu is deep magic.
>
>  This fix allows the spec2k gcc.scilab and fma3d benchmarks to progress
> further.

How is that possible, because V9 class CPUs do not have "wim"?

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

* Re: [Qemu-devel] linux-user exception handling
  2008-08-27 17:14     ` Blue Swirl
@ 2008-08-27 17:30       ` Vince Weaver
  2008-08-27 18:19         ` Blue Swirl
  0 siblings, 1 reply; 8+ messages in thread
From: Vince Weaver @ 2008-08-27 17:30 UTC (permalink / raw)
  To: qemu-devel

On Wed, 27 Aug 2008, Blue Swirl wrote:
>
> How is that possible, because V9 class CPUs do not have "wim"?

I am running v8plus binaries, which are a horrible mix of v8 and v9 code.

But you are right, "wim" was deleted for v9.  The reason I did the code 
the way I did was because the restore_window() function was updating the 
register (even on sparc64).

So I guess the real fix is to implement proper save_window() and 
restore_window(), and also flush_window().  Then make sure that "ta 3" on 
v9 calls the proper flush_window() code.

As a temporary workaround though the patch I posted seems to work.

Vince

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

* Re: [Qemu-devel] linux-user exception handling
  2008-08-27 17:30       ` Vince Weaver
@ 2008-08-27 18:19         ` Blue Swirl
  2008-08-27 19:02           ` Vince Weaver
  0 siblings, 1 reply; 8+ messages in thread
From: Blue Swirl @ 2008-08-27 18:19 UTC (permalink / raw)
  To: qemu-devel

[-- Attachment #1: Type: text/plain, Size: 835 bytes --]

On 8/27/08, Vince Weaver <vince@csl.cornell.edu> wrote:
> On Wed, 27 Aug 2008, Blue Swirl wrote:
>
> >
> > How is that possible, because V9 class CPUs do not have "wim"?
> >
>
>  I am running v8plus binaries, which are a horrible mix of v8 and v9 code.
>
>  But you are right, "wim" was deleted for v9.  The reason I did the code the
> way I did was because the restore_window() function was updating the
> register (even on sparc64).
>
>  So I guess the real fix is to implement proper save_window() and
> restore_window(), and also flush_window().  Then make sure that "ta 3" on v9
> calls the proper flush_window() code.
>
>  As a temporary workaround though the patch I posted seems to work.

With this patch I get the sequence AA to MM and then back to AA.
Strangely Sparc32 prints AA to MM and then back to BB, never reaches
AA.

[-- Attachment #2: fix_s32p_wim.diff --]
[-- Type: plain/text, Size: 1772 bytes --]

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

* Re: [Qemu-devel] linux-user exception handling
  2008-08-27 18:19         ` Blue Swirl
@ 2008-08-27 19:02           ` Vince Weaver
  2008-08-27 19:26             ` Blue Swirl
  0 siblings, 1 reply; 8+ messages in thread
From: Vince Weaver @ 2008-08-27 19:02 UTC (permalink / raw)
  To: qemu-devel

On Wed, 27 Aug 2008, Blue Swirl wrote:
>
> With this patch I get the sequence AA to MM and then back to AA.
> Strangely Sparc32 prints AA to MM and then back to BB, never reaches
> AA.

Your patch is much better than mine, with it all of the gcc spec2k inputs 
work.  So I'm all for committing it.

One semi-related thing, according to the documentation V9 increments CWP 
on save and decrements it on restore, while V8 does the opposite.  I'm not 
sure if it is worth making the Qemu save/restore code behave that way too.

Vince

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

* Re: [Qemu-devel] linux-user exception handling
  2008-08-27 19:02           ` Vince Weaver
@ 2008-08-27 19:26             ` Blue Swirl
  0 siblings, 0 replies; 8+ messages in thread
From: Blue Swirl @ 2008-08-27 19:26 UTC (permalink / raw)
  To: qemu-devel

On 8/27/08, Vince Weaver <vince@csl.cornell.edu> wrote:
> On Wed, 27 Aug 2008, Blue Swirl wrote:
>
> >
> > With this patch I get the sequence AA to MM and then back to AA.
> > Strangely Sparc32 prints AA to MM and then back to BB, never reaches
> > AA.
> >
>
>  Your patch is much better than mine, with it all of the gcc spec2k inputs
> work.  So I'm all for committing it.

Okay, I committed it.

The address where the windows are saved may be incorrect, perhaps the
stack bias of -2047 should be added?

>  One semi-related thing, according to the documentation V9 increments CWP on
> save and decrements it on restore, while V8 does the opposite.  I'm not sure
> if it is worth making the Qemu save/restore code behave that way too.

Maybe, I can't remember why I did it like that. It could have had
something to with register layout.

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

end of thread, other threads:[~2008-08-27 19:26 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-08-25 20:26 [Qemu-devel] linux-user exception handling Vince Weaver
2008-08-25 20:34 ` Blue Swirl
2008-08-27 16:58   ` Vince Weaver
2008-08-27 17:14     ` Blue Swirl
2008-08-27 17:30       ` Vince Weaver
2008-08-27 18:19         ` Blue Swirl
2008-08-27 19:02           ` Vince Weaver
2008-08-27 19:26             ` Blue Swirl

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).