Hi,

The attached patch is to sys/i386/* code.  It's basically 50%, albeit the
easy 50%, of the Junior Kernel Hacker task from jhb last month.  I
finished it and tested awhile ago (~1 month) but my current box died.  My
current box is still dead, so I've yet to test it any further, but Peter
Wemm and jhb both looked at it and said it looked "ok" and to get people
to test it.

The attached patch is for current from 9/19/01 -- Yes, Im sorry, this
sucks.  I have a 4.3 release CD here so Im going to have to use that to
rebuild a box back to current (FTP installs with 4.4 floppies have really
sucked).  If you're willing to test and don't mind this patch, thanks.  If
you are willing to test and want a newer patch, let me know and I'll get
you one tonight or tomorrow.

Btw, the patch is also located at
http://www.watson.org/~arr/fbsd-patches/ldt-2-mdproc.diff

Cheers,
Andrew

*-------------.................................................
| Andrew R. Reiter 
| [EMAIL PROTECTED]
| "It requires a very unusual mind
|   to undertake the analysis of the obvious" -- A.N. Whitehead
--- include/pcb.h.orig  Wed Sep 19 02:07:48 2001
+++ include/pcb.h       Wed Sep 19 02:08:37 2001
@@ -61,7 +61,6 @@
        int     pcb_dr6;
        int     pcb_dr7;
 
-       struct  pcb_ldt *pcb_ldt;       /* per process (user) LDT */
        union   savefpu pcb_save;
        u_char  pcb_flags;
 #define        FP_SOFTFP       0x01    /* process using software fltng pnt emulator 
*/
--- include/pcb_ext.h.orig      Wed Sep 19 02:07:54 2001
+++ include/pcb_ext.h   Wed Sep 19 02:10:37 2001
@@ -43,20 +43,9 @@
        struct  vm86_kernel ext_vm86;   /* vm86 area */
 };
 
-struct pcb_ldt {
-       caddr_t ldt_base;
-       int     ldt_len;
-       int     ldt_refcnt;
-       u_long  ldt_active;
-       struct  segment_descriptor ldt_sd;
-};
-
 #ifdef _KERNEL
 
 int i386_extend_pcb __P((struct thread *));
-void set_user_ldt __P((struct pcb *));
-struct pcb_ldt *user_ldt_alloc __P((struct pcb *, int));
-void user_ldt_free __P((struct pcb *));
 
 #endif
 
--- include/proc.h.orig Wed Sep 19 02:07:59 2001
+++ include/proc.h      Wed Sep 19 03:28:55 2001
@@ -38,6 +38,15 @@
 #define        _MACHINE_PROC_H_
 
 #include <machine/globals.h>
+#include <machine/segments.h>
+
+struct proc_ldt {
+        caddr_t ldt_base;
+        int     ldt_len;
+        int     ldt_refcnt;
+        u_long  ldt_active;
+        struct  segment_descriptor ldt_sd;
+};
 
 /*
  * Machine-dependent part of the proc structure for i386.
@@ -46,6 +55,15 @@
 };
 
 struct mdproc {
+       struct proc_ldt *md_ldt;        /* per-process ldt */
 };
+
+#ifdef _KERNEL
+
+void   set_user_ldt __P((struct mdproc *));
+struct         proc_ldt *user_ldt_alloc __P((struct mdproc *, int));
+void   user_ldt_free __P((struct thread *));
+
+#endif /* _KERNEL */
 
 #endif /* !_MACHINE_PROC_H_ */
--- i386/genassym.c.orig        Wed Sep 19 02:16:34 2001
+++ i386/genassym.c     Wed Sep 19 13:03:45 2001
@@ -63,6 +63,7 @@
 #include <vm/pmap.h>
 #include <vm/vm_map.h>
 #include <sys/user.h>
+#include <sys/proc.h>
 #include <net/if.h>
 #include <netinet/in.h>
 #include <nfs/nfsproto.h>
@@ -76,6 +77,7 @@
 #include <machine/sigframe.h>
 #include <machine/globaldata.h>
 #include <machine/vm86.h>
+#include <machine/proc.h>
 
 ASSYM(P_VMSPACE, offsetof(struct proc, p_vmspace));
 ASSYM(VM_PMAP, offsetof(struct vmspace, vm_pmap));
@@ -92,6 +94,9 @@
 ASSYM(TD_PROC, offsetof(struct thread, td_proc));
 ASSYM(TD_INTR_NESTING_LEVEL, offsetof(struct thread, td_intr_nesting_level));
 
