Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/i386 Move the user-set LDT out of the PCB and into ...



details:   https://anonhg.NetBSD.org/src/rev/58f25706b0c9
branches:  trunk
changeset: 472931:58f25706b0c9
user:      thorpej <thorpej%NetBSD.org@localhost>
date:      Wed May 12 19:28:28 1999 +0000

description:
Move the user-set LDT out of the PCB and into the pmap.  Applications
which set the LDT and share VM space (e.g. new versions of WINE) expect
the LDT to be logically coupled to the address space.  Use the new pmap_fork()
interface to copy non-shared user-set LDTs when the address space is forked.

diffstat:

 sys/arch/i386/i386/gdt.c         |   40 +++++++++++---
 sys/arch/i386/i386/machdep.c     |    5 +-
 sys/arch/i386/i386/pmap.c        |   99 +++++++++++++++++++++++++++++++++++++-
 sys/arch/i386/i386/pmap.new.c    |  103 +++++++++++++++++++++++++++++++++++++-
 sys/arch/i386/i386/sys_machdep.c |   72 +++++++++++++--------------
 sys/arch/i386/i386/vm_machdep.c  |   40 ++++----------
 sys/arch/i386/include/gdt.h      |    8 +-
 sys/arch/i386/include/pcb.h      |    6 +-
 sys/arch/i386/include/pmap.h     |   18 ++++++-
 sys/arch/i386/include/pmap.new.h |   18 ++++++-
 10 files changed, 317 insertions(+), 92 deletions(-)

diffs (truncated from 795 to 300 lines):

diff -r 021dbd0ec059 -r 58f25706b0c9 sys/arch/i386/i386/gdt.c
--- a/sys/arch/i386/i386/gdt.c  Wed May 12 19:11:23 1999 +0000
+++ b/sys/arch/i386/i386/gdt.c  Wed May 12 19:28:28 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: gdt.c,v 1.16 1999/03/24 05:51:00 mrg Exp $     */
+/*     $NetBSD: gdt.c,v 1.17 1999/05/12 19:28:28 thorpej Exp $ */
 
 /*-
  * Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
@@ -117,10 +117,12 @@
 {
        struct proc *p;
        struct pcb *pcb;
+       pmap_t pmap;
        int slot = NGDT, oslot;
 
        for (p = allproc.lh_first; p != 0; p = p->p_list.le_next) {
                pcb = &p->p_addr->u_pcb;
+               pmap = p->p_vmspace->vm_map.pmap;
                oslot = IDXSEL(pcb->pcb_tss_sel);
                if (oslot >= gdt_count) {
                        while (gdt[slot].sd.sd_type != SDT_SYSNULL) {
@@ -131,7 +133,8 @@
                        gdt[oslot].gd.gd_type = SDT_SYSNULL;
                        pcb->pcb_tss_sel = GSEL(slot, SEL_KPL);
                }
-               oslot = IDXSEL(pcb->pcb_ldt_sel);
+               simple_lock(&pmap->pm_lock);
+               oslot = IDXSEL(pmap->pm_ldt_sel);
                if (oslot >= gdt_count) {
                        while (gdt[slot].sd.sd_type != SDT_SYSNULL) {
                                if (++slot >= gdt_count)
@@ -139,8 +142,20 @@
                        }
                        gdt[slot] = gdt[oslot];
                        gdt[oslot].gd.gd_type = SDT_SYSNULL;
-                       pcb->pcb_ldt_sel = GSEL(slot, SEL_KPL);
+                       pmap->pm_ldt_sel = GSEL(slot, SEL_KPL);
+
+                       /* Refresh the PCB. */
+                       pcb->pcb_pmap = pmap;
+                       pcb->pcb_ldt_sel = pmap->pm_ldt_sel;
+
+                       /*
+                        * XXX We don't need to re-load the LDT on this
+                        * XXX processor, but if this pmap/pcb is in use
+                        * XXX on _another_ processor, we need to notify
+                        * XXX it!
+                        */
                }
+               simple_unlock(&pmap->pm_lock);
        }
        for (; slot < gdt_count; slot++)
                if (gdt[slot].gd.gd_type == SDT_SYSNULL)
@@ -290,8 +305,8 @@
 }
 
 void
-ldt_alloc(pcb, ldt, len)
-       struct pcb *pcb;
+ldt_alloc(pmap, ldt, len)
+       struct pmap *pmap;
        union descriptor *ldt;
        size_t len;
 {
@@ -299,13 +314,20 @@
 
        slot = gdt_get_slot();
        setsegment(&gdt[slot].sd, ldt, len - 1, SDT_SYSLDT, SEL_KPL, 0, 0);
-       pcb->pcb_ldt_sel = GSEL(slot, SEL_KPL);
+       simple_lock(&pmap->pm_lock);
+       pmap->pm_ldt_sel = GSEL(slot, SEL_KPL);
+       simple_unlock(&pmap->pm_lock);
 }
 
 void
