Source-Changes-HG archive

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

[src/trunk]: src/sys/arch/amd64 Optionally include saving and restoring the 6...



details:   https://anonhg.NetBSD.org/src/rev/d3cd457e53a3
branches:  trunk
changeset: 580915:d3cd457e53a3
user:      fvdl <fvdl%NetBSD.org@localhost>
date:      Sun May 15 21:37:46 2005 +0000

description:
Optionally include saving and restoring the 64bit %gs and %fs base register
values in the PCB. Do this in pmap_activate for now (XXX not a good place
for it, but a convenient one).

diffstat:

 sys/arch/amd64/amd64/machdep.c         |  131 ++++++++++++++++++++++++++++----
 sys/arch/amd64/amd64/pmap.c            |   11 ++-
 sys/arch/amd64/amd64/process_machdep.c |    6 +-
 sys/arch/amd64/include/mcontext.h      |    5 +-
 sys/arch/amd64/include/pcb.h           |    6 +-
 sys/arch/amd64/include/segments.h      |   17 ++++-
 6 files changed, 147 insertions(+), 29 deletions(-)

diffs (truncated from 326 to 300 lines):

diff -r 140d06674d02 -r d3cd457e53a3 sys/arch/amd64/amd64/machdep.c
--- a/sys/arch/amd64/amd64/machdep.c    Sun May 15 21:31:26 2005 +0000
+++ b/sys/arch/amd64/amd64/machdep.c    Sun May 15 21:37:46 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: machdep.c,v 1.33 2005/04/25 15:02:02 lukem Exp $       */
+/*     $NetBSD: machdep.c,v 1.34 2005/05/15 21:37:46 fvdl Exp $        */
 
 /*-
  * Copyright (c) 1996, 1997, 1998, 2000 The NetBSD Foundation, Inc.
@@ -72,7 +72,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.33 2005/04/25 15:02:02 lukem Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.34 2005/05/15 21:37:46 fvdl Exp $");
 
 #include "opt_user_ldt.h"
 #include "opt_ddb.h"
@@ -1669,7 +1669,7 @@
        int64_t rflags;
 
        if ((flags & _UC_CPU) != 0) {
-               error = check_mcontext(mcp, tf);
+               error = check_mcontext(l, mcp, tf);
                if (error != 0)
                        return error;
                /*
@@ -1703,35 +1703,64 @@
 }
 
 int
-check_mcontext(const mcontext_t *mcp, struct trapframe *tf)
+check_mcontext(struct lwp *l, const mcontext_t *mcp, struct trapframe *tf)
 {
        const __greg_t *gr;
        uint16_t sel;
+       int error;
+       struct pmap *pmap = l->l_proc->p_vmspace->vm_map.pmap;
 
        gr = mcp->__gregs;
 
        if (((gr[_REG_RFL] ^ tf->tf_rflags) & PSL_USERSTATIC) != 0)
                return EINVAL;
 
-       sel = gr[_REG_ES] & 0xffff;
-       if (sel != 0 && !VALID_USER_DSEL(sel))
-               return EINVAL;
+       if (__predict_false((pmap->pm_flags & PMF_USER_LDT) != 0)) {
+               error = valid_user_selector(l, gr[_REG_ES], NULL, 0);
+               if (error != 0)
+                       return error;
+
+               error = valid_user_selector(l, gr[_REG_FS], NULL, 0);
+               if (error != 0)
+                       return error;
 
-       sel = gr[_REG_FS] & 0xffff;
-       if (sel != 0 && !VALID_USER_DSEL(sel))
-               return EINVAL;
+               error = valid_user_selector(l, gr[_REG_GS], NULL, 0);
+               if (error != 0)
+                       return error;
+
+               if ((gr[_REG_DS] & 0xffff) == 0)
+                       return EINVAL;
+               error = valid_user_selector(l, gr[_REG_DS], NULL, 0);
+               if (error != 0)
+                       return error;
 
-       sel = gr[_REG_GS] & 0xffff;
-       if (sel != 0 && !VALID_USER_DSEL(sel))
-               return EINVAL;
+               if ((gr[_REG_SS] & 0xffff) == 0)
+                       return EINVAL;
+               error = valid_user_selector(l, gr[_REG_SS], NULL, 0);
+               if (error != 0)
+                       return error;
+       } else {
+               sel = gr[_REG_ES] & 0xffff;
+               if (sel != 0 && !VALID_USER_DSEL(sel))
+                       return EINVAL;
+
+               sel = gr[_REG_FS] & 0xffff;
+               if (sel != 0 && !VALID_USER_DSEL(sel))
+                       return EINVAL;
 
-       sel = gr[_REG_DS] & 0xffff;
-       if (!VALID_USER_DSEL(sel))
-               return EINVAL;
+               sel = gr[_REG_GS] & 0xffff;
+               if (sel != 0 && !VALID_USER_DSEL(sel))
+                       return EINVAL;
 
-       sel = gr[_REG_SS] & 0xffff;
-       if (!VALID_USER_DSEL(sel)) 
-               return EINVAL;
+               sel = gr[_REG_DS] & 0xffff;
+               if (!VALID_USER_DSEL(sel))
+                       return EINVAL;
+
+               sel = gr[_REG_SS] & 0xffff;
+               if (!VALID_USER_DSEL(sel)) 
+                       return EINVAL;
+
+       }
 
        sel = gr[_REG_CS] & 0xffff;
        if (!VALID_USER_CSEL(sel))
@@ -1806,6 +1835,70 @@
        simple_unlock(&idt_lock);
 }
 
+int
+memseg_baseaddr(struct lwp *l, uint64_t seg, char *ldtp, int llen,
+               uint64_t *addr)
+{
+       int off, len;
+       char *dt;
+       struct mem_segment_descriptor *sdp;
+       struct proc *p = l->l_proc;
+       struct pmap *pmap= p->p_vmspace->vm_map.pmap;
+       uint64_t base;
+
+       seg &= 0xffff;
+
+       if (seg == 0) {
+               if (addr != NULL)
+                       *addr = 0;
+               return 0;
+       }
+
+       off = (seg & 0xfff8);
+       if (seg & SEL_LDT) {
+               if (ldtp != NULL) {
+                       dt = ldtp;
+                       len = llen;
+               } else if (pmap->pm_flags & PMF_USER_LDT) {
+                       len = pmap->pm_ldt_len;
+                       dt = (char *)pmap->pm_ldt;
+               } else {
+                       dt = ldtstore;
+                       len = LDT_SIZE;
+               }
+
+               if (off > (len - 8))
+                       return EINVAL;
+       } else {
+               if (seg != GUDATA_SEL || seg != GUDATA32_SEL)
+                       return EINVAL;
+       }
+
+       sdp = (struct mem_segment_descriptor *)(dt + off);
+       if (sdp->sd_type < SDT_MEMRO || sdp->sd_p == 0)
+               return EINVAL;
+
+       base = ((uint64_t)sdp->sd_hibase << 32) | ((uint64_t)sdp->sd_lobase);
+       if (sdp->sd_gran == 1)
+               base <<= PAGE_SHIFT;
+
+       if (base >= VM_MAXUSER_ADDRESS)
+               return EINVAL;
+
+       if (addr == NULL)
+               return 0;
+
+       *addr = base;
+
+       return 0;
+}
+
+int
+valid_user_selector(struct lwp *l, uint64_t seg, char *ldtp, int len)
+{
+       return memseg_baseaddr(l, seg, ldtp, len, NULL);
+}
+
 /*
  * Number of processes is limited by number of available GDT slots.
  */
