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