changeset 1217:f95ffdc997b7

6219276 need per-process equivalent of device context 6244042 x86 kernels do not need default LDTs 6308413 sysi86(SI86DSCR) rejects the first valid custom descriptor #6 with errno 6308413 contributed by Juergen Keil <jk@tools.de>
author rab
date Fri, 06 Jan 2006 10:19:31 -0800
parents bbbeae705cee
children da9792769ae8
files usr/src/uts/common/Makefile.files usr/src/uts/common/disp/thread.c usr/src/uts/common/os/exec.c usr/src/uts/common/os/exit.c usr/src/uts/common/os/fork.c usr/src/uts/common/os/lwp.c usr/src/uts/common/os/proc.c usr/src/uts/common/sys/proc.h usr/src/uts/i86pc/ml/mpcore.s usr/src/uts/i86pc/ml/offsets.in usr/src/uts/i86pc/os/mlsetup.c usr/src/uts/i86pc/os/trap.c usr/src/uts/i86pc/sys/machcpuvar.h usr/src/uts/intel/ia32/ml/swtch.s usr/src/uts/intel/ia32/os/archdep.c usr/src/uts/intel/ia32/os/desctbls.c usr/src/uts/intel/ia32/os/syscall.c usr/src/uts/intel/ia32/os/sysi86.c usr/src/uts/intel/sys/segments.h
diffstat 19 files changed, 433 insertions(+), 346 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/Makefile.files	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/common/Makefile.files	Fri Jan 06 10:19:31 2006 -0800
@@ -20,7 +20,7 @@
 # CDDL HEADER END
 #
 #
-# Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
 # ident	"%Z%%M%	%I%	%E% SMI"
@@ -212,6 +212,7 @@
 		priocntl.o	\
 		priv.o		\
 		priv_const.o	\
+		proc.o		\
 		procset.o	\
 		processor_bind.o	\
 		processor_info.o	\
--- a/usr/src/uts/common/disp/thread.c	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/common/disp/thread.c	Fri Jan 06 10:19:31 2006 -0800
@@ -20,7 +20,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -582,6 +582,8 @@
 
 	if (t->t_ctx != NULL)
 		exitctx(t);
+	if (t->t_procp->p_pctx != NULL)
+		exitpctx(t->t_procp);
 
 	t->t_state = TS_ZOMB;	/* set zombie thread */
 
@@ -685,6 +687,8 @@
 		lwp_freeregs(t->t_lwp, 0);
 	if (t->t_ctx)
 		freectx(t, 0);
+	if (t->t_procp->p_pctx)
+		freepctx(t->t_procp, 0);
 	t->t_stk = NULL;
 	if (t->t_lwp)
 		lwp_stk_fini(t->t_lwp);
@@ -872,7 +876,7 @@
 }
 
 /*
- * Install a device context for the current thread
+ * Install thread context ops for the current thread.
  */
 void
 installctx(
@@ -900,8 +904,8 @@
 }
 
 /*
- * Remove a device context from the current thread
- * (Or allow the agent thread to remove device context from another
+ * Remove thread context ops from the current thread.
+ * (Or allow the agent thread to remove thread context ops from another
  * thread in the same, stopped, process)
  */
 int
@@ -1006,7 +1010,7 @@
 
 /*
  * freectx is called from thread_free() and exec() to get
- * rid of old device context.
+ * rid of old thread context ops.
  */
 void
 freectx(kthread_t *t, int isexec)
--- a/usr/src/uts/common/os/exec.c	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/common/os/exec.c	Fri Jan 06 10:19:31 2006 -0800
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -87,11 +87,6 @@
 uint_t auxv_hwcap32 = 0;	/* 32-bit version of auxv_hwcap */
 #endif
 
-#if defined(__i386) || defined(__amd64)
-extern void ldt_free(proc_t *p);
-extern void ldt_load(void);
-#endif
-
 int exec_lpg_disable = 0;
 
 #define	PSUIDFLAGS		(SNOCD|SUGID)
@@ -257,10 +252,12 @@
 	lwp_freeregs(lwp, 1);
 
 	/*
-	 * Free device context
+	 * Free thread and process context ops.
 	 */
 	if (curthread->t_ctx)
 		freectx(curthread, 1);
+	if (p->p_pctx)
+		freepctx(p, 1);
 
 	/*
 	 * Remember file name for accounting; clear any cached DTrace predicate.
@@ -343,30 +340,6 @@
 
 	ASSERT(curthread->t_schedctl == NULL);
 
-#if defined(__i386) || defined(__amd64)
-	/* If the process uses a private LDT then change it to default */
-	if (p->p_ldt)
-		ldt_free(p);
-#endif	/* __i386 || __amd64 */
-
-#if defined(__amd64)
-	/*
-	 * Make sure the process has the correct LDT descriptor for its data
-	 * model.
-	 */
-	if (p->p_model == DATAMODEL_LP64)
-		p->p_ldt_desc = ldt0_default64_desc;
-	else
-		p->p_ldt_desc = ldt0_default_desc;
-
-	/*
-	 * Ensure the change of LDT is propagated into the LDTR.
-	 */
-	kpreempt_disable();
-	ldt_load();
-	kpreempt_enable();
-#endif /* __amd64 */
-
 #if defined(__sparc)
 	if (p->p_utraps != NULL)
 		utrap_free(p);
--- a/usr/src/uts/common/os/exit.c	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/common/os/exit.c	Fri Jan 06 10:19:31 2006 -0800
@@ -21,7 +21,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -75,10 +75,6 @@
 #include <sys/sdt.h>
 #include <sys/corectl.h>
 
-#if defined(__x86)
-extern void ldt_free(proc_t *pp);
-#endif
-
 /*
  * convert code/data pair into old style wait status
  */
@@ -538,14 +534,6 @@
 	} else
 		mutex_exit(&pidlock);
 
-#if defined(__x86)
-	/*
-	 * If the process was using a private LDT then free it.
-	 */
-	if (p->p_ldt)
-		ldt_free(p);
-#endif
-
 #if defined(__sparc)
 	if (p->p_utraps != NULL)
 		utrap_free(p);