diff -r 140d06674d02 -r d3cd457e53a3 sys/arch/amd64/amd64/pmap.c
--- a/sys/arch/amd64/amd64/pmap.c       Sun May 15 21:31:26 2005 +0000
+++ b/sys/arch/amd64/amd64/pmap.c       Sun May 15 21:37:46 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pmap.c,v 1.16 2005/04/01 11:59:23 yamt Exp $   */
+/*     $NetBSD: pmap.c,v 1.17 2005/05/15 21:37:46 fvdl Exp $   */
 
 /*
  *
@@ -108,7 +108,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.16 2005/04/01 11:59:23 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.17 2005/05/15 21:37:46 fvdl Exp $");
 
 #ifndef __x86_64__
 #include "opt_cputype.h"
@@ -2051,7 +2051,8 @@
                size_t len;
 
                len = pmap1->pm_ldt_len;
-               new_ldt = (char *)uvm_km_alloc(kernel_map, len, UVM_KMF_WIRED);
+               new_ldt = (char *)uvm_km_alloc(kernel_map, len, 0,
+                   UVM_KMF_WIRED);
                memcpy(new_ldt, pmap1->pm_ldt, len);
                pmap2->pm_ldt = new_ldt;
                pmap2->pm_ldt_len = pmap1->pm_ldt_len;
@@ -2128,6 +2129,10 @@
                 */
                x86_atomic_setbits_ul(&pmap->pm_cpus, (1U << cpu_number()));
        }
