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