@@ -769,6 +757,24 @@
 	p->p_tidhash_sz = 0;
 
 	/*
+	 * If the process has context ops installed, call the exit routine
+	 * on behalf of this last remaining thread. Normally exitpctx() is
+	 * called during thread_exit() or lwp_exit(), but because this is the
+	 * last thread in the process, we must call it here. By the time
+	 * thread_exit() is called (below), the association with the relevant
+	 * process has been lost.
+	 *
+	 * We also free the context here.
+	 */
+	if (p->p_pctx) {
+		kpreempt_disable();
+		exitpctx(p);
+		kpreempt_enable();
+
+		freepctx(p, 0);
+	}
+
+	/*
 	 * curthread's proc pointer is changed to point at p0 because
 	 * curthread's original proc pointer can be freed as soon as
 	 * the child sends a SIGCLD to its parent.
--- a/usr/src/uts/common/os/fork.c	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/common/os/fork.c	Fri Jan 06 10:19:31 2006 -0800
@@ -21,7 +21,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -407,12 +407,11 @@
 	corectl_path_hold(cp->p_corefile = p->p_corefile);
 	corectl_content_hold(cp->p_content = p->p_content);
 
-#if defined(__x86)
 	/*
-	 * Get the right ldt descr for the child.
+	 * Duplicate process context ops, if any.
 	 */
-	(void) ldt_dup(p, cp);
-#endif
+	if (p->p_pctx)
+		forkpctx(p, cp);
 
 #ifdef __sparc
 	utrap_dup(p, cp);
@@ -796,10 +795,6 @@
 
 	p->p_as = &kas;
 
-#if defined(__x86)
-	(void) ldt_dup(&p0, p);		/* Get the default ldt descr */
-#endif
-
 	if ((lwp = lwp_create(pc, arg, 0, p, TS_STOPPED, pri,
 	    &curthread->t_hold, cid, 1)) == NULL) {
 		task_t *tk;
--- a/usr/src/uts/common/os/lwp.c	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/common/os/lwp.c	Fri Jan 06 10:19:31 2006 -0800
@@ -21,7 +21,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -785,6 +785,12 @@
 	 * death-row by resume().  Avoid preemption after resetting t->t_procp.
 	 */
 	t->t_preempt++;
+
+	if (t->t_ctx != NULL)
+		exitctx(t);
+	if (p->p_pctx != NULL)
+		exitpctx(p);
+
 	t->t_procp = &p0;
 
 	/*
@@ -817,9 +823,6 @@
 
 	lwp_pcb_exit();
 
-	if (t->t_ctx != NULL)
-		exitctx(t);
-
 	t->t_state = TS_ZOMB;
 	swtch_from_zombie();
 	/* never returns */
@@ -1617,12 +1620,7 @@
 	lwp_forkregs(lwp, clwp);
 
 	/*
-	 * fork device context, if any.
-	 *
-	 * Someday we could do the work to support the possibility of
-	 * forkctx() or lwp_createctx() failing.  Currently, this would
-	 * only be needed on x86 for the occasional process using a
-	 * private LDT.
+	 * Fork thread context ops, if any.
 	 */
 	if (t->t_ctx)
 		forkctx(t, ct);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/uts/common/os/proc.c	Fri Jan 06 10:19:31 2006 -0800
@@ -0,0 +1,155 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/proc.h>
+
+/*
+ * Install process context ops for the current process.
+ */
+void
+installpctx(
+	proc_t *p,
+	void	*arg,
+	void	(*save)(void *),
+	void	(*restore)(void *),
+	void	(*fork)(void *, void *),
+	void	(*exit)(void *),
+	void	(*free)(void *, int))
+{
+	struct pctxop *pctx;
+
+	pctx = kmem_alloc(sizeof (struct pctxop), KM_SLEEP);
+	pctx->save_op = save;
+	pctx->restore_op = restore;
+	pctx->fork_op = fork;
+	pctx->exit_op = exit;
+	pctx->free_op = free;
+	pctx->arg = arg;
+	pctx->next = p->p_pctx;
+	p->p_pctx = pctx;
+}
+
+/*
+ * Remove a process context ops from the current process.
+ */
+int
+removepctx(
+	proc_t *p,
+	void	*arg,
+	void	(*save)(void *),
+	void	(*restore)(void *),
+	void	(*fork)(void *, void *),
+	void	(*exit)(void *),
+	void	(*free)(void *, int))
+{
+	struct pctxop *pctx, *prev_pctx;
+
+	prev_pctx = NULL;
+	for (pctx = p->p_pctx; pctx != NULL; pctx = pctx->next) {
+		if (pctx->save_op == save && pctx->restore_op == restore &&
+		    pctx->fork_op == fork &&
+		    pctx->exit_op == exit && pctx->free_op == free &&
+		    pctx->arg == arg) {
+			if (prev_pctx)
+				prev_pctx->next = pctx->next;
+			else
+				p->p_pctx = pctx->next;
+			if (pctx->free_op != NULL)
+				(pctx->free_op)(pctx->arg, 0);
+			kmem_free(pctx, sizeof (struct pctxop));
+			return (1);
+		}
+		prev_pctx = pctx;
+	}
+	return (0);
+}
+
+void
+savepctx(proc_t *p)
+{
+	struct pctxop *pctx;
+
+	ASSERT(p == curthread->t_procp);
+	for (pctx = p->p_pctx; pctx != 0; pctx = pctx->next)
+		if (pctx->save_op != NULL)
+			(pctx->save_op)(pctx->arg);
+}
+
+void
+restorepctx(proc_t *p)
+{
+	struct pctxop *pctx;
+
+	ASSERT(p == curthread->t_procp);
+	for (pctx = p->p_pctx; pctx != 0; pctx = pctx->next)
+		if (pctx->restore_op != NULL)
+			(pctx->restore_op)(pctx->arg);
+}
+
+void
+forkpctx(proc_t *p, proc_t *cp)
+{
+	struct pctxop *pctx;
+
+	for (pctx = p->p_pctx; pctx != NULL; pctx = pctx->next)
+		if (pctx->fork_op != NULL)
+			(pctx->fork_op)(p, cp);
+}
+
+/*
+ * exitpctx is called during thread/lwp exit to perform any actions
+ * needed when an LWP in the process leaves the processor for the last
+ * time. This routine is not intended to deal with freeing memory; freepctx()
+ * is used for that purpose during proc_exit(). This routine is provided to
+ * allow for clean-up that can't wait until thread_free().
+ */
+void
+exitpctx(proc_t *p)
+{
+	struct pctxop *pctx;
+
+	for (pctx = p->p_pctx; pctx != NULL; pctx = pctx->next)
+		if (pctx->exit_op != NULL)
+			(pctx->exit_op)(p);
+}
+
+/*
+ * freepctx is called from proc_exit() to get rid of the actual context ops.
+ */
+void
+freepctx(proc_t *p, int isexec)
+{
+	struct pctxop *pctx;
+
+	while ((pctx = p->p_pctx) != NULL) {
+		p->p_pctx = pctx->next;
+		if (pctx->free_op != NULL)
+			(pctx->free_op)(pctx->arg, isexec);
+		kmem_free(pctx, sizeof (struct pctxop));
+	}
+}
--- a/usr/src/uts/common/sys/proc.h	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/common/sys/proc.h	Fri Jan 06 10:19:31 2006 -0800
@@ -21,7 +21,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -86,6 +86,16 @@
 	struct vnode	*le_trace;	/* pointer to /proc lwp vnode */
 } lwpent_t;
 