+       if (pcb->pcb_flags & PCB_GS64)
+               wrmsr(MSR_KERNELGSBASE, pcb->pcb_gs);
+       if (pcb->pcb_flags & PCB_GS64)
+               wrmsr(MSR_FSBASE, pcb->pcb_fs);
 }
 
 /*
diff -r 140d06674d02 -r d3cd457e53a3 sys/arch/amd64/amd64/process_machdep.c
--- a/sys/arch/amd64/amd64/process_machdep.c    Sun May 15 21:31:26 2005 +0000
+++ b/sys/arch/amd64/amd64/process_machdep.c    Sun May 15 21:37:46 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: process_machdep.c,v 1.4 2003/11/30 12:59:30 fvdl Exp $ */
+/*     $NetBSD: process_machdep.c,v 1.5 2005/05/15 21:37:46 fvdl Exp $ */
 
 /*-
  * Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -60,7 +60,7 @@
 
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.4 2003/11/30 12:59:30 fvdl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: process_machdep.c,v 1.5 2005/05/15 21:37:46 fvdl Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -161,7 +161,7 @@
         * Note that struct regs is compatible with
         * the __gregs array in mcontext_t.
         */
-       error = check_mcontext((mcontext_t *)regs, tf);
+       error = check_mcontext(l, (mcontext_t *)regs, tf);
        if (error != 0)
                return error;
 
diff -r 140d06674d02 -r d3cd457e53a3 sys/arch/amd64/include/mcontext.h
--- a/sys/arch/amd64/include/mcontext.h Sun May 15 21:31:26 2005 +0000
+++ b/sys/arch/amd64/include/mcontext.h Sun May 15 21:37:46 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: mcontext.h,v 1.5 2004/10/21 16:49:47 fvdl Exp $        */
+/*     $NetBSD: mcontext.h,v 1.6 2005/05/15 21:37:46 fvdl Exp $        */
 
 /*-
  * Copyright (c) 1999 The NetBSD Foundation, Inc.
@@ -151,7 +151,8 @@
 #define _UC_MACHINE_PAD32      5
 
 struct trapframe;
-int check_mcontext(const mcontext_t *, struct trapframe *);
+struct lwp;
+int check_mcontext(struct lwp *, const mcontext_t *, struct trapframe *);
 
 #endif /* _KERNEL */
 
diff -r 140d06674d02 -r d3cd457e53a3 sys/arch/amd64/include/pcb.h
--- a/sys/arch/amd64/include/pcb.h      Sun May 15 21:31:26 2005 +0000
+++ b/sys/arch/amd64/include/pcb.h      Sun May 15 21:37:46 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pcb.h,v 1.2 2003/08/07 16:26:36 agc Exp $      */
+/*     $NetBSD: pcb.h,v 1.3 2005/05/15 21:37:46 fvdl Exp $     */
 
 /*-
  * Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -109,10 +109,14 @@
        int     pcb_cr0;                /* saved image of CR0 */
        int     pcb_flags;
 #define        PCB_USER_LDT    0x01            /* has user-set LDT */
+#define PCB_GS64       0x02
+#define PCB_FS64       0x04
        caddr_t pcb_onfault;            /* copyin/out fault recovery */
        struct cpu_info *pcb_fpcpu;     /* cpu holding our fp state. */
        unsigned pcb_iomap[NIOPORTS/32];        /* I/O bitmap */
        struct pmap *pcb_pmap;          /* back pointer to our pmap */
+       uint64_t pcb_gs;
+       uint64_t pcb_fs;
 };
 
 /*    
diff -r 140d06674d02 -r d3cd457e53a3 sys/arch/amd64/include/segments.h
--- a/sys/arch/amd64/include/segments.h Sun May 15 21:31:26 2005 +0000
+++ b/sys/arch/amd64/include/segments.h Sun May 15 21:37:46 2005 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: segments.h,v 1.4 2004/02/13 11:36:20 wiz Exp $ */
+/*     $NetBSD: segments.h,v 1.5 2005/05/15 21:37:46 fvdl Exp $        */
 
 /*-
  * Copyright (c) 1990 The Regents of the University of California.
@@ -163,6 +163,16 @@
 } __attribute__((packed));
 



Home | Main Index | Thread Index | Old Index