Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 2 Nov 2004 16:12:47 +0300 (MSK)
From:      Andrew Belashov <bel@orel.ru>
To:        FreeBSD-gnats-submit@FreeBSD.org
Subject:   sparc64/73413: [patch] pthread(libkse) library is broken on sparc64
Message-ID:  <200411021312.iA2DClwd081016@white.orel.ru>
Resent-Message-ID: <200411021320.iA2DKJDQ009601@freefall.freebsd.org>

next in thread | raw e-mail | index | archive | help

>Number:         73413
>Category:       sparc64
>Synopsis:       [patch] pthread(libkse) library is broken on sparc64
>Confidential:   no
>Severity:       serious
>Priority:       low
>Responsible:    freebsd-sparc64
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Tue Nov 02 13:20:19 GMT 2004
>Closed-Date:
>Last-Modified:
>Originator:     Andrew Belashov
>Release:        FreeBSD 5.3-STABLE sparc64
>Organization:
JSC CenterTelecom
>Environment:
System: FreeBSD bel.localdomain 5.3-STABLE FreeBSD 5.3-STABLE #13: Tue Nov  2
14:04:34 MSK 2004     bel@bel.localdomain:/usr/obj/usr/src/sys/SUNC3D  sparc64

	Hardware: Ultra 60 (2 x UltraSparc IIi @ 450 MHz)

>Description:

	Programs compiled with libkse does not work at all.

>How-To-Repeat:

	Use this test code:

--- ss2.c begins here ---
#include <stdio.h>
#include <string.h>
#include <pthread.h>

static void *
entry1(void *argp)
{
	long x = 0, y = 1;
	while (1) {
		if ((y - x) != 1) {
			fprintf(stderr, "FATAL ERROR: (y - x) != 1, "
				"x = %ld, y = %ld\n", x, y);
		}
		x++; y++;
	}
	return NULL;
}

void *
entry2(void *argp)
{
	long x = 0, y = -1;
	while (1) {
		if ((y - x) != -1) {
			fprintf(stderr, "FATAL ERROR: (y - x) != -1, "
				"x = %ld, y = %ld\n", x, y);
		}
		x--; y--;
	}
	return NULL;
}

static void *
entry3(void *argp)
{
	long x = 0, y = 2;
	while (1) {
		if ((y - x) != 2) {
			fprintf(stderr, "FATAL ERROR: (y - x) != 2, "
				"x = %ld, y = %ld\n", x, y);
		}
		x += 2; y += 2;
	}
	return NULL;
}

static void *
entry4(void *argp)
{
	long x = 0, y = -2;
	while (1) {
		if ((y - x) != -2) {
			fprintf(stderr, "FATAL ERROR: (y - x) != -2, "
				"x = %ld, y = %ld\n", x, y);
		}
		x -= 2; y -= 2;
	}
	return NULL;
}

struct thr_table {
	void * 		(*entry)(void *);
	pthread_t	thread;
};

static struct thr_table threads[] = {
	{entry1, NULL},
	{entry2, NULL},
	{entry3, NULL},
	{entry4, NULL},
	{NULL, NULL}
};

int
main()
{
	int error;
	struct thr_table *pthr;

	for (pthr = threads; pthr->entry != NULL; pthr++) {
		error = pthread_create(&pthr->thread, NULL, pthr->entry, NULL);
		if (error)
			fprintf(stderr, "Error in pthread_create(): %s\n",
				strerror(error));
	}

	sleep(20);

	return 0;
}
--- ss2.c ends here ---

bel@bel$ cc -g -o ss2 ss2.c -lkse
bel@bel$ ./ss2
Segmentation fault (core dumped)

