diff options
author | jhb <jhb@FreeBSD.org> | 2001-10-25 00:53:43 +0000 |
---|---|---|
committer | jhb <jhb@FreeBSD.org> | 2001-10-25 00:53:43 +0000 |
commit | ba0a9ee2e6605c9d7c16f4f8ff1b8abd51656a52 (patch) | |
tree | 985767d54ab8587f13c4b10e2042c123e33ede0e /sys | |
parent | 5a9e0848db34a5ed03ef25c96a45f2759fd0e14c (diff) | |
download | FreeBSD-src-ba0a9ee2e6605c9d7c16f4f8ff1b8abd51656a52.zip FreeBSD-src-ba0a9ee2e6605c9d7c16f4f8ff1b8abd51656a52.tar.gz |
Split the per-process Local Descriptor Table out of the PCB and into
struct mdproc.
Submitted by: Andrew R. Reiter <arr@watson.org>
Silence on: -current
Diffstat (limited to 'sys')
-rw-r--r-- | sys/amd64/amd64/cpu_switch.S | 11 | ||||
-rw-r--r-- | sys/amd64/amd64/genassym.c | 6 | ||||
-rw-r--r-- | sys/amd64/amd64/machdep.c | 5 | ||||
-rw-r--r-- | sys/amd64/amd64/swtch.s | 11 | ||||
-rw-r--r-- | sys/amd64/amd64/sys_machdep.c | 96 | ||||
-rw-r--r-- | sys/amd64/amd64/vm_machdep.c | 40 | ||||
-rw-r--r-- | sys/amd64/include/pcb.h | 1 | ||||
-rw-r--r-- | sys/amd64/include/pcb_ext.h | 11 | ||||
-rw-r--r-- | sys/amd64/include/proc.h | 18 | ||||
-rw-r--r-- | sys/i386/i386/genassym.c | 6 | ||||
-rw-r--r-- | sys/i386/i386/machdep.c | 5 | ||||
-rw-r--r-- | sys/i386/i386/swtch.s | 11 | ||||
-rw-r--r-- | sys/i386/i386/sys_machdep.c | 96 | ||||
-rw-r--r-- | sys/i386/i386/vm_machdep.c | 40 | ||||
-rw-r--r-- | sys/i386/include/pcb.h | 1 | ||||
-rw-r--r-- | sys/i386/include/pcb_ext.h | 11 | ||||
-rw-r--r-- | sys/i386/include/proc.h | 18 |
17 files changed, 215 insertions, 172 deletions
diff --git a/sys/amd64/amd64/cpu_switch.S b/sys/amd64/amd64/cpu_switch.S index 55d4c0d..d63afbd 100644 --- a/sys/amd64/amd64/cpu_switch.S +++ b/sys/amd64/amd64/cpu_switch.S @@ -246,7 +246,8 @@ sw1b: /* 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 @@ sw1b: 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. */ diff --git a/sys/amd64/amd64/genassym.c b/sys/amd64/amd64/genassym.c index 5e0d93a..9f41665 100644 --- a/sys/amd64/amd64/genassym.c +++ b/sys/amd64/amd64/genassym.c @@ -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_KSE, offsetof(struct thread, td_kse)); 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_EBX, offsetof(struct pcb, pcb_ebx)); 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)); diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 6711515..213559c 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -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 @@ setregs(td, entry, stack, ps_strings) 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; diff --git a/sys/amd64/amd64/swtch.s b/sys/amd64/amd64/swtch.s index 55d4c0d..d63afbd 100644 --- a/sys/amd64/amd64/swtch.s +++ b/sys/amd64/amd64/swtch.s @@ -246,7 +246,8 @@ sw1b: /* 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 @@ sw1b: 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. */ diff --git a/sys/amd64/amd64/sys_machdep.c b/sys/amd64/amd64/sys_machdep.c index 4c53d5a..a88acc9 100644 --- a/sys/amd64/amd64/sys_machdep.c +++ b/sys/amd64/amd64/sys_machdep.c @@ -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_set_ldt __P((struct thread *, char *)); 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_ @@ -256,15 +257,15 @@ done: * 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)); @@ -272,14 +273,14 @@ set_user_ldt(struct pcb *pcb) #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 @@ -288,15 +289,15 @@ set_user_ldt_rv(struct pcb *pcb) * 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); @@ -314,11 +315,11 @@ user_ldt_alloc(struct pcb *pcb, int len) 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)); } @@ -327,30 +328,31 @@ user_ldt_alloc(struct pcb *pcb, int len) /* * 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); } @@ -361,8 +363,7 @@ i386_get_ldt(td, args) 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; @@ -379,10 +380,10 @@ i386_get_ldt(td, args) 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); @@ -405,8 +406,8 @@ i386_set_ldt(td, args) { int error = 0, i, n; int largest_ld; - struct pcb *pcb = td->td_pcb; - struct pcb_ldt *pcb_ldt = pcb->pcb_ldt; + struct mdproc *mdp = &td->td_proc->p_md; + struct proc_ldt *pldt = mdp->md_ldt; struct i386_ldt_args ua, *uap = &ua; caddr_t old_ldt_base; int old_ldt_len; @@ -431,16 +432,16 @@ i386_set_ldt(td, args) 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)); @@ -449,16 +450,17 @@ i386_set_ldt(td, args) 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 } @@ -532,7 +534,7 @@ i386_set_ldt(td, args) /* 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; diff --git a/sys/amd64/amd64/vm_machdep.c b/sys/amd64/amd64/vm_machdep.c index e993e31..59898e3 100644 --- a/sys/amd64/amd64/vm_machdep.c +++ b/sys/amd64/amd64/vm_machdep.c @@ -125,6 +125,7 @@ cpu_fork(td1, p2, flags) register struct proc *p1; struct thread *td2; struct pcb *pcb2; + struct mdproc *mdp2; #ifdef DEV_NPX int savecrit; #endif @@ -134,15 +135,15 @@ cpu_fork(td1, p2, flags) 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 @@ cpu_fork(td1, p2, flags) 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 @@ -191,7 +196,6 @@ cpu_fork(td1, p2, flags) 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?). @@ -206,13 +210,13 @@ cpu_fork(td1, p2, flags) /* 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"); } } @@ -254,7 +258,7 @@ cpu_exit(td) register struct thread *td; { struct pcb *pcb = td->td_pcb; - + struct mdproc *mdp = &td->td_proc->p_md; #ifdef DEV_NPX npxexit(td); #endif @@ -267,8 +271,8 @@ cpu_exit(td) 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 diff --git a/sys/amd64/include/pcb.h b/sys/amd64/include/pcb.h index 21d95c5..9eb0f81 100644 --- a/sys/amd64/include/pcb.h +++ b/sys/amd64/include/pcb.h @@ -61,7 +61,6 @@ struct pcb { 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 */ diff --git a/sys/amd64/include/pcb_ext.h b/sys/amd64/include/pcb_ext.h index c6f9fc0..3256f99 100644 --- a/sys/amd64/include/pcb_ext.h +++ b/sys/amd64/include/pcb_ext.h @@ -43,20 +43,9 @@ struct pcb_ext { 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 diff --git a/sys/amd64/include/proc.h b/sys/amd64/include/proc.h index 9e9e449..911f6b8 100644 --- a/sys/amd64/include/proc.h +++ b/sys/amd64/include/proc.h @@ -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 mdthread { }; 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_ */ diff --git a/sys/i386/i386/genassym.c b/sys/i386/i386/genassym.c index 5e0d93a..9f41665 100644 --- a/sys/i386/i386/genassym.c +++ b/sys/i386/i386/genassym.c @@ -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_KSE, offsetof(struct thread, td_kse)); 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_EBX, offsetof(struct pcb, pcb_ebx)); 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)); diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 6711515..213559c 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -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 @@ setregs(td, entry, stack, ps_strings) 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; diff --git a/sys/i386/i386/swtch.s b/sys/i386/i386/swtch.s index 55d4c0d..d63afbd 100644 --- a/sys/i386/i386/swtch.s +++ b/sys/i386/i386/swtch.s @@ -246,7 +246,8 @@ sw1b: /* 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 @@ sw1b: 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. */ diff --git a/sys/i386/i386/sys_machdep.c b/sys/i386/i386/sys_machdep.c index 4c53d5a..a88acc9 100644 --- a/sys/i386/i386/sys_machdep.c +++ b/sys/i386/i386/sys_machdep.c @@ -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_set_ldt __P((struct thread *, char *)); 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_ @@ -256,15 +257,15 @@ done: * 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)); @@ -272,14 +273,14 @@ set_user_ldt(struct pcb *pcb) #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 @@ -288,15 +289,15 @@ set_user_ldt_rv(struct pcb *pcb) * 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); @@ -314,11 +315,11 @@ user_ldt_alloc(struct pcb *pcb, int len) 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)); } @@ -327,30 +328,31 @@ user_ldt_alloc(struct pcb *pcb, int len) /* * 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); } @@ -361,8 +363,7 @@ i386_get_ldt(td, args) 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; @@ -379,10 +380,10 @@ i386_get_ldt(td, args) 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); @@ -405,8 +406,8 @@ i386_set_ldt(td, args) { int error = 0, i, n; int largest_ld; - struct pcb *pcb = td->td_pcb; - struct pcb_ldt *pcb_ldt = pcb->pcb_ldt; + struct mdproc *mdp = &td->td_proc->p_md; + struct proc_ldt *pldt = mdp->md_ldt; struct i386_ldt_args ua, *uap = &ua; caddr_t old_ldt_base; int old_ldt_len; @@ -431,16 +432,16 @@ i386_set_ldt(td, args) 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)); @@ -449,16 +450,17 @@ i386_set_ldt(td, args) 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 } @@ -532,7 +534,7 @@ i386_set_ldt(td, args) /* 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; diff --git a/sys/i386/i386/vm_machdep.c b/sys/i386/i386/vm_machdep.c index e993e31..59898e3 100644 --- a/sys/i386/i386/vm_machdep.c +++ b/sys/i386/i386/vm_machdep.c @@ -125,6 +125,7 @@ cpu_fork(td1, p2, flags) register struct proc *p1; struct thread *td2; struct pcb *pcb2; + struct mdproc *mdp2; #ifdef DEV_NPX int savecrit; #endif @@ -134,15 +135,15 @@ cpu_fork(td1, p2, flags) 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 @@ cpu_fork(td1, p2, flags) 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 @@ -191,7 +196,6 @@ cpu_fork(td1, p2, flags) 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?). @@ -206,13 +210,13 @@ cpu_fork(td1, p2, flags) /* 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"); } } @@ -254,7 +258,7 @@ cpu_exit(td) register struct thread *td; { struct pcb *pcb = td->td_pcb; - + struct mdproc *mdp = &td->td_proc->p_md; #ifdef DEV_NPX npxexit(td); #endif @@ -267,8 +271,8 @@ cpu_exit(td) 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 diff --git a/sys/i386/include/pcb.h b/sys/i386/include/pcb.h index 21d95c5..9eb0f81 100644 --- a/sys/i386/include/pcb.h +++ b/sys/i386/include/pcb.h @@ -61,7 +61,6 @@ struct pcb { 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 */ diff --git a/sys/i386/include/pcb_ext.h b/sys/i386/include/pcb_ext.h index c6f9fc0..3256f99 100644 --- a/sys/i386/include/pcb_ext.h +++ b/sys/i386/include/pcb_ext.h @@ -43,20 +43,9 @@ struct pcb_ext { 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 diff --git a/sys/i386/include/proc.h b/sys/i386/include/proc.h index 9e9e449..911f6b8 100644 --- a/sys/i386/include/proc.h +++ b/sys/i386/include/proc.h @@ -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 mdthread { }; 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_ */ |