+ASSYM(P_MD, offsetof(struct proc, p_md));
+ASSYM(MD_LDT, offsetof(struct mdproc, md_ldt));
+
 ASSYM(KE_FLAGS, offsetof(struct kse, ke_flags));
 
 ASSYM(KEF_ASTPENDING, KEF_ASTPENDING);
@@ -126,7 +131,6 @@
 ASSYM(PCB_EIP, offsetof(struct pcb, pcb_eip));
 ASSYM(TSS_ESP0, offsetof(struct i386tss, tss_esp0));
 
-ASSYM(PCB_USERLDT, offsetof(struct pcb, pcb_ldt));
 ASSYM(PCB_GS, offsetof(struct pcb, pcb_gs));
 ASSYM(PCB_DR0, offsetof(struct pcb, pcb_dr0));
 ASSYM(PCB_DR1, offsetof(struct pcb, pcb_dr1));
--- i386/machdep.c.orig Wed Sep 19 02:16:39 2001
+++ i386/machdep.c      Wed Sep 19 04:57:31 2001
@@ -103,6 +103,7 @@
 #include <machine/md_var.h>
 #include <machine/pc/bios.h>
 #include <machine/pcb_ext.h>           /* pcb.h included via sys/user.h */
+#include <machine/proc.h>
 #include <machine/globals.h>
 #ifdef PERFMON
 #include <machine/perfmon.h>
@@ -880,8 +881,8 @@
        struct trapframe *regs = td->td_frame;
        struct pcb *pcb = td->td_pcb;
 
-       if (pcb->pcb_ldt)
-               user_ldt_free(pcb);
+       if (td->td_proc->p_md.md_ldt)
+               user_ldt_free(td);
   
        bzero((char *)regs, sizeof(struct trapframe));
        regs->tf_eip = entry;
--- i386/swtch.s.orig   Wed Sep 19 02:16:14 2001
+++ i386/swtch.s        Thu Sep 20 03:51:55 2001
@@ -246,7 +246,8 @@
        /* XXX FIXME: we should be restoring the local APIC TPR */
 #endif /* SMP */
 
-       cmpl    $0, PCB_USERLDT(%edx)   /* if there is one */
+       movl    TD_PROC(%ecx), %eax     /* load struct proc from CURTHREAD */
+       cmpl    $0, P_MD+MD_LDT(%eax)   /* see if md_ldt == 0 */
        jnz     1f                      /* then use it */
        movl    _default_ldt,%eax       /* We will use the default */
        cmpl    PCPU(CURRENTLDT),%eax   /* check to see if already loaded */
@@ -255,9 +256,11 @@
        movl    %eax,PCPU(CURRENTLDT)   /* store what we have */
        jmp     2f
 
-1:     pushl   %edx                    /* call a non-trusting routine */
-       call    set_user_ldt            /* to check and load the ldt */
-       popl    %edx
+1:     pushl   %edx                    /* save edx */
+       pushl   P_MD+MD_LDT(%eax)       /* passing p_md -> set_user_ldt */
+       call    set_user_ldt            /* check and load the ldt */
+       popl    %eax                    /* get p_md off stack */
+       popl    %edx                    /* restore edx */
 2:
 
        /* This must be done after loading the user LDT. */
--- i386/sys_machdep.c.orig     Wed Sep 19 02:16:22 2001
+++ i386/sys_machdep.c  Wed Sep 19 04:34:30 2001
@@ -54,6 +54,7 @@
 
 #include <machine/cpu.h>
 #include <machine/pcb_ext.h>   /* pcb.h included by sys/user.h */
+#include <machine/proc.h>
 #include <machine/sysarch.h>
 
 #include <vm/vm_kern.h>                /* for kernel_map */
@@ -70,7 +71,7 @@
 static int i386_get_ioperm     __P((struct thread *, char *));
 static int i386_set_ioperm     __P((struct thread *, char *));
 #ifdef SMP
-static void set_user_ldt_rv    __P((struct pcb *));
+static void set_user_ldt_rv    __P((struct thread *));
 #endif
 
 #ifndef _SYS_SYSPROTO_H_
@@ -257,15 +258,15 @@
  * curproc but before sched_lock's owner is updated in mi_switch().
  */   
 void