+typedef struct pctxop {
+	void	(*save_op)(void *);	/* function to invoke to save ctx */
+	void	(*restore_op)(void *);	/* function to invoke to restore ctx */
+	void	(*fork_op)(void *, void *); /* invoke to fork context */
+	void	(*exit_op)(void *);	/* invoked during process exit */
+	void	(*free_op)(void *, int); /* function which frees the context */
+	void	*arg;			/* argument to above functions */
+	struct pctxop *next;		/* next pcontext ops */
+} pctxop_t;
+
 /*
  * Elements of the lwp directory, p->p_lwpdir[].
  *
@@ -270,6 +280,9 @@
 	 * C2 Security  (C2_AUDIT)
 	 */
 	struct p_audit_data	*p_audit_data; /* per process audit structure */
+
+	pctxop_t	*p_pctx;
+
 #if defined(__x86)
 	/*
 	 * LDT support.
@@ -551,7 +564,7 @@
 extern void upcount_dec(uid_t, zoneid_t);
 extern int upcount_get(uid_t, zoneid_t);
 #if defined(__x86)
-extern int ldt_dup(proc_t *, proc_t *);
+extern void ldt_dup(proc_t *, proc_t *);
 extern selector_t setup_thrptr(proc_t *, uintptr_t);
 #endif
 
@@ -644,6 +657,15 @@
 extern	void	lwp_createctx(kthread_t *, kthread_t *);
 extern	void	exitctx(kthread_t *);
 extern	void	freectx(kthread_t *, int);
+extern	void	installpctx(proc_t *, void *, void (*)(), void (*)(),
+    void (*)(), void (*)(), void (*)());
+extern	int	removepctx(proc_t *, void *, void (*)(), void (*)(),
+    void (*)(), void (*)(), void (*)());
+extern	void	savepctx(proc_t *);
+extern	void	restorepctx(proc_t *);
+extern	void	forkpctx(proc_t *, proc_t *);
+extern	void	exitpctx(proc_t *);
+extern	void	freepctx(proc_t *, int);
 extern	kthread_t *thread_unpin(void);
 extern	void	thread_create_intr(struct cpu *);
 extern	void	thread_init(void);
--- a/usr/src/uts/i86pc/ml/mpcore.s	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/i86pc/ml/mpcore.s	Fri Jan 06 10:19:31 2006 -0800
@@ -20,7 +20,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 	
@@ -252,7 +252,7 @@
 	movw	$KTSS_SEL, %ax		/* setup kernel TSS */
 	ltr	%ax
 
-	movw	$ULDT_SEL, %ax		/* setup ldt */
+	xorw	%ax, %ax		/* clear LDTR */
 	lldt	%ax
 
 	/*
@@ -500,7 +500,7 @@
 	movw	$KTSS_SEL, %ax		/* setup kernel TSS */
 	ltr	%ax
 
-	movw	$ULDT_SEL, %ax		/* setup ldt */
+	xorw	%ax, %ax		/* clear LDTR */
 	lldt	%ax
 
 	/*
@@ -636,7 +636,7 @@
 	movl	TSS_ESP0(%esi),%esp
 	movw	$KTSS_SEL,%ax
 	ltr	%ax
-	movw	$ULDT_SEL, %ax		  /* setup ldt */
+	xorw	%ax, %ax		/* clear LDTR */
 	lldt	%ax
 	movl	%cr0,%edx
 	andl    $-1![CR0_TS|CR0_EM],%edx  /* clear emulate math chip bit */
@@ -719,7 +719,7 @@
 	mov	TSS_ESP0(%esi), %esp
 	mov	$(KTSS_SEL), %ax
 	ltr	%ax
-	mov	$ULDT_SEL, %ax		/* load user ldt */
+	xorw	%ax, %ax		/* clear LDTR */
 	lldt	%ax
 	mov	%cr0, %edx
 	and	$~(CR0_TS|CR0_EM), %edx	/* clear emulate math chip bit */
--- a/usr/src/uts/i86pc/ml/offsets.in	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/i86pc/ml/offsets.in	Fri Jan 06 10:19:31 2006 -0800
@@ -1,5 +1,5 @@
 \
-\ Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+\ Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 \ Use is subject to license terms.
 \
 \ CDDL HEADER START
@@ -75,6 +75,7 @@
 	p_ldt
 	p_ldt_desc
 	p_model
+	p_pctx
 	p_agenttp
 
 _kthread	THREAD_SIZE
--- a/usr/src/uts/i86pc/os/mlsetup.c	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/i86pc/os/mlsetup.c	Fri Jan 06 10:19:31 2006 -0800
@@ -20,7 +20,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -296,23 +296,12 @@
 
 	CPU->cpu_pri = 12;		/* initial PIL for the boot CPU */
 
-	CPU->cpu_ldt = ldt0_default;	/* default LDT */
 	CPU->cpu_gdt = gdt0;
 
 	/*
-	 * This must be done _after_ init_tables(), called above, has set up
-	 * ldt0_default_desc.
+	 * The kernel doesn't use LDTs unless a process explicitly requests one.
 	 */
