summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorrab <none@none>2006-01-06 10:19:31 -0800
committerrab <none@none>2006-01-06 10:19:31 -0800
commit0baeff3d96eae184e775c1064f1836090446a7bf (patch)
tree223a82fa3266e75588aace66980f22165d83fcff /usr/src
parentd045b9872121ef87817d5d01968d80cc01574bc8 (diff)
downloadillumos-gate-0baeff3d96eae184e775c1064f1836090446a7bf.tar.gz
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>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/uts/common/Makefile.files3
-rw-r--r--usr/src/uts/common/disp/thread.c14
-rw-r--r--usr/src/uts/common/os/exec.c35
-rw-r--r--usr/src/uts/common/os/exit.c32
-rw-r--r--usr/src/uts/common/os/fork.c13
-rw-r--r--usr/src/uts/common/os/lwp.c18
-rw-r--r--usr/src/uts/common/os/proc.c155
-rw-r--r--usr/src/uts/common/sys/proc.h26
-rw-r--r--usr/src/uts/i86pc/ml/mpcore.s10
-rw-r--r--usr/src/uts/i86pc/ml/offsets.in3
-rw-r--r--usr/src/uts/i86pc/os/mlsetup.c17
-rw-r--r--usr/src/uts/i86pc/os/trap.c39
-rw-r--r--usr/src/uts/i86pc/sys/machcpuvar.h4
-rw-r--r--usr/src/uts/intel/ia32/ml/swtch.s107
-rw-r--r--usr/src/uts/intel/ia32/os/archdep.c8
-rw-r--r--usr/src/uts/intel/ia32/os/desctbls.c89
-rw-r--r--usr/src/uts/intel/ia32/os/syscall.c4
-rw-r--r--usr/src/uts/intel/ia32/os/sysi86.c191
-rw-r--r--usr/src/uts/intel/sys/segments.h11
19 files changed, 433 insertions, 346 deletions
diff --git a/usr/src/uts/common/Makefile.files b/usr/src/uts/common/Makefile.files
index b51fd395d9..d614acf224 100644
--- a/usr/src/uts/common/Makefile.files
+++ b/usr/src/uts/common/Makefile.files
@@ -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 @@ GENUNIX_OBJS += \
priocntl.o \
priv.o \
priv_const.o \
+ proc.o \
procset.o \
processor_bind.o \
processor_info.o \
diff --git a/usr/src/uts/common/disp/thread.c b/usr/src/uts/common/disp/thread.c
index 6cc6b08098..d9dfeb4993 100644
--- a/usr/src/uts/common/disp/thread.c
+++ b/usr/src/uts/common/disp/thread.c
@@ -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 @@ thread_exit()
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 @@ thread_free(kthread_t *t)
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 @@ reapq_add(kthread_t *t)
}
/*
- * Install a device context for the current thread
+ * Install thread context ops for the current thread.
*/
void
installctx(
@@ -900,8 +904,8 @@ installctx(
}
/*
- * 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 @@ exitctx(kthread_t *t)
/*
* 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)
diff --git a/usr/src/uts/common/os/exec.c b/usr/src/uts/common/os/exec.c
index 004efdd5ed..e7a44db1d8 100644
--- a/usr/src/uts/common/os/exec.c
+++ b/usr/src/uts/common/os/exec.c
@@ -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_hwcap = 0; /* auxv AT_SUN_HWCAP value; determined on the fly */
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 @@ exec_common(const char *fname, const char **argp, const char **envp)
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 @@ exec_common(const char *fname, const char **argp, const char **envp)
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);
diff --git a/usr/src/uts/common/os/exit.c b/usr/src/uts/common/os/exit.c
index 83a6978064..7fcba5d9ec 100644
--- a/usr/src/uts/common/os/exit.c
+++ b/usr/src/uts/common/os/exit.c
@@ -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 @@ proc_exit(int why, int what)
} 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 @@ proc_exit(int why, int what)
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.
diff --git a/usr/src/uts/common/os/fork.c b/usr/src/uts/common/os/fork.c
index 8c8a4e984a..4171c0b122 100644
--- a/usr/src/uts/common/os/fork.c
+++ b/usr/src/uts/common/os/fork.c
@@ -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 @@ cfork(int isvfork, int isfork1)
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 @@ newproc(void (*pc)(), caddr_t arg, id_t cid, int pri, struct contract **ct)
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;
diff --git a/usr/src/uts/common/os/lwp.c b/usr/src/uts/common/os/lwp.c
index df3f6767e8..dbccf77b9e 100644
--- a/usr/src/uts/common/os/lwp.c
+++ b/usr/src/uts/common/os/lwp.c
@@ -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 @@ lwp_exit(void)
* 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_exit(void)
lwp_pcb_exit();
- if (t->t_ctx != NULL)
- exitctx(t);
-
t->t_state = TS_ZOMB;
swtch_from_zombie();
/* never returns */
@@ -1617,12 +1620,7 @@ forklwp(klwp_t *lwp, proc_t *cp, id_t lwpid)
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);
diff --git a/usr/src/uts/common/os/proc.c b/usr/src/uts/common/os/proc.c
new file mode 100644
index 0000000000..83563f34a9
--- /dev/null
+++ b/usr/src/uts/common/os/proc.c
@@ -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));
+ }
+}
diff --git a/usr/src/uts/common/sys/proc.h b/usr/src/uts/common/sys/proc.h
index 1049c645e4..eb1463d88d 100644
--- a/usr/src/uts/common/sys/proc.h
+++ b/usr/src/uts/common/sys/proc.h
@@ -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 @@ typedef struct lwpent {
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 @@ typedef struct proc {
* 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_inc(uid_t, zoneid_t);
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 forkctx(kthread_t *, kthread_t *);
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);
diff --git a/usr/src/uts/i86pc/ml/mpcore.s b/usr/src/uts/i86pc/ml/mpcore.s
index cf64091917..1c1b84df15 100644
--- a/usr/src/uts/i86pc/ml/mpcore.s
+++ b/usr/src/uts/i86pc/ml/mpcore.s
@@ -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 @@ kernel_cs_code:
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 @@ kernel_cs_code:
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 @@ kernel_cs_code:
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 @@ kernel_cs_code:
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 */
diff --git a/usr/src/uts/i86pc/ml/offsets.in b/usr/src/uts/i86pc/ml/offsets.in
index 4a1959a822..13ec19da05 100644
--- a/usr/src/uts/i86pc/ml/offsets.in
+++ b/usr/src/uts/i86pc/ml/offsets.in
@@ -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 @@ proc PROCSIZE
p_ldt
p_ldt_desc
p_model
+ p_pctx
p_agenttp
_kthread THREAD_SIZE
diff --git a/usr/src/uts/i86pc/os/mlsetup.c b/usr/src/uts/i86pc/os/mlsetup.c
index 5118e61495..02326001f2 100644
--- a/usr/src/uts/i86pc/os/mlsetup.c
+++ b/usr/src/uts/i86pc/os/mlsetup.c
@@ -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 @@ mlsetup(struct regs *rp)
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.
diff --git a/usr/src/uts/i86pc/os/trap.c b/usr/src/uts/i86pc/os/trap.c
index 7016be0cb2..2287b59493 100644
--- a/usr/src/uts/i86pc/os/trap.c
+++ b/usr/src/uts/i86pc/os/trap.c
@@ -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 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid)
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) {
+
+ /*
+ * 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.
+ */
+
/*
- * System calls via the call gate come in through
- * not-present traps.
- *
* 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 @@ trap(struct regs *rp, caddr_t addr, processorid_t cpuid)
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
diff --git a/usr/src/uts/i86pc/sys/machcpuvar.h b/usr/src/uts/i86pc/sys/machcpuvar.h
index 50241f2303..9e355d4b49 100644
--- a/usr/src/uts/i86pc/sys/machcpuvar.h
+++ b/usr/src/uts/i86pc/sys/machcpuvar.h
@@ -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 @@ struct machcpu {
/* 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 */
diff --git a/usr/src/uts/intel/ia32/ml/swtch.s b/usr/src/uts/intel/ia32/ml/swtch.s
index 888d8a45ee..48103f954f 100644
--- a/usr/src/uts/intel/ia32/ml/swtch.s
+++ b/usr/src/uts/intel/ia32/ml/swtch.s
@@ -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 @@ resume(kthread_t *t)
call savectx /* call ctx ops */
.nosavectx:
- /*
- * Setup LDT register
- */
- movq T_PROCP(%r12), %rax /* load new thread proc */
+ /*
+ * 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 */
- /* make sure GDT contains the right LDT desc */
- movq %gs:CPU_GDT, %r11
+ movq %r14, %rdi /* arg = proc pointer */
+ call savepctx /* call ctx ops */
+.nosavepctx:
- 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
-
- /*
+ /*
* Temporarily switch to the idle thread's stack
*/
movq CPU_IDLE_THREAD(%r15), %rax /* idle thread pointer */
@@ -329,10 +325,19 @@ resume(kthread_t *t)
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 @@ resume_return:
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 @@ resume_return:
.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 @@ resume_from_zombie(kthread_t *t)
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 @@ resume_from_zombie_return:
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
diff --git a/usr/src/uts/intel/ia32/os/archdep.c b/usr/src/uts/intel/ia32/os/archdep.c
index 943c713966..5a94720495 100644
--- a/usr/src/uts/intel/ia32/os/archdep.c
+++ b/usr/src/uts/intel/ia32/os/archdep.c
@@ -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 @@ fix_segreg(greg_t sr, model_t datamodel)
}
/*
- * 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.
*/
diff --git a/usr/src/uts/intel/ia32/os/desctbls.c b/usr/src/uts/intel/ia32/os/desctbls.c
index 59b8d001de..4ce5312548 100644
--- a/usr/src/uts/intel/ia32/os/desctbls.c
+++ b/usr/src/uts/intel/ia32/os/desctbls.c
@@ -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 @@ extern void syscall_int(void);
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 @@ struct tss dftss0; /* #DF double-fault exception */
#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 @@ init_gdt(void)
SDP_PAGES, SDP_OP32);
/*
- * LDT descriptor for 64-bit processes
- */
- 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
+ * 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_default,
- sizeof (ldt0_default) - 1, SDT_SYSLDT, SEL_KPL);
- ldt0_default_desc = *((system_desc_t *)&gdt0[GDT_LDT]);
/*
* Kernel TSS
@@ -446,14 +429,6 @@ init_gdt(void)
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 @@ init_idt(void)
#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
diff --git a/usr/src/uts/intel/ia32/os/syscall.c b/usr/src/uts/intel/ia32/os/syscall.c
index b53c04ff92..8176ddb908 100644
--- a/usr/src/uts/intel/ia32/os/syscall.c
+++ b/usr/src/uts/intel/ia32/os/syscall.c
@@ -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 @@ nosys()
return (set_errno(ENOSYS));
}
-#ifdef _SYSCALL32_IMPL
/*
* Execute a 32-bit system call on behalf of the current thread.
*/
@@ -868,7 +867,6 @@ dosyscall(void)
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
diff --git a/usr/src/uts/intel/ia32/os/sysi86.c b/usr/src/uts/intel/ia32/os/sysi86.c
index 24f3dec349..08b48234f7 100644
--- a/usr/src/uts/intel/ia32/os/sysi86.c
+++ b/usr/src/uts/intel/ia32/os/sysi86.c
@@ -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 @@ ssd_to_sgd(struct ssd *ssd, gate_desc_t *sgd)
#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 @@ ldt_savectx(kthread_t *t)
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 @@ setdscr(caddr_t ap)
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 @@ setdscr(caddr_t ap)
* 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 @@ setdscr(caddr_t ap)
* 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 @@ setdscr(caddr_t ap)
* 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 @@ setdscr(caddr_t ap)
/*
* 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,17 +667,10 @@ setup_ldt(proc_t *pp)
/*
* 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);
- }
- bzero(ldtp, ptob(btopr(MINNLDT * sizeof (user_desc_t))));
+ (void) segkmem_xalloc(NULL, ldtp, MINNLDT * sizeof (user_desc_t),
+ VM_SLEEP, 0, segkmem_page_create, NULL);
- /*
- * Copy the default LDT entries into the new table.
- */
- bcopy(ldt0_default, ldtp, MINNLDT * sizeof (user_desc_t));
+ bzero(ldtp, ptob(btopr(MINNLDT * sizeof (user_desc_t))));
kpreempt_disable();
@@ -645,22 +685,6 @@ setup_ldt(proc_t *pp)
*((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 @@ ldt_map(proc_t *pp, uint_t seli)
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 @@ ldt_map(proc_t *pp, uint_t seli)
/*
* 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 @@ ldt_free(proc_t *pp)
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 @@ ldt_free(proc_t *pp)
/*
* 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 @@ ldt_dup(proc_t *pp, proc_t *cp)
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 @@ ldt_dup(proc_t *pp, proc_t *cp)
(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);
}
diff --git a/usr/src/uts/intel/sys/segments.h b/usr/src/uts/intel/sys/segments.h
index 0578a6f7fd..3045d533a2 100644
--- a/usr/src/uts/intel/sys/segments.h
+++ b/usr/src/uts/intel/sys/segments.h
@@ -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 gate_desc_t idt0[NIDT];
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