-ldt_free(pcb)
-       struct pcb *pcb;
+ldt_free(pmap)
+       struct pmap *pmap;
 {
+       int slot;
 
-       gdt_put_slot(IDXSEL(pcb->pcb_ldt_sel));
+       simple_lock(&pmap->pm_lock);
+       slot = IDXSEL(pmap->pm_ldt_sel);
+       simple_unlock(&pmap->pm_lock);
+
+       gdt_put_slot(slot);
 }
diff -r 021dbd0ec059 -r 58f25706b0c9 sys/arch/i386/i386/machdep.c
--- a/sys/arch/i386/i386/machdep.c      Wed May 12 19:11:23 1999 +0000
+++ b/sys/arch/i386/i386/machdep.c      Wed May 12 19:28:28 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: machdep.c,v 1.352 1999/04/26 22:46:45 thorpej Exp $    */
+/*     $NetBSD: machdep.c,v 1.353 1999/05/12 19:28:29 thorpej Exp $    */
 
 /*-
  * Copyright (c) 1996, 1997, 1998 The NetBSD Foundation, Inc.
@@ -1664,8 +1664,7 @@
 #endif
 
 #ifdef USER_LDT
-       if (pcb->pcb_flags & PCB_USER_LDT)
-               i386_user_cleanup(pcb);
+       pmap_ldt_cleanup(p);
 #endif
 
        p->p_md.md_flags &= ~MDP_USEDFPU;
diff -r 021dbd0ec059 -r 58f25706b0c9 sys/arch/i386/i386/pmap.c
--- a/sys/arch/i386/i386/pmap.c Wed May 12 19:11:23 1999 +0000
+++ b/sys/arch/i386/i386/pmap.c Wed May 12 19:28:28 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.c,v 1.68 1999/03/27 05:57:04 mycroft Exp $        */
+/*     $NetBSD: pmap.c,v 1.69 1999/05/12 19:28:29 thorpej Exp $        */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -114,6 +114,7 @@
  */
 
 #include "opt_cputype.h"
+#include "opt_user_ldt.h"
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -131,6 +132,7 @@
 
 #include <dev/isa/isareg.h>
 #include <machine/isa_machdep.h>
+#include <machine/gdt.h>
 
 #ifdef DEBUG
 void   pmap_pvdump __P((paddr_t pa));
@@ -735,6 +737,11 @@
        pmap->pm_pdir[PTDPTDI] =
            pmap_extract(pmap_kernel(), (vaddr_t)pmap->pm_pdir) | PG_V | PG_KW;
 
+       /* init the LDT */
+       pmap->pm_ldt = NULL;
+       pmap->pm_ldt_len = 0;
+       pmap->pm_ldt_sel = GSEL(GLDT_SEL, SEL_KPL);
+
        pmap->pm_count = 1;
        simple_lock_init(&pmap->pm_lock);
 }
@@ -789,6 +796,18 @@
 #endif
 
        uvm_km_free(kernel_map, (vaddr_t)pmap->pm_pdir, NBPG);