-#if defined(__amd64)
-	/*
-	 * ldt0_default64 contains all invalid entries. We use that as p0's LDT
-	 * because p0 should never have any reason to use the LDT. This will
-	 * catch things early if such a scenario should ever occur.
-	 */
-	p0.p_ldt_desc = ldt0_default64_desc;
-#else
-	p0.p_ldt_desc = ldt0_default_desc;
-#endif /* __amd64 */
+	p0.p_ldt_desc = zero_sdesc;
 
 	/*
 	 * Kernel IDT.
--- a/usr/src/uts/i86pc/os/trap.c	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/i86pc/os/trap.c	Fri Jan 06 10:19:31 2006 -0800
@@ -21,7 +21,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -993,14 +993,39 @@
 		if (kern_gpfault(rp))
 			(void) die(type, rp, addr, cpuid);
 		goto cleanup;
+		/*FALLTHROUGH*/
 
+/*
+ * ONLY 32-bit PROCESSES can USE a PRIVATE LDT! 64-bit apps should have
+ * no legacy need for them, so we put a stop to it here.
+ *
+ * So: not-present fault is ONLY valid for 32-bit processes with a private LDT
+ * trying to do a system call. Emulate it.
+ *
+ * #gp fault is ONLY valid for 32-bit processes also, which DO NOT have private
+ * LDT, and are trying to do a system call. Emulate it.
+ */
 	case T_SEGFLT + USER:	/* segment not present fault */
+	case T_GPFLT + USER:	/* general protection violation */
 #ifdef _SYSCALL32_IMPL