-set_user_ldt(struct pcb *pcb)
+set_user_ldt(struct mdproc *mdp)
 {
-       struct pcb_ldt *pcb_ldt;
+       struct proc_ldt *pldt;
 
-       pcb_ldt = pcb->pcb_ldt;
+       pldt = mdp->md_ldt;
 #ifdef SMP
-       gdt[PCPU_GET(cpuid) * NGDT + GUSERLDT_SEL].sd = pcb_ldt->ldt_sd;
+       gdt[PCPU_GET(cpuid) * NGDT + GUSERLDT_SEL].sd = pldt->ldt_sd;
 #else
-       gdt[GUSERLDT_SEL].sd = pcb_ldt->ldt_sd;
+       gdt[GUSERLDT_SEL].sd = pldt->ldt_sd;
 #endif
        lldt(GSEL(GUSERLDT_SEL, SEL_KPL));
        PCPU_SET(currentldt, GSEL(GUSERLDT_SEL, SEL_KPL));
@@ -273,14 +274,14 @@
 
 #ifdef SMP
 static void
-set_user_ldt_rv(struct pcb *pcb)
+set_user_ldt_rv(struct thread *td)
 {
 
-       if (pcb != PCPU_GET(curpcb))
+       if (td != PCPU_GET(curthread))
                return;
 
        mtx_lock_spin(&sched_lock);
-       set_user_ldt(pcb);
+       set_user_ldt(&td->td_proc->p_md);
        mtx_unlock_spin(&sched_lock);
 }
 #endif
@@ -289,15 +290,15 @@
  * Must be called with either sched_lock free or held but not recursed.
  * If it does not return NULL, it will return with it owned.
  */
-struct pcb_ldt *
-user_ldt_alloc(struct pcb *pcb, int len)
+struct proc_ldt *
+user_ldt_alloc(struct mdproc *mdp, int len)
 {
-       struct pcb_ldt *pcb_ldt, *new_ldt;
+       struct proc_ldt *pldt, *new_ldt;
 
        if (mtx_owned(&sched_lock))
                mtx_unlock_spin(&sched_lock);
        mtx_assert(&sched_lock, MA_NOTOWNED);
-       MALLOC(new_ldt, struct pcb_ldt *, sizeof(struct pcb_ldt),
+       MALLOC(new_ldt, struct proc_ldt *, sizeof(struct proc_ldt),
                M_SUBPROC, M_WAITOK);
 
        new_ldt->ldt_len = len = NEW_MAX_LD(len);
@@ -315,11 +316,11 @@
        gdt_segs[GUSERLDT_SEL].ssd_limit = len * sizeof(union descriptor) - 1;
        ssdtosd(&gdt_segs[GUSERLDT_SEL], &new_ldt->ldt_sd);
 
-       if ((pcb_ldt = pcb->pcb_ldt)) {
-               if (len > pcb_ldt->ldt_len)
-                       len = pcb_ldt->ldt_len;
-               bcopy(pcb_ldt->ldt_base, new_ldt->ldt_base,
-                       len * sizeof(union descriptor));
+       if ((pldt = mdp->md_ldt)) {
+               if (len > pldt->ldt_len)
+                       len = pldt->ldt_len;
+               bcopy(pldt->ldt_base, new_ldt->ldt_base,
+                   len * sizeof(union descriptor));
        } else {
                bcopy(ldt, new_ldt->ldt_base, sizeof(ldt));
        }
@@ -328,30 +329,31 @@
 
 /*
  * Must be called either with sched_lock free or held but not recursed.
- * If pcb->pcb_ldt is not NULL, it will return with sched_lock released.
+ * If md_ldt is not NULL, it will return with sched_lock released.
  */
 void
-user_ldt_free(struct pcb *pcb)
+user_ldt_free(struct thread *td)
 {
-       struct pcb_ldt *pcb_ldt = pcb->pcb_ldt;
+       struct mdproc *mdp = &td->td_proc->p_md;
+       struct proc_ldt *pldt = mdp->md_ldt;
 
-       if (pcb_ldt == NULL)
+       if (pldt == NULL)
                return;
 
        if (!mtx_owned(&sched_lock))
                mtx_lock_spin(&sched_lock);
        mtx_assert(&sched_lock, MA_OWNED | MA_NOTRECURSED);
-       if (pcb == PCPU_GET(curpcb)) {
+       if (td == PCPU_GET(curthread)) {
                lldt(_default_ldt);
                PCPU_SET(currentldt, _default_ldt);
        }
 
-       pcb->pcb_ldt = NULL;
-       if (--pcb_ldt->ldt_refcnt == 0) {
+       mdp->md_ldt = NULL;
+       if (--pldt->ldt_refcnt == 0) {
                mtx_unlock_spin(&sched_lock);
-               kmem_free(kernel_map, (vm_offset_t)pcb_ldt->ldt_base,
-                       pcb_ldt->ldt_len * sizeof(union descriptor));
-               FREE(pcb_ldt, M_SUBPROC);
+               kmem_free(kernel_map, (vm_offset_t)pldt->ldt_base,
+                       pldt->ldt_len * sizeof(union descriptor));
+               FREE(pldt, M_SUBPROC);
        } else
                mtx_unlock_spin(&sched_lock);
 }
@@ -362,8 +364,7 @@
        char *args;
 {
        int error = 0;
-       struct pcb *pcb = td->td_pcb;
-       struct pcb_ldt *pcb_ldt = pcb->pcb_ldt;
+       struct proc_ldt *pldt = td->td_proc->p_md.md_ldt;
        int nldt, num;
        union descriptor *lp;
        struct i386_ldt_args ua, *uap = &ua;
@@ -380,10 +381,10 @@
        if ((uap->start < 0) || (uap->num <= 0))
                return(EINVAL);
 
-       if (pcb_ldt) {
-               nldt = pcb_ldt->ldt_len;
+       if (pldt) {
+               nldt = pldt->ldt_len;
                num = min(uap->num, nldt);
-               lp = &((union descriptor *)(pcb_ldt->ldt_base))[uap->start];
+               lp = &((union descriptor *)(pldt->ldt_base))[uap->start];
        } else {
                nldt = sizeof(ldt)/sizeof(ldt[0]);
                num = min(uap->num, nldt);
@@ -406,8 +407,9 @@
 {
        int error = 0, i, n;
        int largest_ld;
+       struct mdproc *mdp = &td->td_proc->p_md;
        struct pcb *pcb = td->td_pcb;
-       struct pcb_ldt *pcb_ldt = pcb->pcb_ldt;
+       struct proc_ldt *pldt = mdp->md_ldt;
        struct i386_ldt_args ua, *uap = &ua;
        caddr_t old_ldt_base;
        int old_ldt_len;
@@ -432,16 +434,16 @@
                return(EINVAL);
 
        /* allocate user ldt */
-       if (!pcb_ldt || largest_ld >= pcb_ldt->ldt_len) {
-               struct pcb_ldt *new_ldt = user_ldt_alloc(pcb, largest_ld);
+       if (!pldt || largest_ld >= pldt->ldt_len) {
+               struct proc_ldt *new_ldt = user_ldt_alloc(mdp, largest_ld);
                if (new_ldt == NULL)
                        return ENOMEM;
-               if (pcb_ldt) {
-                       old_ldt_base = pcb_ldt->ldt_base;
-                       old_ldt_len = pcb_ldt->ldt_len;
-                       pcb_ldt->ldt_sd = new_ldt->ldt_sd;
-                       pcb_ldt->ldt_base = new_ldt->ldt_base;
-                       pcb_ldt->ldt_len = new_ldt->ldt_len;
+               if (pldt) {
+                       old_ldt_base = pldt->ldt_base;
+                       old_ldt_len = pldt->ldt_len;
+                       pldt->ldt_sd = new_ldt->ldt_sd;
+                       pldt->ldt_base = new_ldt->ldt_base;
+                       pldt->ldt_len = new_ldt->ldt_len;
                        mtx_unlock_spin(&sched_lock);
                        kmem_free(kernel_map, (vm_offset_t)old_ldt_base,
                                old_ldt_len * sizeof(union descriptor));
@@ -450,16 +452,17 @@
                        mtx_lock_spin(&sched_lock);
 #endif
                } else {
-                       pcb->pcb_ldt = pcb_ldt = new_ldt;
+                       mdp->md_ldt = pldt = new_ldt;
 #ifdef SMP
                        mtx_unlock_spin(&sched_lock);
 #endif
                }
 #ifdef SMP
                /* signal other cpus to reload ldt */
-               smp_rendezvous(NULL, (void (*)(void *))set_user_ldt_rv, NULL, pcb);
+               smp_rendezvous(NULL, (void (*)(void *))set_user_ldt_rv, 
+                   NULL, td);
 #else
-               set_user_ldt(pcb);
+               set_user_ldt(mdp);
                mtx_unlock_spin(&sched_lock);
 #endif
        }
@@ -533,7 +536,7 @@
        /* Fill in range */
        savecrit = critical_enter();
        error = copyin(uap->descs, 
-           &((union descriptor *)(pcb_ldt->ldt_base))[uap->start],
+           &((union descriptor *)(pldt->ldt_base))[uap->start],
            uap->num * sizeof(union descriptor));
        if (!error)
                td->td_retval[0] = uap->start;
--- i386/vm_machdep.c.orig      Wed Sep 19 02:16:28 2001
+++ i386/vm_machdep.c   Wed Sep 19 03:39:14 2001
@@ -125,6 +125,7 @@
        register struct proc *p1;
        struct thread *td2;
        struct pcb *pcb2;
+       struct mdproc *mdp2;
 #ifdef DEV_NPX
        int savecrit;
 #endif
@@ -134,15 +135,15 @@
        if ((flags & RFPROC) == 0) {
                if ((flags & RFMEM) == 0) {
                        /* unshare user LDT */
-                       struct pcb *pcb1 = td1->td_pcb;
-                       struct pcb_ldt *pcb_ldt = pcb1->pcb_ldt;
-                       if (pcb_ldt && pcb_ldt->ldt_refcnt > 1) {
-                               pcb_ldt = user_ldt_alloc(pcb1,pcb_ldt->ldt_len);
-                               if (pcb_ldt == NULL)
+                       struct mdproc *mdp1 = &td1->td_proc->p_md;
+                       struct proc_ldt *pldt = mdp1->md_ldt;
+                       if (pldt && pldt->ldt_refcnt > 1) {
+                               pldt = user_ldt_alloc(mdp1, pldt->ldt_len);
+                               if (pldt == NULL)
                                        panic("could not copy LDT");
-                               pcb1->pcb_ldt = pcb_ldt;
-                               set_user_ldt(pcb1);
-                               user_ldt_free(pcb1);
+                               mdp1->md_ldt = pldt;
+                               set_user_ldt(mdp1);
+                               user_ldt_free(td1);
                        }
                }
                return;
@@ -162,9 +163,13 @@
        pcb2 = (struct pcb *)(td2->td_kstack + KSTACK_PAGES * PAGE_SIZE) - 1;
        td2->td_pcb = pcb2;
 
-       /* Copy p1's pcb. */
+       /* Copy p1's pcb */
        bcopy(td1->td_pcb, pcb2, sizeof(*pcb2));
 
+       /* Point mdproc and then copy over td1's contents */
+       mdp2 = &td2->td_proc->p_md;
+       bcopy(&td1->td_proc->p_md, mdp2, sizeof(*mdp2));
+
        /*
         * Create a new fresh stack for the new process.
         * Copy the trap frame for the return to user mode as if from a
@@ -190,7 +195,6 @@
        pcb2->pcb_eip = (int)fork_trampoline;
        /*-
         * pcb2->pcb_dr*:       cloned above.
-        * pcb2->pcb_ldt:       duplicated below, if necessary.
         * pcb2->pcb_savefpu:   cloned above.
         * pcb2->pcb_flags:     cloned above.
         * pcb2->pcb_onfault:   cloned above (always NULL here?).
@@ -205,13 +209,13 @@
 
         /* Copy the LDT, if necessary. */
        mtx_lock_spin(&sched_lock);
-        if (pcb2->pcb_ldt != 0) {
+        if (mdp2->md_ldt != 0) {
                if (flags & RFMEM) {
-                       pcb2->pcb_ldt->ldt_refcnt++;
+                       mdp2->md_ldt->ldt_refcnt++;
                } else {
-                       pcb2->pcb_ldt = user_ldt_alloc(pcb2,
-                               pcb2->pcb_ldt->ldt_len);
-                       if (pcb2->pcb_ldt == NULL)
+                       mdp2->md_ldt = user_ldt_alloc(mdp2,
+                           mdp2->md_ldt->ldt_len);
+                       if (mdp2->md_ldt == NULL)
                                panic("could not copy LDT");
                }
         }
@@ -253,7 +257,7 @@
        register struct thread *td;
 {
        struct pcb *pcb = td->td_pcb; 
-
+       struct mdproc *mdp = &td->td_proc->p_md;
 #ifdef DEV_NPX
        npxexit(td);
 #endif
@@ -266,8 +270,8 @@
                    ctob(IOPAGES + 1));
                pcb->pcb_ext = 0;
        }
-       if (pcb->pcb_ldt)
-               user_ldt_free(pcb);
+       if (mdp->md_ldt)
+               user_ldt_free(td);
         if (pcb->pcb_flags & PCB_DBREGS) {
                 /*
                  * disable all hardware breakpoints

Reply via email to