Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 12 Aug 1998 13:31:42 -0400 (EDT)
From:      Luoqi Chen <luoqi@chen.ml.org>
To:        FreeBSD-gnats-submit@FreeBSD.ORG
Subject:   i386/7591: Move `currentldt' to per-cpu area (for wine to work on SMP)
Message-ID:  <199808121731.NAA02965@sabrina.chen.ml.org>

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


>Number:         7591
>Category:       i386
>Synopsis:       `currentldt' should be in per-cpu area on SMP
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:
>Keywords:
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Wed Aug 12 11:00:00 PDT 1998
>Last-Modified:
>Originator:     Luoqi Chen
>Organization:
>Release:        FreeBSD 3.0-CURRENT i386
>Environment:

	3.0-CURRENT SMP kernel with USER_LDT option.

>Description:

	Presently there is only one `currentldt' variable for all cpus
	in a SMP system. Unexpected things could happen if each cpu
	has a different ldt setting and one cpu tries to use value
	of currentldt set by another cpu.

>How-To-Repeat:

	Run wine on a SMP machine with SMP kernel.

>Fix:
	
	The fix is to move currentldt to the per-cpu area. It includes
	patches I filed in PR i386/6219 which are also user ldt related.

Index: sys/i386/i386/genassym.c
===================================================================
RCS file: /fun/cvs/src/sys/i386/i386/genassym.c,v
retrieving revision 1.59
diff -u -r1.59 genassym.c
--- genassym.c	1998/07/11 12:17:07	1.59
+++ genassym.c	1998/08/11 22:26:13
@@ -38,6 +38,7 @@
  */
 
 #include "opt_vm86.h"
+#include "opt_user_ldt.h"
 
 #include <stddef.h>
 
@@ -203,6 +204,9 @@
 	printf("#define\tGD_COMMON_TSSD %#x\n", OS(globaldata, common_tssd));
 	printf("#define\tGD_PRIVATE_TSS %#x\n", OS(globaldata, private_tss));
 	printf("#define\tGD_MY_TR %#x\n", OS(globaldata, my_tr));
+#endif
+#ifdef USER_LDT
+	printf("#define\tGD_CURRENTLDT %#x\n", OS(globaldata, currentldt));
 #endif
 #ifdef SMP
 	printf("#define\tGD_CPUID %#x\n", OS(globaldata, cpuid));
Index: sys/i386/i386/globals.s
===================================================================
RCS file: /fun/cvs/src/sys/i386/i386/globals.s,v
retrieving revision 1.6
diff -u -r1.6 globals.s
--- globals.s	1998/06/21 14:45:00	1.6
+++ globals.s	1998/08/11 22:26:42
@@ -27,6 +27,7 @@
  */
 
 #include "opt_vm86.h"
+#include "opt_user_ldt.h"
 
 #ifndef SMP
 #include <machine/asmacros.h>
@@ -82,6 +83,11 @@
 	.set	_common_tssd,globaldata + GD_COMMON_TSSD
 	.set	_private_tss,globaldata + GD_PRIVATE_TSS
 	.set	_my_tr,globaldata + GD_MY_TR
+#endif
+
+#ifdef USER_LDT
+	.globl	_currentldt
+	.set	_currentldt,globaldata + GD_CURRENTLDT
 #endif
 
 #ifdef SMP
Index: sys/i386/i386/machdep.c
===================================================================
RCS file: /fun/cvs/src/sys/i386/i386/machdep.c,v
retrieving revision 1.303
diff -u -r1.303 machdep.c
--- machdep.c	1998/07/11 07:45:30	1.303
+++ machdep.c	1998/08/11 22:35:23
@@ -801,14 +801,15 @@
 	u_long stack;
 {
 	struct trapframe *regs = p->p_md.md_regs;
-
-#ifdef USER_LDT
 	struct pcb *pcb = &p->p_addr->u_pcb;
 
+#ifdef USER_LDT
 	/* was i386_user_cleanup() in NetBSD */
 	if (pcb->pcb_ldt) {
-		if (pcb == curpcb)
-			lldt(GSEL(GUSERLDT_SEL, SEL_KPL));
+		if (pcb == curpcb) {
+			lldt(_default_ldt);
+			currentldt = _default_ldt;
+		}
 		kmem_free(kernel_map, (vm_offset_t)pcb->pcb_ldt,
 			pcb->pcb_ldt_len * sizeof(union descriptor));
 		pcb->pcb_ldt_len = (int)pcb->pcb_ldt = 0;
@@ -824,6 +825,14 @@
 	regs->tf_es = _udatasel;
 	regs->tf_cs = _ucodesel;
 
+	/* reset %fs and %gs as well */
+	pcb->pcb_fs = _udatasel;
+	pcb->pcb_gs = _udatasel;
+	if (pcb == curpcb) {
+		__asm("mov %0,%%fs" : : "r" (_udatasel));
+		__asm("mov %0,%%gs" : : "r" (_udatasel));
+	}
+
 	/*
 	 * Initialize the math emulator (if any) for the current process.
 	 * Actually, just clear the bit that says that the emulator has
@@ -881,7 +890,6 @@
  * Initialize segments & interrupt table
  */
 
-int currentldt;
 int _default_ldt;
 #ifdef SMP
 union descriptor gdt[NGDT + NCPU];	/* global descriptor table */
@@ -1248,7 +1256,9 @@
 
 	_default_ldt = GSEL(GLDT_SEL, SEL_KPL);
 	lldt(_default_ldt);
+#ifdef USER_LDT
 	currentldt = _default_ldt;
+#endif
 
 #ifdef DDB
 	kdb_init();
Index: sys/i386/i386/mp_machdep.c
===================================================================
RCS file: /fun/cvs/src/sys/i386/i386/mp_machdep.c,v
retrieving revision 1.76
diff -u -r1.76 mp_machdep.c
--- mp_machdep.c	1998/05/17 22:12:08	1.76
+++ mp_machdep.c	1998/08/11 22:25:26
@@ -28,6 +28,7 @@
 #include "opt_smp.h"
 #include "opt_vm86.h"
 #include "opt_cpu.h"
+#include "opt_user_ldt.h"
 
 #ifdef SMP
 #include <machine/smptests.h>
@@ -466,6 +467,9 @@
 	lgdt(&r_gdt);			/* does magic intra-segment return */
 	lidt(&r_idt);
 	lldt(_default_ldt);
+#ifdef USER_LDT
+	currentldt = _default_ldt;
+#endif
 
 	my_tr = NGDT + cpuid;
 	gsel_tss = GSEL(my_tr, SEL_KPL);
Index: sys/i386/i386/sys_machdep.c
===================================================================
RCS file: /fun/cvs/src/sys/i386/i386/sys_machdep.c,v
retrieving revision 1.35
diff -u -r1.35 sys_machdep.c
--- sys_machdep.c	1998/07/28 03:29:32	1.35
+++ sys_machdep.c	1998/08/11 22:32:03
@@ -64,8 +64,8 @@
 
 
 
-void set_user_ldt	__P((struct pcb *pcb));
 #ifdef USER_LDT
+void set_user_ldt	__P((struct pcb *pcb));
 static int i386_get_ldt	__P((struct proc *, char *));
 static int i386_set_ldt	__P((struct proc *, char *));
 #endif
Index: sys/i386/i386/vm_machdep.c
===================================================================
RCS file: /fun/cvs/src/sys/i386/i386/vm_machdep.c,v
retrieving revision 1.108
diff -u -r1.108 vm_machdep.c
--- vm_machdep.c	1998/05/19 00:00:10	1.108
+++ vm_machdep.c	1998/07/04 03:05:13
@@ -710,8 +710,10 @@
 #endif
 #ifdef USER_LDT
 	if (pcb->pcb_ldt != 0) {
-		if (pcb == curpcb)
-			lldt(GSEL(GUSERLDT_SEL, SEL_KPL));
+		if (pcb == curpcb) {
+			lldt(_default_ldt);
+			currentldt = _default_ldt;
+		}
 		kmem_free(kernel_map, (vm_offset_t)pcb->pcb_ldt,
 			pcb->pcb_ldt_len * sizeof(union descriptor));
 		pcb->pcb_ldt_len = (int)pcb->pcb_ldt = 0;
Index: sys/i386/include/globaldata.h
===================================================================
RCS file: /fun/cvs/src/sys/i386/include/globaldata.h,v
retrieving revision 1.5
diff -u -r1.5 globaldata.h
--- globaldata.h	1998/05/28 09:30:02	1.5
+++ globaldata.h	1998/08/11 22:15:54
@@ -49,6 +49,9 @@
 	u_int		private_tss;
 	u_int		my_tr;		
 #endif
+#ifdef USER_LDT
+	int		currentldt;
+#endif
 #ifdef SMP
 	u_int		cpuid;
 	u_int		cpu_lockid;
>Audit-Trail:
>Unformatted:

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-bugs" in the body of the message



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