+
+#ifdef USER_LDT
+       if (pmap->pm_flags & PMF_USER_LDT) {
+               /*
+                * No need to switch the LDT; this address space
+                * is gone, nothing is using it.
+                */
+               ldt_free(pmap);
+               uvm_km_free(kernel_map, (vaddr_t)pmap->pm_ldt,
+                   pmap->pm_ldt_len * sizeof(union descriptor));
+       }
+#endif
 }
 
 /*
@@ -812,6 +831,80 @@
        simple_unlock(&pmap->pm_lock);
 }
 
+#if defined(PMAP_FORK)
+/*
+ * pmap_fork:
+ *
+ *     Perform any necessary data structure manipulation when
+ *     a VM space is forked.
+ */
+void
+pmap_fork(pmap1, pmap2)
+       pmap_t pmap1, pmap2;
+{
+
+       simple_lock(&pmap1->pm_lock);
+       simple_lock(&pmap2->pm_lock);
+
+#ifdef USER_LDT
+       /* Copy the LDT, if necessary. */
+       if (pmap1->pm_flags & PMF_USER_LDT) {
+               union descriptor *new_ldt;
+               size_t len;
+
+               len = pmap1->pm_ldt_len * sizeof(union descriptor);
+               new_ldt = (union descriptor *)uvm_km_alloc(kernel_map, len);
+               memcpy(new_ldt, pmap1->pm_ldt, len);
+               pmap2->pm_ldt = new_ldt;
+               pmap2->pm_ldt_len = pmap1->pm_ldt_len;
+               pmap2->pm_flags |= PMF_USER_LDT;
+               ldt_alloc(pmap2, new_ldt, len);
+       }
+#endif /* USER_LDT */
+
+       simple_unlock(&pmap2->pm_lock);
+       simple_unlock(&pmap1->pm_lock);
+}
+#endif /* PMAP_FORK */
+
+#ifdef USER_LDT
+/*
+ * pmap_ldt_cleanup:
+ *
+ *     If the pmap has a local LDT, deallocate it, and restore the
+ *     default.
+ */
+void
+pmap_ldt_cleanup(p)
+       struct proc *p;
+{
+       struct pcb *pcb = &p->p_addr->u_pcb;
+       pmap_t pmap = p->p_vmspace->vm_map.pmap;
+       union descriptor *old_ldt = NULL;
+       size_t len = 0;
+
+       simple_lock(&pmap->pm_lock);
+
+       if (pmap->pm_flags & PMF_USER_LDT) {
+               ldt_free(pmap);
+               pmap->pm_ldt_sel = GSEL(GLDT_SEL, SEL_KPL);
+               pcb->pcb_ldt_sel = pmap->pm_ldt_sel;
+               if (pcb == curpcb)
+                       lldt(pcb->pcb_ldt_sel);
+               old_ldt = pmap->pm_ldt;
+               len = pmap->pm_ldt_len * sizeof(union descriptor);
+               pmap->pm_ldt = NULL;
+               pmap->pm_ldt_len = 0;
+               pmap->pm_flags &= ~PMF_USER_LDT;
+       }
+
+       simple_unlock(&pmap->pm_lock);
+
+       if (old_ldt != NULL)
+               uvm_km_free(kernel_map, (vaddr_t)old_ldt, len);
+}
+#endif /* USER_LDT */
+
 /*
  * pmap_activate:
  *
@@ -824,9 +917,13 @@
        struct pcb *pcb = &p->p_addr->u_pcb;
        pmap_t pmap = p->p_vmspace->vm_map.pmap;
 
+       pcb->pcb_pmap = pmap;
+       pcb->pcb_ldt_sel = pmap->pm_ldt_sel;
        pcb->pcb_cr3 = pmap_extract(pmap_kernel(), (vaddr_t)pmap->pm_pdir);
        if (p == curproc)
                lcr3(pcb->pcb_cr3);
+       if (pcb == curpcb)
+               lldt(pcb->pcb_ldt_sel);
 }
 
 /*
diff -r 021dbd0ec059 -r 58f25706b0c9 sys/arch/i386/i386/pmap.new.c
--- a/sys/arch/i386/i386/pmap.new.c     Wed May 12 19:11:23 1999 +0000
+++ b/sys/arch/i386/i386/pmap.new.c     Wed May 12 19:28:28 1999 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.new.c,v 1.25 1999/05/05 05:21:13 chs Exp $        */
+/*     $NetBSD: pmap.new.c,v 1.26 1999/05/12 19:28:29 thorpej Exp $    */
 
 /*
  *
@@ -60,6 +60,7 @@
  */
 
 #include "opt_cputype.h"
+#include "opt_user_ldt.h"
 #include "opt_lockdebug.h"
 #include "opt_multiprocessor.h"
 
@@ -78,6 +79,7 @@
 
 #include <machine/cpu.h>
 #include <machine/specialreg.h>
+#include <machine/gdt.h>
 
 #include <dev/isa/isareg.h>
 #include <machine/isa_machdep.h>
@@ -1786,6 +1788,7 @@
   pmap->pm_stats.wired_count = 0;
   pmap->pm_stats.resident_count = 1;   /* count the PDP allocd below */
   pmap->pm_ptphint = NULL;
+  pmap->pm_flags = 0;
 
   /* allocate PDP */
   pmap->pm_pdir = (pd_entry_t *) uvm_km_alloc(kernel_map, NBPG);
@@ -1800,6 +1803,11 @@
   /* put in recursive PDE to map the PTEs */
   pmap->pm_pdir[PDSLOT_PTE] = pmap->pm_pdirpa | PG_V | PG_KW;
 
+  /* init the LDT */
+  pmap->pm_ldt = NULL;
+  pmap->pm_ldt_len = 0;



Home | Main Index | Thread Index | Old Index