+		if (p->p_model != DATAMODEL_NATIVE) {
+#endif /* _SYSCALL32_IMPL */
 		if (instr_is_syscall((caddr_t)rp->r_pc)) {
+			if (type == T_SEGFLT + USER)
+				ASSERT(p->p_ldt != NULL);
+
+			if ((p->p_ldt == NULL && type == T_GPFLT + USER) ||
+			    type == T_SEGFLT + USER) {
+
 			/*
-			 * System calls via the call gate come in through
-			 * not-present traps.
-			 *
+			 * The user attempted a system call via the obsolete
+			 * call gate mechanism. Because the process doesn't have
+			 * an LDT (i.e. the ldtr contains 0), a #gp results.
+			 * Emulate the syscall here, just as we do above for a
+			 * #np trap.
+			 */
+
+			/*
 			 * Since this is a not-present trap, rp->r_pc points to
 			 * the trapping lcall instruction. We need to bump it
 			 * to the next insn so the app can continue on.
@@ -1017,11 +1042,11 @@
 
 			dosyscall();
 			goto out;
+			}
+		}
+#ifdef _SYSCALL32_IMPL
 		}
 #endif /* _SYSCALL32_IMPL */
-		/*FALLTHROUGH*/
-
-	case T_GPFLT + USER:	/* general protection violation */
 		/*
 		 * If the current process is using a private LDT and the
 		 * trapping instruction is sysenter, the sysenter instruction
--- a/usr/src/uts/i86pc/sys/machcpuvar.h	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/i86pc/sys/machcpuvar.h	Fri Jan 06 10:19:31 2006 -0800
@@ -20,7 +20,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -76,10 +76,8 @@
 	/* i86 hardware table addresses that cannot be shared */
 	user_desc_t	*mcpu_gdt;	/* GDT */
 	gate_desc_t	*mcpu_idt;	/* IDT */
-
 	struct tss	*mcpu_tss;	/* TSS */
 
-	user_desc_t	*mcpu_ldt;	/* LDT XXX - needed? */
 	struct	cpu_tables *mcpu_cp_tables;	/* pointer to space acquired */
 						/* while starting up */
 						/* auxillary processors */
--- a/usr/src/uts/intel/ia32/ml/swtch.s	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/intel/ia32/ml/swtch.s	Fri Jan 06 10:19:31 2006 -0800
@@ -20,7 +20,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -216,22 +216,18 @@
 	call	savectx			/* call ctx ops */
 
 .nosavectx:
-	/*
-	 * Setup LDT register
-	 */
-	movq 	T_PROCP(%r12), %rax	/* load new thread proc */
-
-	/* make sure GDT contains the right LDT desc */
-	movq	%gs:CPU_GDT, %r11
+        /*
+         * Call savepctx if process has installed context ops.
+         */
+	movq	T_PROCP(%r13), %r14	/* %r14 = proc */
+        cmpq    $0, P_PCTX(%r14)         /* should current thread savectx? */
+        je      .nosavepctx              /* skip call when zero */
 
-	movq	P_LDT_DESC(%rax), %r10
-	movq	_CONST(P_LDT_DESC+8)(%rax), %rax
-	movq	%r10, ULDT_SEL(%r11)
-	movq	%rax, _CONST(ULDT_SEL+8)(%r11)
-	movl	$ULDT_SEL, %edx
-	lldt	%dx
+        movq    %r14, %rdi              /* arg = proc pointer */
+        call    savepctx                 /* call ctx ops */
+.nosavepctx:
 
-	/* 
+	/*
 	 * Temporarily switch to the idle thread's stack
 	 */
 	movq	CPU_IDLE_THREAD(%r15), %rax 	/* idle thread pointer */
@@ -329,10 +325,19 @@
 	jz	.norestorectx		/* skip call when zero */
 	movq	%r12, %rdi		/* arg = thread pointer */
 	call	restorectx		/* call ctx ops */
-
 .norestorectx:
 
 	/*
+	 * Call restorepctx if context ops have been installed for the proc.
+	 */
+	movq	T_PROCP(%r12), %rcx
+	cmpq	$0, P_PCTX(%rcx)
+	jz	.norestorepctx
+	movq	%rcx, %rdi
+	call	restorepctx
+.norestorepctx:
+	
+	/*
 	 * If we are resuming an interrupt thread, store a timestamp 
 	 * in the thread structure.
 	 */
@@ -425,35 +430,28 @@
 	addl	$4, %esp		/* restore stack pointer */
 
 .nosavectx:
-	movl	T_LWP(%esi), %ecx
-	pushl	%ecx			/* save fp address for later check */
-
-	/*
-	 * Setup LDT register
-	 */
-	movl 	T_PROCP(%edi), %eax	/* load new proc */
-
-	/* make sure GDT contains the right LDT desc */
-	movl	%gs:CPU_GDT, %ecx
-
-	movl	P_LDT_DESC(%eax), %edx
-	movl	_CONST(P_LDT_DESC+4)(%eax), %eax
-	movl	%edx, ULDT_SEL(%ecx)
-	movl	%eax, _CONST(ULDT_SEL+4)(%ecx)
-	movl	$ULDT_SEL, %edx
-	lldt	%dx
+        /*
+         * Call savepctx if process has installed context ops.
+         */
+	movl	T_PROCP(%esi), %eax	/* %eax = proc */
+	cmpl	$0, P_PCTX(%eax)	/* should current thread savectx? */
+	je	.nosavepctx		/* skip call when zero */
+	pushl	%eax			/* arg = proc pointer */
+	call	savepctx		/* call ctx ops */
+	addl	$4, %esp
+.nosavepctx:	
 
 	/* 
 	 * Temporarily switch to the idle thread's stack
 	 */
 	movl	CPU_IDLE_THREAD(%ebx), %eax 	/* idle thread pointer */
-	popl	%ecx			/* restore pointer to fp structure. */
 
 	/* 
 	 * Set the idle thread as the current thread
 	 */
 	movl	T_SP(%eax), %esp	/* It is safe to set esp */
 	movl	%eax, CPU_THREAD(%ebx)
+	movl	T_LWP(%esi), %ecx	/* load pointer to pcb_fpu */
 	movl	%ecx, %ebx		/* save pcb_fpu pointer in %ebx */
 
 	/* switch in the hat context for the new thread */
@@ -532,6 +530,17 @@
 .norestorectx:
 
 	/*
+	 * Call restorepctx if context ops have been installed for the proc.
+	 */
+	movl	T_PROCP(%edi), %eax
+	cmpl	$0, P_PCTX(%eax)
+	je	.norestorepctx
+	pushl	%eax			/* arg = proc pointer */
+	call	restorepctx
+	addl	$4, %esp		/* restore stack pointer */
+.norestorepctx:
+
+	/*
 	 * If we are resuming an interrupt thread, store a timestamp 
 	 * in the thread structure.
 	 */
@@ -633,21 +642,6 @@
 
 	movq	%gs:CPU_THREAD, %r13	/* %r13 = curthread */
 
-	/*
-	 * Setup LDT register
-	 */
-	movq 	T_PROCP(%r12), %rax	/* load new thread proc */
-
-	/* make sure GDT contains the right LDT desc */
-	movq	%gs:CPU_GDT, %r11
-
-	movq	P_LDT_DESC(%rax), %r10
-	movq	_CONST(P_LDT_DESC+8)(%rax), %rax
-	movq	%r10, ULDT_SEL(%r11)
-	movq	%rax, _CONST(ULDT_SEL+8)(%r11)
-	movl	$ULDT_SEL, %edx
-	lldt	%dx
-
 	/* clean up the fp unit. It might be left enabled */
 	movq	%cr0, %rax
 	testq	$CR0_TS, %rax
@@ -723,21 +717,6 @@
 
 	movl	%gs:CPU_THREAD, %esi	/* %esi = curthread */
 
-	/*
-	 * Setup LDT register
-	 */
-	movl 	T_PROCP(%edi), %ecx	/* load new proc  */
-
-	/* make sure GDT contains the right LDT desc */
-	movl	%gs:CPU_GDT, %eax
-
-	movl	P_LDT_DESC(%ecx), %edx
-	movl	_CONST(P_LDT_DESC+4)(%ecx), %ecx
-	movl	%edx, ULDT_SEL(%eax)
-	movl	%ecx, _CONST(ULDT_SEL+4)(%eax)
-	movl	$ULDT_SEL, %edx
-	lldt	%dx
-
 	/* clean up the fp unit. It might be left enabled */
 	movl	%cr0, %eax
 	testl	$CR0_TS, %eax
--- a/usr/src/uts/intel/ia32/os/archdep.c	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/intel/ia32/os/archdep.c	Fri Jan 06 10:19:31 2006 -0800
@@ -20,7 +20,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -633,7 +633,11 @@
 	}
 
 	/*
-	 * Force it into the LDT in ring 3 for 32-bit processes.
+	 * Force it into the LDT in ring 3 for 32-bit processes, which by
+	 * default do not have an LDT, so that any attempt to use an invalid
+	 * selector will reference the (non-existant) LDT, and cause a #gp fault
+	 * for the process.
+	 *
 	 * 64-bit processes get the null gdt selector since they
 	 * are not allowed to have a private LDT.
 	 */
--- a/usr/src/uts/intel/ia32/os/desctbls.c	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/intel/ia32/os/desctbls.c	Fri Jan 06 10:19:31 2006 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -56,6 +56,7 @@
 #include <sys/cmn_err.h>
 #include <sys/reboot.h>
 #include <sys/kdi.h>
+#include <sys/systm.h>
 
 extern void syscall_int(void);
 
@@ -66,16 +67,6 @@
 user_desc_t	gdt0[NGDT];		/* global descriptor table */
 desctbr_t	gdt0_default_r;
 
-#pragma	align	16(ldt0_default)
-user_desc_t	ldt0_default[MINNLDT];	/* default local descriptor table */
-system_desc_t	ldt0_default_desc;	/* seg descriptor for ldt0_default */
-
-#if defined(__amd64)
-#pragma align	16(ltd0_default64)
-user_desc_t	ldt0_default64[MINNLDT]; /* default LDT for 64-bit apps */
-system_desc_t	ldt0_default64_desc;	/* seg descriptor for ldt0_default64 */
-#endif	/* __amd64 */
-
 #pragma	align	16(idt0)
 gate_desc_t	idt0[NIDT]; 		/* interrupt descriptor table */
 desctbr_t	idt0_default_r;		/* describes idt0 in IDTR format */
@@ -89,6 +80,7 @@
 #endif	/* __i386 */
 
 user_desc_t	zero_udesc;		/* base zero user desc native procs */
+system_desc_t	zero_sdesc;
 
 #if defined(__amd64)
 user_desc_t	zero_u32desc;		/* 32-bit compatibility procs */
@@ -347,18 +339,9 @@
 	    SDP_PAGES, SDP_OP32);
 
 	/*
-	 * LDT descriptor for 64-bit processes
+	 * The 64-bit kernel has no default LDT. By default, the LDT descriptor
+	 * in the GDT is 0.
 	 */
-	set_syssegd((system_desc_t *)&gdt0[GDT_LDT], ldt0_default64,
-	    sizeof (ldt0_default64) - 1, SDT_SYSLDT, SEL_KPL);
-	ldt0_default64_desc = *((system_desc_t *)&gdt0[GDT_LDT]);
-
-	/*
-	 * LDT descriptor for 32-bit processes
-	 */
-	set_syssegd((system_desc_t *)&gdt0[GDT_LDT], ldt0_default,
-	    sizeof (ldt0_default) - 1, SDT_SYSLDT, SEL_KPL);
-	ldt0_default_desc = *((system_desc_t *)&gdt0[GDT_LDT]);
 
 	/*
 	 * Kernel TSS
@@ -446,14 +429,6 @@
 	    SDP_OP32);
 
 	/*
-	 * LDT for current process
-	 */
-	set_syssegd((system_desc_t *)&gdt0[GDT_LDT], ldt0_default,
-	    sizeof (ldt0_default) - 1, SDT_SYSLDT, SEL_KPL);
-
-	ldt0_default_desc = *((system_desc_t *)&gdt0[GDT_LDT]);
-
-	/*
 	 * TSS for T_DBLFLT (double fault) handler
 	 */
 	set_syssegd((system_desc_t *)&gdt0[GDT_DBFLT], &dftss0,
@@ -769,62 +744,18 @@
 
 #endif	/* __i386 */
 
-#if defined(__amd64)
-
-static void
-init_ldt(void)
-{
-	/*
-	 * System calls using call gates from libc.a and libc.so.1
-	 * must cause a #NP fault and be processed in trap().
-	 * Therefore clear the "present" bit in the gate descriptor.
-	 */
-
-	/*
-	 * call gate for libc.a (obsolete)
-	 */
-	set_gatesegd((gate_desc_t *)&ldt0_default[LDT_SYSCALL],
-	    (void (*)(void))&sys_lcall32, KCS_SEL, 1, SDT_SYSCGT, SEL_UPL);
-	((gate_desc_t *)&ldt0_default[LDT_SYSCALL])->sgd_p = 0;
-
-	/*
-	 * i386 call gate for system calls from libc.
-	 */
-	set_gatesegd((gate_desc_t *)&ldt0_default[LDT_ALTSYSCALL],
-	    (void (*)(void))&sys_lcall32, KCS_SEL, 1, SDT_SYSCGT, SEL_UPL);
-	((gate_desc_t *)&ldt0_default[LDT_ALTSYSCALL])->sgd_p = 0;
-
-	wr_ldtr(ULDT_SEL);
-}
-
-#elif defined(__i386)
-
 /*
- * Note that the call gates for system calls ask the hardware to copy exactly
- * one parameter onto the kernel stack for us; the parameter itself is not used.
- * The real reason this is done is to make room for a snapshot of EFLAGS. See
- * comment above sys_call() for details.
+ * The kernel does not deal with LDTs unless a user explicitly creates
+ * one. Under normal circumstances, the LDTR contains 0. Any process attempting
+ * to reference the LDT will therefore cause a #gp. System calls made via the
+ * obsolete lcall mechanism are emulated by the #gp fault handler.
  */
 static void
 init_ldt(void)
 {
-	/*
-	 * call gate for libc.a (obsolete)
-	 */
-	set_gatesegd((gate_desc_t *)&ldt0_default[LDT_SYSCALL],
-	    (void (*)(void))&sys_call, KCS_SEL, 1, SDT_SYSCGT, SEL_UPL);
-
-	/*
-	 * i386 call gate for system calls from libc.
-	 */
-	set_gatesegd((gate_desc_t *)&ldt0_default[LDT_ALTSYSCALL],
-	    (void (*)(void))&sys_call, KCS_SEL, 1, SDT_SYSCGT, SEL_UPL);
-
-	wr_ldtr(ULDT_SEL);
+	wr_ldtr(0);
 }
 
-#endif	/* __i386 */
-
 #if defined(__amd64)
 
 static void
--- a/usr/src/uts/intel/ia32/os/syscall.c	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/intel/ia32/os/syscall.c	Fri Jan 06 10:19:31 2006 -0800
@@ -21,7 +21,7 @@
  */
 
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -834,7 +834,6 @@
 	return (set_errno(ENOSYS));
 }
 
-#ifdef _SYSCALL32_IMPL
 /*
  * Execute a 32-bit system call on behalf of the current thread.
  */
@@ -868,7 +867,6 @@
 	syscall_exit(curthread, (int)ret & 0xffffffffu, (int)(ret >> 32));
 	syscall_mstate(LMS_SYSTEM, LMS_TRAP);
 }