bel@bel$ gdb ss2 ss2.core
GNU gdb 6.1.1 [FreeBSD]
Copyright 2004 Free Software Foundation, Inc.
[...]
This GDB was configured as "sparc64-marcel-freebsd"...
Core was generated by `ss2'.
Program terminated with signal 11, Segmentation fault.
Reading symbols from /usr/lib/libkse.so.1...done.
Loaded symbols for /usr/lib/libkse.so.1
Reading symbols from /lib/libc.so.5...done.
Loaded symbols for /lib/libc.so.5
Reading symbols from /libexec/ld-elf.so.1...done.
Loaded symbols for /libexec/ld-elf.so.1
#0  0x0000000040507bb0 in __utrap_panic () from /lib/libc.so.5
(gdb) bt
#0  0x0000000040507bb0 in __utrap_panic () from /lib/libc.so.5
#1  0x00000000405079d4 in __sparc_utrap () from /lib/libc.so.5
#2  0x000000004049ab6c in __sparc_utrap_gen () from /lib/libc.so.5
#3  0x000000004049ab6c in __sparc_utrap_gen () from /lib/libc.so.5
Previous frame identical to this frame (corrupt stack?)
(gdb) quit

>Fix:

	I have preliminary patch. Also needed kernel patch from
PR sparc64/72998 <http://www.freebsd.org/cgi/query-pr.cgi?pr=sparc64/72998>;


--- libkse.patch begins here ---
--- lib/libpthread/arch/sparc64/include/pthread_md.h.orig	Thu Aug  5 09:29:06 2004
+++ lib/libpthread/arch/sparc64/include/pthread_md.h	Thu Sep 30 14:16:50 2004
@@ -232,6 +232,9 @@ _thread_switch(struct kcb *kcb, struct t
 
 	_tcb_set(kcb, tcb);
 	mc = &tcb->tcb_tmbx.tm_context.uc_mcontext;
+
+	/* XXX Setup new tcb_tp pointer in machine context */
+	mc->mc_global[6] = (uint64_t)_tp;
 	if (_libkse_debug == 0) {
 		tcb->tcb_tmbx.tm_lwp = kcb->kcb_kmbx.km_lwp;
 		if (setmbox)
--- lib/libpthread/arch/sparc64/sparc64/thr_getcontext.S.orig	Mon Aug  9 12:20:25 2004
+++ lib/libpthread/arch/sparc64/sparc64/thr_getcontext.S	Thu Sep 30 14:18:53 2004
@@ -27,24 +27,66 @@
 #include <machine/asm.h>
 __FBSDID("$FreeBSD: src/lib/libpthread/arch/sparc64/sparc64/thr_getcontext.S,v 1.3 2003/10/09 20:52:17 deischen Exp $");
 
+#include <machine/fsr.h>
+#include <machine/tstate.h>
+
 #include "assym.s"
 
+/*
+ * int thr_getcontext(mcontext_t *mcp);
+ *
+ * Returns -1 if there is an error, 0 no errors; 1 upon return
+ * from a setcontext().
+ */
 	.weak	CNAME(_thr_getcontext)
 	.set	CNAME(_thr_getcontext),CNAME(__thr_getcontext)
 ENTRY(__thr_getcontext)
 	add	%o7, 8, %o1
 	add	%o1, 4, %o2
+	stx	%g6, [%o0 + MC_GLOBAL + (6 * 8)] /* Current tcb_tp pointer */
+	stx	%g7, [%o0 + MC_GLOBAL + (7 * 8)] /* XXX %g7 not used? */
 	stx	%sp, [%o0 + MC_OUT + (6 * 8)]
 	stx	%o1, [%o0 + MC_TPC]
 	stx	%o2, [%o0 + MC_TNPC]
-	mov	MC_VALID_FLAGS, %l0		/* Validate the context. */
-	stx	%l0, [%o0 + MC_FLAGS]
-	mov	1, %l0
-	stx	%l0, [%o0 + MC_OUT + (0 * 8)]	/* return 1 when resumed */
-	retl
-	mov	0, %o0				/* return 0 */
+	rd	%y, %g1				/* XXX %y deprecated */
+	stx	%g1, [%o0 + MC_Y]
+	rd	%fprs, %g1
+	stx	%g1, [%o0 + MC_FPRS]
+	wr	%g0, FPRS_FEF, %fprs		/* Enable FPU */
+	stx	%fsr, [%o0 + MC_FSR]		/* Store FPU Status Register */
+	rd	%gsr, %g2
+	stx	%g2, [%o0 + MC_GSR]		/* Store %gsr */
+	wr	%g1, 0, %fprs			/* Restore %fprs */
+	andcc	%g1, FPRS_FEF, %g0		/* FPU enabled? */
+	bz,a,pt	%xcc, 1f
+	 nop
+	std	%f0,  [%o0 + MC_FP + (0 * 64)]	/* Store FPU registers */
+	std	%f16, [%o0 + MC_FP + (1 * 64)]
+	std	%f32, [%o0 + MC_FP + (2 * 64)]
+	std	%f48, [%o0 + MC_FP + (3 * 64)]
+
+1:
+	set	(TSTATE_IE | TSTATE_PEF), %g1
+	stx	%g1, [%o0 + MC_TSTATE]		/* XXX Emulated %tstate */
+	mov	T_RESERVED, %g1
+	stx	%g1, [%o0 + MC_TYPE]		/* XXX Emulated trap type */
+	clr	[%o0 + MC_WSTATE]		/* XXX Emulated %wstate */
+
+	mov	MC_VALID_FLAGS, %o3		/* Validate the context. */
+	stx	%o3, [%o0 + MC_FLAGS]
+	mov	1, %o3
+	stx	%o3, [%o0 + MC_OUT + (0 * 8)]	/* return 1 when resumed */
+	jmpl	%o7 + 8, %g0
+	 clr	%o0				/* return 0 */
 END(__thr_getcontext)
 
+/*
+ * int thr_setcontext(mcontext_t *mcp, intptr_t val, intptr_t *loc)
+ *
+ * Restores the context in mcp.
+ *
+ * Returns 0 if there are no errors; -1 otherwise
+ */
 	.weak	CNAME(_thr_setcontext)
 	.set	CNAME(_thr_setcontext),CNAME(__thr_setcontext)
 ENTRY(__thr_setcontext)
@@ -53,28 +95,59 @@ ENTRY(__thr_setcontext)
 	mov	%i0, %l0
 	mov	%i1, %l1
 	mov	%i2, %l2
+	ldx	[%l0 + MC_FLAGS], %l5
+	cmp	%l5, MC_VALID_FLAGS
+	be,pt	%icc, 2f			/* XXX Checking lower 32bit */
+	 nop
+	return	%i7 + 8
+	 mov	-1, %i0				/* Return -1 */
+2:
 	ldx	[%l0 + MC_GLOBAL + (1 * 8)], %g1
 	ldx	[%l0 + MC_GLOBAL + (2 * 8)], %g2
 	ldx	[%l0 + MC_GLOBAL + (3 * 8)], %g3
 	ldx	[%l0 + MC_GLOBAL + (4 * 8)], %g4
 	ldx	[%l0 + MC_GLOBAL + (5 * 8)], %g5
-	ldx	[%l0 + MC_GLOBAL + (6 * 8)], %g6
-	ldx	[%l0 + MC_GLOBAL + (7 * 8)], %g7
-	ldx	[%l0 + MC_OUT + (0 * 8)], %i0
+	ldx	[%l0 + MC_GLOBAL + (6 * 8)], %g6 /* Current tcb_tp pointer */
+	ldx	[%l0 + MC_GLOBAL + (7 * 8)], %g7 /* XXX %g7 not used? */
+	ldx	[%l0 + MC_OUT + (0 * 8)], %i0	/* Return value */
 	ldx	[%l0 + MC_OUT + (1 * 8)], %i1
 	ldx     [%l0 + MC_OUT + (2 * 8)], %i2
 	ldx	[%l0 + MC_OUT + (3 * 8)], %i3
 	ldx	[%l0 + MC_OUT + (4 * 8)], %i4
 	ldx	[%l0 + MC_OUT + (5 * 8)], %i5
-	ldx	[%l0 + MC_OUT + (6 * 8)], %i6
+	ldx	[%l0 + MC_OUT + (6 * 8)], %fp	/* %fp */
 	ldx	[%l0 + MC_OUT + (7 * 8)], %i7
+	ldx	[%l0 + MC_FPRS], %l5
+	ldx	[%l0 + MC_GSR], %l4
+	ldx	[%l0 + MC_Y], %l3
+	wr	%g0, FPRS_FEF, %fprs		/* Enable FPU */
+	andcc	%l5, FPRS_FEF, %g0		/* FPU has been enabled? */
+	bz,a,pt	%xcc, 3f
+	 nop
+	ldd	[%l0 + MC_FP + (0 * 64)], %f0	/* Restore FPU registers */
+	ldd	[%l0 + MC_FP + (1 * 64)], %f16
+	ldd	[%l0 + MC_FP + (2 * 64)], %f32
+	ldd	[%l0 + MC_FP + (3 * 64)], %f48
+3:
+	ldx	[%l0 + MC_FSR], %fsr		/* Restore %fsr */
+	wr	%l4, 0, %gsr			/* Restore %gsr */
+	wr	%g0, 0, %fprs			/* Disable FPU */
+	wr	%l3, 0, %y			/* XXX %y deprecated */
+	wr	%l5, 0, %fprs			/* Restore %fprs */
 	ldx	[%l0 + MC_TPC], %l4
 	ldx	[%l0 + MC_TNPC], %l3
-	brz	%l2, 1f
-	nop
-	stx	%l1, [%l2]
-1:	jmpl	%l3, %g0
-	return	%l4
+	ldx	[%l0 + MC_TSTATE], %l5
+	brnz,a,pn	%l2, 1f
+	 stx	%l1, [%l2]			/* Set mbox */
+1:	
+	srlx	%l5, TSTATE_CCR_SHIFT, %l1
+	and	%l1, CCR_MASK, %l1
+	srlx	%l5, TSTATE_ASI_SHIFT, %l2
+	and	%l2, ASI_MASK, %l2
+	wr	%l2, 0, %asi
+	wr	%l1, 0, %ccr
+	jmpl	%l4, %g0
+	 return	%l3
 END(__thr_setcontext)
 
 ENTRY(_sparc64_enter_uts)
@@ -83,5 +156,5 @@ ENTRY(_sparc64_enter_uts)
 	add	%i2, %i3, %i2
 	sub	%i2, SPOFF + CCFSZ, %sp
 	jmpl	%i0, %g0
-	mov	%i1, %o0
+	 mov	%i1, %o0
 END(_sparc64_enter_uts)
--- lib/libpthread/arch/sparc64/sparc64/assym.s.orig	Thu Oct  9 18:48:09 2003
+++ lib/libpthread/arch/sparc64/sparc64/assym.s	Thu Sep 30 13:26:09 2004
@@ -11,5 +11,22 @@
 #define	MC_VALID_FLAGS	0x1
 #define	MC_GLOBAL	0x0
 #define	MC_OUT		0x40
-#define	MC_TPC		0xc8
+#define	MC_LOCAL	0x80
+#define	MC_IN		0xc0
+#define MC_FP		0x100
+#define MC_SIZEOF	512
+
+#define	MC_FPRS		0x80
+#define	MC_FSR		0x88
+#define	MC_GSR		0x90
 #define	MC_TNPC		0xc0
+#define	MC_TPC		0xc8
+#define MC_TSTATE	0xd0
+#define MC_TYPE		0xd8
+#define MC_Y		0xe0
+#define MC_WSTATE	0xe8
+
+#define CCR_MASK	0xff
+#define ASI_MASK	0xff
+#define T_SYSCALL	48
+#define T_RESERVED	0
--- libkse.patch ends here ---


>Release-Note:
>Audit-Trail:
>Unformatted:



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200411021312.iA2DClwd081016>