Subject: Re: 32 bit linux java solution?
To: None <port-amd64@netbsd.org>
From: Christos Zoulas <christos@astron.com>
List: port-amd64
Date: 11/22/2007 01:32:08
In article <474363DD.7080302@pp2.inet.fi>,
Arto Huusko <arto.huusko@pp2.inet.fi> wrote:
>I think I have found the reason why 32 bit linux java eventually
>ends up in the state where one thread keeps faulting, and another
>thread keeps on calling sched_yield. (BTW, 64 bit java is not
>functional even on AMD processors in -current, but that's beside
>the point here...)
>
>It has to do with some JVM feature called safepointing, which is
>implemented by a thread manipulating protection of one page,
>and then yielding until other threads notice the situation
>by getting SIGSEGV, and doing whatever they need to do.
>
>On NetBSD, the thread getting SIGSEGV doesn't notice that the
>signal was received due to safepointing (and apparently ends up
>restarting the instruction over and over again), because
>
> - for some reason JVM inspects the fault address from cr2 field
> of mcontext of ucontext (instead of si_addr of sigcontext)
>
> see JVM_handle_linux_signal in
> hotspot/src/os_cpu/linux_i486/os_linux_i486.cpp
>
> - NetBSD linux32 emul does not set this field
>
> see linux32_save_sigcontext in
> sys/compat/linux32/arch/amd64/linux32_machdep.c
> in revision 1.12, on line 389:
>
> /* sc->sc_cr2 = l->l_addr->u_pcb.pcb_cr2; */ /* XXX */
>
>I unfortunately have no idea where a suitable value for cr2 is
>available at that point...
Index: compat/linux32/arch/amd64/linux32_machdep.c
===================================================================
RCS file: /cvsroot/src/sys/compat/linux32/arch/amd64/linux32_machdep.c,v
retrieving revision 1.12
diff -u -u -r1.12 linux32_machdep.c
--- compat/linux32/arch/amd64/linux32_machdep.c 19 Oct 2007 12:16:39 -0000 1.12
+++ compat/linux32/arch/amd64/linux32_machdep.c 22 Nov 2007 01:30:58 -0000
@@ -386,7 +386,7 @@
sc->sc_ss = tf->tf_ss;
sc->sc_err = tf->tf_err;
sc->sc_trapno = tf->tf_trapno;
- /* sc->sc_cr2 = l->l_addr->u_pcb.pcb_cr2; */ /* XXX */
+ sc->sc_cr2 = l->l_addr->u_pcb.pcb_cr2;
NETBSD32PTR32(sc->sc_387, NULL);
/* Save signal stack. */
Index: arch/amd64/amd64/trap.c
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/amd64/trap.c,v
retrieving revision 1.36
diff -u -u -r1.36 trap.c
--- arch/amd64/amd64/trap.c 15 Nov 2007 19:18:33 -0000 1.36
+++ arch/amd64/amd64/trap.c 22 Nov 2007 01:30:58 -0000
@@ -452,7 +452,8 @@
vm = p->p_vmspace;
if (vm == NULL)
goto we_re_toast;
- va = trunc_page((vaddr_t)cr2);
+ pcb->pcb_cr2 = cr2;
+ va = trunc_page((vaddr_t)cr2);
/*
* It is only a kernel address space fault iff:
* 1. (type & T_USER) == 0 and
Index: arch/amd64/include/pcb.h
===================================================================
RCS file: /cvsroot/src/sys/arch/amd64/include/pcb.h,v
retrieving revision 1.7
diff -u -u -r1.7 pcb.h
--- arch/amd64/include/pcb.h 17 Oct 2007 19:53:04 -0000 1.7
+++ arch/amd64/include/pcb.h 22 Nov 2007 01:30:58 -0000
@@ -107,6 +107,7 @@
u_int64_t pcb_ldt_sel;
struct savefpu pcb_savefpu; /* floating point state */
int pcb_cr0; /* saved image of CR0 */
+ int pcb_cr2; /* page fault address (CR2) */
int pcb_flags;
#define PCB_USER_LDT 0x01 /* has user-set LDT */
#define PCB_GS64 0x02