-#endif /* _SYSCALL32_IMPL */
 
 /*
  * Get the arguments to the current system call. See comment atop
--- a/usr/src/uts/intel/ia32/os/sysi86.c	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/intel/ia32/os/sysi86.c	Fri Jan 06 10:19:31 2006 -0800
@@ -20,7 +20,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -64,8 +64,9 @@
 #include <sys/cmn_err.h>
 
 static int setdscr(caddr_t ap);
-static void *setup_ldt(proc_t *pp);
+static void setup_ldt(proc_t *pp);
 static void *ldt_map(proc_t *pp, uint_t seli);
+static void ldt_free(proc_t *pp);
 
 extern void rtcsync(void);
 extern long ggmtl(void);
@@ -305,12 +306,36 @@
 #endif
 }
 
-static void ldt_installctx(kthread_t *, kthread_t *);
+/*
+ * Load LDT register with the current process's LDT.
+ */
+void
+ldt_load(void)
+{
+	/*
+	 */
+	*((system_desc_t *)&CPU->cpu_gdt[GDT_LDT]) = curproc->p_ldt_desc;
+	wr_ldtr(ULDT_SEL);
+}
+
+/*
+ * Store a NULL selector in the LDTR. All subsequent illegal references to
+ * the LDT will result in a #gp.
+ */
+void
+ldt_unload(void)
+{
+	CPU->cpu_gdt[GDT_LDT] = zero_udesc;
+	wr_ldtr(0);
+}
 
 /*ARGSUSED*/
 static void
