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