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