-ldt_savectx(kthread_t *t)
+ldt_savectx(proc_t *p)
 {
+	ASSERT(p->p_ldt != NULL);
+	ASSERT(p == curproc);
+
 #if defined(__amd64)
 	/*
 	 * The 64-bit kernel must be sure to clear any stale ldt
@@ -332,57 +357,87 @@
 	clr_ldt_sregs();
 #endif
 
+	ldt_unload();
 	cpu_fast_syscall_enable(NULL);
 }
 
+static void
+ldt_restorectx(proc_t *p)
+{
+	ASSERT(p->p_ldt != NULL);
+	ASSERT(p == curproc);
+
+	ldt_load();
+	cpu_fast_syscall_disable(NULL);
+}
+
 /*
- * When a thread with a private LDT execs, fast syscalls must be enabled for the
- * new process image.
+ * When a process with a private LDT execs, fast syscalls must be enabled for
+ * the new process image.
  */
 /* ARGSUSED */
 static void
-ldt_freectx(kthread_t *t, int isexec)
+ldt_freectx(proc_t *p, int isexec)
 {
+	ASSERT(p->p_ldt);
+
 	if (isexec) {
 		kpreempt_disable();
 		cpu_fast_syscall_enable(NULL);
 		kpreempt_enable();
 	}
+
+	/*
+	 * ldt_free() will free the memory used by the private LDT, reset the
+	 * process's descriptor, and re-program the LDTR.
+	 */
+	ldt_free(p);
 }
 
 /*
  * Install ctx op that ensures syscall/sysenter are disabled.
  * See comments below.
  *
- * When a thread with a private LDT creates a new LWP or forks, the new LWP
+ * When a thread with a private LDT forks, the new process
  * must have the LDT context ops installed.
  */
 /* ARGSUSED */
 static void
-ldt_installctx(kthread_t *t, kthread_t *ct)
+ldt_installctx(proc_t *p, proc_t *cp)
 {
-	kthread_t *targ = t;
+	proc_t		*targ = p;
+	kthread_t	*t;
 
 	/*
-	 * If this is a fork or an lwp_create, operate on the child thread.
+	 * If this is a fork, operate on the child process.
 	 */
-	if (ct != NULL)
-		targ = ct;
+	if (cp != NULL) {
+		targ = cp;
+		ldt_dup(p, cp);
+	}
 
-	ASSERT(removectx(targ, NULL, ldt_savectx, cpu_fast_syscall_disable,
-	    ldt_installctx, ldt_installctx, cpu_fast_syscall_enable,
-	    ldt_freectx) == 0);
+	/*
+	 * The process context ops expect the target process as their argument.
+	 */
+	ASSERT(removepctx(targ, targ, ldt_savectx, ldt_restorectx,
+	    ldt_installctx, ldt_savectx, ldt_freectx) == 0);
 
-	installctx(targ, NULL, ldt_savectx, cpu_fast_syscall_disable,
-	    ldt_installctx, ldt_installctx, cpu_fast_syscall_enable,
-	    ldt_freectx);
+	installpctx(targ, targ, ldt_savectx, ldt_restorectx,
+	    ldt_installctx, ldt_savectx, ldt_freectx);
 
 	/*
 	 * We've just disabled fast system call and return instructions; take
 	 * the slow path out to make sure we don't try to use one to return
-	 * back to user.
+	 * back to user. We must set t_post_sys for every thread in the
+	 * process to make sure none of them escape out via fast return.
 	 */
-	targ->t_post_sys = 1;
+
+	mutex_enter(&targ->p_lock);
+	t = targ->p_tlist;
+	do {
+		t->t_post_sys = 1;
+	} while ((t = t->t_forw) != targ->p_tlist);
+	mutex_exit(&targ->p_lock);
 }
 
 static int
@@ -392,7 +447,6 @@
 	ushort_t seli; 		/* selector index */
 	user_desc_t *dscrp;	/* descriptor pointer */
 	proc_t	*pp = ttoproc(curthread);
-	kthread_t *t;
 
 	if (get_udatamodel() == DATAMODEL_LP64)
 		return (EINVAL);
@@ -410,7 +464,7 @@
 	 * check the selector index.
 	 */
 	seli = SELTOIDX(ssd.sel);
-	if (seli >= MAXNLDT || seli <= LDT_UDBASE)
+	if (seli >= MAXNLDT || seli < LDT_UDBASE)
 		return (EINVAL);
 
 	mutex_enter(&pp->p_ldtlock);
@@ -420,10 +474,8 @@
 	 * private LDT for it.
 	 */
 	if (pp->p_ldt == NULL) {
-		if (setup_ldt(pp) == NULL) {
-			mutex_exit(&pp->p_ldtlock);
-			return (ENOMEM);
-		}
+		kpreempt_disable();
+		setup_ldt(pp);
 
 		/*
 		 * Now that this process has a private LDT, the use of
@@ -431,26 +483,21 @@
 		 * is forbidden for this processes because they destroy
 		 * the contents of %cs and %ss segment registers.
 		 *
-		 * Explicity disable them here and add context handlers
-		 * to all lwps in the process. Note that disabling
+		 * Explicity disable them here and add a context handler
+		 * to the process. Note that disabling
 		 * them here means we can't use sysret or sysexit on
 		 * the way out of this system call - so we force this
 		 * thread to take the slow path (which doesn't make use
 		 * of sysenter or sysexit) back out.
 		 */
 
-		mutex_enter(&pp->p_lock);
-		t = pp->p_tlist;
-		do {
-			ldt_installctx(t, NULL);
-		} while ((t = t->t_forw) != pp->p_tlist);
-		mutex_exit(&pp->p_lock);
+		ldt_installctx(pp, NULL);
 
-		kpreempt_disable();
 		cpu_fast_syscall_disable(NULL);
-		kpreempt_enable();
+
 		ASSERT(curthread->t_post_sys != 0);
 		wr_ldtr(ULDT_SEL);
+		kpreempt_enable();
 	}
 
 	if (ldt_map(pp, seli) == NULL) {
@@ -604,9 +651,9 @@
 
 /*
  * Allocate a private LDT for this process and initialize it with the
- * default entries. Returns 0 for errors, pointer to LDT for success.
+ * default entries.
  */
-static void *
+void
 setup_ldt(proc_t *pp)
 {
 	user_desc_t *ldtp;	/* descriptor pointer */
@@ -620,18 +667,11 @@
 	/*
 	 * Allocate the minimum number of physical pages for LDT.
 	 */
-	if (segkmem_xalloc(NULL, ldtp, MINNLDT * sizeof (user_desc_t),
-	    VM_SLEEP, 0, segkmem_page_create, NULL) == NULL) {
-		vmem_free(heap_arena, ldtp, ptob(npages));
-		return (0);
-	}
+	(void) segkmem_xalloc(NULL, ldtp, MINNLDT * sizeof (user_desc_t),
+	    VM_SLEEP, 0, segkmem_page_create, NULL);
+
 	bzero(ldtp, ptob(btopr(MINNLDT * sizeof (user_desc_t))));
 
-	/*
-	 * Copy the default LDT entries into the new table.
-	 */
-	bcopy(ldt0_default, ldtp, MINNLDT * sizeof (user_desc_t));
-
 	kpreempt_disable();
 
 	/* Update proc structure. XXX - need any locks here??? */
@@ -645,22 +685,6 @@
 		*((system_desc_t *)&CPU->cpu_gdt[GDT_LDT]) = pp->p_ldt_desc;
 
 	kpreempt_enable();
-
-	return (ldtp);
-}
-
-/*
- * Load LDT register with the current process's LDT.
- */
-void
-ldt_load(void)
-{
-	proc_t *p = curthread->t_procp;
-
-	ASSERT(curthread->t_preempt != 0);
-
-	*((system_desc_t *)&CPU->cpu_gdt[GDT_LDT]) = p->p_ldt_desc;
-	wr_ldtr(ULDT_SEL);
 }
 
 /*
@@ -691,11 +715,8 @@
 		if (!on_trap(&otd, OT_DATA_ACCESS))
 			(void) *(volatile int *)page;	/* peek at the page */
 		else {		/* Allocate a physical page */
-			if (segkmem_xalloc(NULL, page, PAGESIZE, VM_SLEEP, 0,
-			    segkmem_page_create, NULL) == NULL) {
-				no_trap();
-				return (NULL);
-			}
+			(void) segkmem_xalloc(NULL, page, PAGESIZE, VM_SLEEP, 0,
+			    segkmem_page_create, NULL);
 			bzero(page, PAGESIZE);
 		}
 		no_trap();
@@ -719,7 +740,7 @@
 /*
  * Free up the kernel memory used for LDT of this process.
  */
-void
+static void
 ldt_free(proc_t *pp)
 {
 	on_trap_data_t otd;
@@ -747,9 +768,11 @@
 	    ptob(btopr(MAXNLDT * sizeof (user_desc_t))));
 	kpreempt_disable();
 	pp->p_ldt = NULL;
-	pp->p_ldt_desc = ldt0_default_desc;
+	pp->p_ldt_desc = zero_sdesc;
+	pp->p_ldtlimit = 0;
+
 	if (pp == curproc)
-		ldt_load();
+		ldt_unload();
 	kpreempt_enable();
 	mutex_exit(&pp->p_ldtlock);
 }
@@ -757,7 +780,7 @@
 /*
  * On fork copy new ldt for child.
  */
-int
+void
 ldt_dup(proc_t *pp, proc_t *cp)
 {
 	on_trap_data_t otd;
@@ -765,14 +788,9 @@
 	volatile caddr_t addr, caddr;
 	int	minsize;
 
-	if (pp->p_ldt == NULL) {
-		cp->p_ldt_desc = ldt0_default_desc;
-		return (0);
-	}
+	ASSERT(pp->p_ldt);
 
-	if (setup_ldt(cp) == NULL) {
-		return (ENOMEM);
-	}
+	setup_ldt(cp);
 
 	mutex_enter(&pp->p_ldtlock);
 	cp->p_ldtlimit = pp->p_ldtlimit;
@@ -789,19 +807,12 @@
 			(void) *(volatile int *)addr; /* peek at the address */
 			/* allocate a page if necessary */
 			if (caddr >= ((caddr_t)cp->p_ldt + minsize)) {
-				if (segkmem_xalloc(NULL, caddr, PAGESIZE,
-				    VM_SLEEP, 0, segkmem_page_create, NULL) ==
-				    NULL) {
-					no_trap();
-					ldt_free(cp);
-					mutex_exit(&pp->p_ldtlock);
-					return (ENOMEM);
-				}
+				(void) segkmem_xalloc(NULL, caddr, PAGESIZE,
+				    VM_SLEEP, 0, segkmem_page_create, NULL);
 			}
 			bcopy(addr, caddr, PAGESIZE);
 		}
 	}
 	no_trap();
 	mutex_exit(&pp->p_ldtlock);
-	return (0);
 }
--- a/usr/src/uts/intel/sys/segments.h	Fri Jan 06 09:41:00 2006 -0800
+++ b/usr/src/uts/intel/sys/segments.h	Fri Jan 06 10:19:31 2006 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -528,13 +528,10 @@
 extern	desctbr_t	idt0_default_reg;
 #pragma	align	16(gdt0)
 extern	user_desc_t	gdt0[NGDT];
-#pragma	align	16(ldt0_default)
-extern	user_desc_t	ldt0_default[MINNLDT];
-extern	system_desc_t	ldt0_default_desc;
-#pragma align	16(ldt0_default64)
-extern user_desc_t	ldt0_default64[MINNLDT];
-extern system_desc_t	ldt0_default64_desc;
+
 extern user_desc_t	zero_udesc;
+extern system_desc_t	zero_sdesc;
+
 #if defined(__amd64)
 extern user_desc_t	zero_u32desc;
 #endif