summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorchs <chs@NetBSD.org>2003-08-24 17:52:28 +0000
committerchs <chs@NetBSD.org>2003-08-24 17:52:28 +0000
commit939df36e552ea9012b7b0d0d15080f894ebaaaff (patch)
tree2c4be187b10b4d03eedeccd43a6ba2359fa195e0 /sys
parent4b28d28d7028d98186f61c78a41660eb73edde00 (diff)
add support for non-executable mappings (where the hardware allows this)
and make the stack and heap non-executable by default. the changes fall into two basic catagories: - pmap and trap-handler changes. these are all MD: = alpha: we already track per-page execute permission with the (software) PG_EXEC bit, so just have the trap handler pay attention to it. = i386: use a new GDT segment for %cs for processes that have no executable mappings above a certain threshold (currently the bottom of the stack). track per-page execute permission with the last unused PTE bit. = powerpc/ibm4xx: just use the hardware exec bit. = powerpc/oea: we already track per-page exec bits, but the hardware only implements non-exec mappings at the segment level. so track the number of executable mappings in each segment and turn on the no-exec segment bit iff the count is 0. adjust the trap handler to deal. = sparc (sun4m): fix our use of the hardware protection bits. fix the trap handler to recognize text faults. = sparc64: split the existing unified TSB into data and instruction TSBs, and only load TTEs into the appropriate TSB(s) for the permissions. fix the trap handler to check for execute permission. = not yet implemented: amd64, hppa, sh5 - changes in all the emulations that put a signal trampoline on the stack. instead, we now put the trampoline into a uvm_aobj and map that into the process separately. originally from openbsd, adapted for netbsd by me.
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/alpha/alpha/pmap.c92
-rw-r--r--sys/arch/alpha/alpha/trap.c58
-rw-r--r--sys/arch/alpha/include/pmap.h7
-rw-r--r--sys/arch/alpha/include/pte.h6
-rw-r--r--sys/arch/i386/i386/freebsd_machdep.c6
-rw-r--r--sys/arch/i386/i386/ibcs2_machdep.c7
-rw-r--r--sys/arch/i386/i386/machdep.c21
-rw-r--r--sys/arch/i386/i386/pmap.c78
-rw-r--r--sys/arch/i386/i386/svr4_machdep.c8
-rw-r--r--sys/arch/i386/i386/trap.c10
-rw-r--r--sys/arch/i386/include/pcb.h3
-rw-r--r--sys/arch/i386/include/pmap.h7
-rw-r--r--sys/arch/i386/include/pte.h4
-rw-r--r--sys/arch/i386/include/segments.h6
-rw-r--r--sys/arch/i386/include/vmparam.h12
-rw-r--r--sys/arch/powerpc/ibm4xx/pmap.c56
-rw-r--r--sys/arch/powerpc/ibm4xx/trap.c10
-rw-r--r--sys/arch/powerpc/include/oea/pmap.h12
-rw-r--r--sys/arch/powerpc/include/oea/pte.h4
-rw-r--r--sys/arch/powerpc/oea/pmap.c157
-rw-r--r--sys/arch/powerpc/powerpc/trap.c20
-rw-r--r--sys/arch/sparc/sparc/pmap.c151
-rw-r--r--sys/arch/sparc/sparc/trap.c16
-rw-r--r--sys/arch/sparc64/include/pmap.h3
-rw-r--r--sys/arch/sparc64/sparc64/clock.c42
-rw-r--r--sys/arch/sparc64/sparc64/db_interface.c71
-rw-r--r--sys/arch/sparc64/sparc64/locore.s67
-rw-r--r--sys/arch/sparc64/sparc64/pmap.c313
-rw-r--r--sys/compat/aout/aout_exec.c9
-rw-r--r--sys/compat/aoutm68k/aoutm68k_exec.c9
-rw-r--r--sys/compat/darwin/darwin_exec.c7
-rw-r--r--sys/compat/freebsd/freebsd_exec.c7
-rw-r--r--sys/compat/hpux/hpux_exec.c7
-rw-r--r--sys/compat/ibcs2/ibcs2_exec.c7
-rw-r--r--sys/compat/irix/irix_exec.c5
-rw-r--r--sys/compat/irix/irix_exec.h3
-rw-r--r--sys/compat/linux/arch/i386/linux_machdep.c8
-rw-r--r--sys/compat/linux/common/linux_exec.c8
-rw-r--r--sys/compat/mach/mach_exec.c7
-rw-r--r--sys/compat/netbsd32/netbsd32_netbsd.c7
-rw-r--r--sys/compat/osf1/osf1_exec.c7
-rw-r--r--sys/compat/pecoff/pecoff_emul.c7
-rw-r--r--sys/compat/sunos/sunos_exec.c9
-rw-r--r--sys/compat/sunos32/sunos32_exec.c7
-rw-r--r--sys/compat/svr4/svr4_exec.c7
-rw-r--r--sys/compat/svr4_32/svr4_32_exec.c7
-rw-r--r--sys/compat/ultrix/ultrix_misc.c7
-rw-r--r--sys/kern/exec_subr.c11
-rw-r--r--sys/kern/kern_exec.c91
-rw-r--r--sys/kern/kern_resource.c6
-rw-r--r--sys/sys/proc.h3
-rw-r--r--sys/uvm/uvm_unix.c12
52 files changed, 842 insertions, 663 deletions
diff --git a/sys/arch/alpha/alpha/pmap.c b/sys/arch/alpha/alpha/pmap.c
index 9fef3139fbf..a2ab6f73a85 100644
--- a/sys/arch/alpha/alpha/pmap.c
+++ b/sys/arch/alpha/alpha/pmap.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.202 2003/08/07 16:26:32 agc Exp $ */
+/* $NetBSD: pmap.c,v 1.203 2003/08/24 17:52:28 chs Exp $ */
/*-
* Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -145,7 +145,7 @@
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.202 2003/08/07 16:26:32 agc Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.203 2003/08/24 17:52:28 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -1554,9 +1554,6 @@ pmap_protect(pmap_t pmap, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
return;
}
- if (prot & VM_PROT_WRITE)
- return;
-
PMAP_LOCK(pmap);
bits = pte_prot(pmap, prot);
@@ -2518,39 +2515,23 @@ alpha_protection_init(void)
up = protection_codes[1];
for (prot = 0; prot < 8; prot++) {
- kp[prot] = 0; up[prot] = 0;
- switch (prot) {
- case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE:
- kp[prot] |= PG_ASM;
- up[prot] |= 0;
- break;
-
- case VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE:
- case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE:
- kp[prot] |= PG_EXEC; /* software */
- up[prot] |= PG_EXEC; /* software */
- /* FALLTHROUGH */
-
- case VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE:
- kp[prot] |= PG_ASM | PG_KRE;
- up[prot] |= PG_URE | PG_KRE;
- break;
+ kp[prot] = PG_ASM;
+ up[prot] = 0;
- case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE:
- kp[prot] |= PG_ASM | PG_KWE;
- up[prot] |= PG_UWE | PG_KWE;
- break;
-
- case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE:
- case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
- kp[prot] |= PG_EXEC; /* software */
- up[prot] |= PG_EXEC; /* software */
- /* FALLTHROUGH */
-
- case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE:
- kp[prot] |= PG_ASM | PG_KWE | PG_KRE;
- up[prot] |= PG_UWE | PG_URE | PG_KWE | PG_KRE;
- break;
+ if (prot & VM_PROT_READ) {
+ kp[prot] |= PG_KRE;
+ up[prot] |= PG_KRE | PG_URE;
+ }
+ if (prot & VM_PROT_WRITE) {
+ kp[prot] |= PG_KWE;
+ up[prot] |= PG_KWE | PG_UWE;
+ }
+ if (prot & VM_PROT_EXECUTE) {
+ kp[prot] |= PG_EXEC | PG_KRE;
+ up[prot] |= PG_EXEC | PG_KRE | PG_URE;
+ } else {
+ kp[prot] |= PG_FOE;
+ up[prot] |= PG_FOE;
}
}
}
@@ -2722,20 +2703,24 @@ pmap_changebit(struct vm_page *pg, u_long set, u_long mask, long cpu_id)
* pmap_emulate_reference:
*
* Emulate reference and/or modified bit hits.
+ * Return 1 if this was an execute fault on a non-exec mapping,
+ * otherwise return 0.
*/
-void
-pmap_emulate_reference(struct lwp *l, vaddr_t v, int user, int write)
+int
+pmap_emulate_reference(struct lwp *l, vaddr_t v, int user, int type)
{
+ struct pmap *pmap = l->l_proc->p_vmspace->vm_map.pmap;
pt_entry_t faultoff, *pte;
struct vm_page *pg;
paddr_t pa;
boolean_t didlock = FALSE;
+ boolean_t exec = FALSE;
long cpu_id = cpu_number();
#ifdef DEBUG
if (pmapdebug & PDB_FOLLOW)
printf("pmap_emulate_reference: %p, 0x%lx, %d, %d\n",
- l, v, user, write);
+ l, v, user, type);
#endif
/*
@@ -2755,13 +2740,19 @@ pmap_emulate_reference(struct lwp *l, vaddr_t v, int user, int write)
if (l->l_proc->p_vmspace == NULL)
panic("pmap_emulate_reference: bad p_vmspace");
#endif
- PMAP_LOCK(l->l_proc->p_vmspace->vm_map.pmap);
+ PMAP_LOCK(pmap);
didlock = TRUE;
- pte = pmap_l3pte(l->l_proc->p_vmspace->vm_map.pmap, v, NULL);
+ pte = pmap_l3pte(pmap, v, NULL);
/*
* We'll unlock below where we're done with the PTE.
*/
}
+ exec = pmap_pte_exec(pte);
+ if (!exec && type == ALPHA_MMCSR_FOE) {
+ if (didlock)
+ PMAP_UNLOCK(pmap);
+ return (1);
+ }
#ifdef DEBUG
if (pmapdebug & PDB_FOLLOW) {
printf("\tpte = %p, ", pte);
@@ -2777,7 +2768,7 @@ pmap_emulate_reference(struct lwp *l, vaddr_t v, int user, int write)
* pmap_emulate_reference(), and the bits aren't guaranteed,
* for them...
*/
- if (write) {
+ if (type == ALPHA_MMCSR_FOW) {
if (!(*pte & (user ? PG_UWE : PG_UWE | PG_KWE)))
panic("pmap_emulate_reference: write but unwritable");
if (!(*pte & PG_FOW))
@@ -2798,7 +2789,7 @@ pmap_emulate_reference(struct lwp *l, vaddr_t v, int user, int write)
* it now.
*/
if (didlock)
- PMAP_UNLOCK(l->l_proc->p_vmspace->vm_map.pmap);
+ PMAP_UNLOCK(pmap);
#ifdef DEBUG
if (pmapdebug & PDB_FOLLOW)
@@ -2806,7 +2797,8 @@ pmap_emulate_reference(struct lwp *l, vaddr_t v, int user, int write)
#endif
#ifdef DIAGNOSTIC
if (!PAGE_IS_MANAGED(pa))
- panic("pmap_emulate_reference(%p, 0x%lx, %d, %d): pa 0x%lx not managed", l, v, user, write, pa);
+ panic("pmap_emulate_reference(%p, 0x%lx, %d, %d): "
+ "pa 0x%lx not managed", l, v, user, type, pa);
#endif
/*
@@ -2822,17 +2814,21 @@ pmap_emulate_reference(struct lwp *l, vaddr_t v, int user, int write)
PMAP_HEAD_TO_MAP_LOCK();
simple_lock(&pg->mdpage.pvh_slock);
- if (write) {
+ if (type == ALPHA_MMCSR_FOW) {
pg->mdpage.pvh_attrs |= (PGA_REFERENCED|PGA_MODIFIED);
- faultoff = PG_FOR | PG_FOW | PG_FOE;
+ faultoff = PG_FOR | PG_FOW;
} else {
pg->mdpage.pvh_attrs |= PGA_REFERENCED;
- faultoff = PG_FOR | PG_FOE;
+ faultoff = PG_FOR;
+ if (exec) {
+ faultoff |= PG_FOE;
+ }
}
pmap_changebit(pg, 0, ~faultoff, cpu_id);
simple_unlock(&pg->mdpage.pvh_slock);
PMAP_HEAD_TO_MAP_UNLOCK();
+ return (0);
}
#ifdef DEBUG
diff --git a/sys/arch/alpha/alpha/trap.c b/sys/arch/alpha/alpha/trap.c
index c86e61eb618..939bb67e016 100644
--- a/sys/arch/alpha/alpha/trap.c
+++ b/sys/arch/alpha/alpha/trap.c
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.80 2003/06/23 11:01:00 martin Exp $ */
+/* $NetBSD: trap.c,v 1.81 2003/08/24 17:52:29 chs Exp $ */
/*-
* Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
@@ -100,7 +100,7 @@
#include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.80 2003/06/23 11:01:00 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.81 2003/08/24 17:52:29 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -232,17 +232,16 @@ void
trap(const u_long a0, const u_long a1, const u_long a2, const u_long entry,
struct trapframe *framep)
{
- register struct lwp *l;
- register int i;
+ struct lwp *l;
u_int64_t ucode;
- int user;
+ vm_prot_t ftype;
+ int i, user;
#if defined(DDB)
int call_debugger = 1;
#endif
l = curlwp;
- uvmexp.traps++; /* XXXSMP: NOT ATOMIC */
ucode = 0;
user = (framep->tf_regs[FRAME_PS] & ALPHA_PSL_USERMODE) != 0;
if (user)
@@ -360,8 +359,10 @@ trap(const u_long a0, const u_long a1, const u_long a2, const u_long entry,
else
KERNEL_LOCK(LK_CANRECURSE|LK_EXCLUSIVE);
- pmap_emulate_reference(l, a0, user,
- a1 == ALPHA_MMCSR_FOW ? 1 : 0);
+ if (pmap_emulate_reference(l, a0, user, a1)) {
+ ftype = VM_PROT_EXECUTE;
+ goto do_fault;
+ }
if (user)
KERNEL_PROC_UNLOCK(l);
@@ -372,12 +373,23 @@ trap(const u_long a0, const u_long a1, const u_long a2, const u_long entry,
case ALPHA_MMCSR_INVALTRANS:
case ALPHA_MMCSR_ACCESS:
{
- register vaddr_t va;
- register struct vmspace *vm = NULL;
- register struct vm_map *map;
- vm_prot_t ftype;
+ vaddr_t va;
+ struct vmspace *vm = NULL;
+ struct vm_map *map;
int rv;
+ switch (a2) {
+ case -1: /* instruction fetch fault */
+ ftype = VM_PROT_EXECUTE;
+ break;
+ case 0: /* load instruction */
+ ftype = VM_PROT_READ;
+ break;
+ case 1: /* store instruction */
+ ftype = VM_PROT_WRITE;
+ break;
+ }
+
if (user)
KERNEL_PROC_LOCK(l);
else {
@@ -427,6 +439,7 @@ trap(const u_long a0, const u_long a1, const u_long a2, const u_long entry,
* The last can occur during an exec() copyin where the
* argument space is lazy-allocated.
*/
+do_fault:
if (user == 0 && (a0 >= VM_MIN_KERNEL_ADDRESS ||
l->l_addr->u_pcb.pcb_onfault == 0))
map = kernel_map;
@@ -435,28 +448,11 @@ trap(const u_long a0, const u_long a1, const u_long a2, const u_long entry,
map = &vm->vm_map;
}
- switch (a2) {
- case -1: /* instruction fetch fault */
- case 0: /* load instruction */
- ftype = VM_PROT_READ;
- break;
- case 1: /* store instruction */
- ftype = VM_PROT_WRITE;
- break;
-#ifdef DIAGNOSTIC
- default: /* XXX gcc -Wuninitialized */
- if (user)
- KERNEL_PROC_UNLOCK(l);
- else
- KERNEL_UNLOCK();
- goto dopanic;
-#endif
- }
-
va = trunc_page((vaddr_t)a0);
rv = uvm_fault(map, va,
(a1 == ALPHA_MMCSR_INVALTRANS) ?
VM_FAULT_INVALID : VM_FAULT_PROTECT, ftype);
+
/*
* If this was a stack access we keep track of the
* maximum accessed stack size. Also, if vm_fault
@@ -614,7 +610,7 @@ alpha_enable_fp(struct lwp *l, int check)
void
ast(struct trapframe *framep)
{
- register struct lwp *l;
+ struct lwp *l;
/*
* We may not have a current process to do AST processing
diff --git a/sys/arch/alpha/include/pmap.h b/sys/arch/alpha/include/pmap.h
index ee2b255d34d..f8e7b318fe0 100644
--- a/sys/arch/alpha/include/pmap.h
+++ b/sys/arch/alpha/include/pmap.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.62 2003/08/07 16:26:33 agc Exp $ */
+/* $NetBSD: pmap.h,v 1.63 2003/08/24 17:52:30 chs Exp $ */
/*-
* Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -258,9 +258,8 @@ boolean_t pmap_pageidlezero(paddr_t);
paddr_t vtophys(vaddr_t);
/* Machine-specific functions. */
-void pmap_bootstrap(paddr_t ptaddr, u_int maxasn, u_long ncpuids);
-void pmap_emulate_reference(struct lwp *p, vaddr_t v,
- int user, int write);
+void pmap_bootstrap(paddr_t, u_int, u_long);
+int pmap_emulate_reference(struct lwp *, vaddr_t, int, int);
#ifdef _PMAP_MAY_USE_PROM_CONSOLE
int pmap_uses_prom_console(void);
#endif
diff --git a/sys/arch/alpha/include/pte.h b/sys/arch/alpha/include/pte.h
index e2be9a58f35..a08be807a43 100644
--- a/sys/arch/alpha/include/pte.h
+++ b/sys/arch/alpha/include/pte.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pte.h,v 1.27 2002/10/14 05:11:23 chs Exp $ */
+/* $NetBSD: pte.h,v 1.28 2003/08/24 17:52:30 chs Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -98,12 +98,12 @@ typedef alpha_pt_entry_t pt_entry_t;
#define PG_URE ALPHA_PTE_UR
#define PG_KWE ALPHA_PTE_KW
#define PG_UWE ALPHA_PTE_UW
-#define PG_PROT ALPHA_PTE_PROT
+#define PG_PROT (ALPHA_PTE_PROT | PG_EXEC | PG_FOE)
#define PG_RSVD 0x000000000000cc80 /* Reserved for hardware */
#define PG_WIRED 0x0000000000010000 /* Wired. [SOFTWARE] */
#define PG_PVLIST 0x0000000000020000 /* on pv list [SOFTWARE] */
#define PG_EXEC 0x0000000000040000 /* execute perms [SOFTWARE] */
-#define PG_FRAME ALPHA_PTE_RAME
+#define PG_FRAME ALPHA_PTE_PFN
#define PG_SHIFT 32
#define PG_PFNUM(x) ALPHA_PTE_TO_PFN(x)
diff --git a/sys/arch/i386/i386/freebsd_machdep.c b/sys/arch/i386/i386/freebsd_machdep.c
index 9f7787c1109..f7885dee81f 100644
--- a/sys/arch/i386/i386/freebsd_machdep.c
+++ b/sys/arch/i386/i386/freebsd_machdep.c
@@ -1,4 +1,4 @@
-/* $NetBSD: freebsd_machdep.c,v 1.37 2003/08/20 21:48:36 fvdl Exp $ */
+/* $NetBSD: freebsd_machdep.c,v 1.38 2003/08/24 17:52:30 chs Exp $ */
/*-
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: freebsd_machdep.c,v 1.37 2003/08/20 21:48:36 fvdl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: freebsd_machdep.c,v 1.38 2003/08/24 17:52:30 chs Exp $");
#if defined(_KERNEL_OPT)
#include "opt_vm86.h"
@@ -181,7 +181,7 @@ freebsd_sendsig(sig, mask, code)
tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
tf->tf_eip = (int)p->p_sigctx.ps_sigcode;
- tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
+ tf->tf_cs = GSEL(GUCODEBIG_SEL, SEL_UPL);
tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
tf->tf_esp = (int)fp;
tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
diff --git a/sys/arch/i386/i386/ibcs2_machdep.c b/sys/arch/i386/i386/ibcs2_machdep.c
index 37deec686a7..6c996afe40e 100644
--- a/sys/arch/i386/i386/ibcs2_machdep.c
+++ b/sys/arch/i386/i386/ibcs2_machdep.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ibcs2_machdep.c,v 1.22 2003/06/23 11:01:18 martin Exp $ */
+/* $NetBSD: ibcs2_machdep.c,v 1.23 2003/08/24 17:52:30 chs Exp $ */
/*-
* Copyright (c) 1997, 2000 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ibcs2_machdep.c,v 1.22 2003/06/23 11:01:18 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ibcs2_machdep.c,v 1.23 2003/08/24 17:52:30 chs Exp $");
#if defined(_KERNEL_OPT)
#include "opt_vm86.h"
@@ -85,6 +85,7 @@ ibcs2_setregs(l, epp, stack)
pcb->pcb_savefpu.sv_87.sv_env.en_cw = __iBCS2_NPXCW__;
tf = l->l_md.md_regs;
tf->tf_eax = 0x2000000; /* XXX base of heap */
+ tf->tf_cs = GSEL(LUCODEBIG_SEL, SEL_UPL);
}
/*
@@ -188,7 +189,7 @@ ibcs2_sendsig(sig, mask, code)
tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
tf->tf_eip = (int)catcher;
- tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
+ tf->tf_cs = GSEL(GUCODEBIG_SEL, SEL_UPL);
tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
tf->tf_esp = (int)fp;
tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c
index c5a5f230506..ee1dcaefd95 100644
--- a/sys/arch/i386/i386/machdep.c
+++ b/sys/arch/i386/i386/machdep.c
@@ -1,4 +1,4 @@
-/* $NetBSD: machdep.c,v 1.532 2003/08/20 21:48:38 fvdl Exp $ */
+/* $NetBSD: machdep.c,v 1.533 2003/08/24 17:52:30 chs 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.532 2003/08/20 21:48:38 fvdl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.533 2003/08/24 17:52:30 chs Exp $");
#include "opt_cputype.h"
#include "opt_ddb.h"
@@ -600,6 +600,7 @@ sendsig(sig, mask, code)
{
struct lwp *l = curlwp;
struct proc *p = l->l_proc;
+ struct pmap *pmap = vm_map_pmap(&p->p_vmspace->vm_map);
struct sigacts *ps = p->p_sigacts;
struct trapframe *tf;
struct sigframe *fp, frame;
@@ -716,7 +717,8 @@ sendsig(sig, mask, code)
tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
tf->tf_eip = (int)catcher;
- tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
+ tf->tf_cs = pmap->pm_hiexec > I386_MAX_EXE_ADDR ?
+ GSEL(GUCODEBIG_SEL, SEL_UPL) : GSEL(GUCODE_SEL, SEL_UPL);
tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
tf->tf_esp = (int)fp;
tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
@@ -730,6 +732,7 @@ sendsig(sig, mask, code)
void
cpu_upcall(struct lwp *l, int type, int nevents, int ninterrupted, void *sas, void *ap, void *sp, sa_upcall_t upcall)
{
+ struct pmap *pmap = vm_map_pmap(&l->l_proc->p_vmspace->vm_map);
struct saframe *sf, frame;
struct trapframe *tf;
@@ -757,7 +760,8 @@ cpu_upcall(struct lwp *l, int type, int nevents, int ninterrupted, void *sas, vo
tf->tf_fs = GSEL(GUDATA_SEL, SEL_UPL);
tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
- tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
+ tf->tf_cs = pmap->pm_hiexec > I386_MAX_EXE_ADDR ?
+ GSEL(GUCODEBIG_SEL, SEL_UPL) : GSEL(GUCODE_SEL, SEL_UPL);
tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
}
@@ -1227,6 +1231,7 @@ setregs(l, pack, stack)
struct exec_package *pack;
u_long stack;
{
+ struct pmap *pmap = vm_map_pmap(&l->l_proc->p_vmspace->vm_map);
struct pcb *pcb = &l->l_addr->u_pcb;
struct trapframe *tf;
@@ -1260,7 +1265,8 @@ setregs(l, pack, stack)
tf->tf_ecx = 0;
tf->tf_eax = 0;
tf->tf_eip = pack->ep_entry;
- tf->tf_cs = LSEL(LUCODE_SEL, SEL_UPL);
+ tf->tf_cs = pmap->pm_hiexec > I386_MAX_EXE_ADDR ?
+ LSEL(LUCODEBIG_SEL, SEL_UPL) : LSEL(LUCODE_SEL, SEL_UPL);
tf->tf_eflags = PSL_USERSET;
tf->tf_esp = stack;
tf->tf_ss = LSEL(LUDATA_SEL, SEL_UPL);
@@ -1460,7 +1466,9 @@ initgdt(union descriptor *tgdt)
/* make gdt gates and memory segments */
setsegment(&gdt[GCODE_SEL].sd, 0, 0xfffff, SDT_MEMERA, SEL_KPL, 1, 1);
setsegment(&gdt[GDATA_SEL].sd, 0, 0xfffff, SDT_MEMRWA, SEL_KPL, 1, 1);
- setsegment(&gdt[GUCODE_SEL].sd, 0, x86_btop(VM_MAXUSER_ADDRESS) - 1,
+ setsegment(&gdt[GUCODE_SEL].sd, 0, x86_btop(I386_MAX_EXE_ADDR) - 1,
+ SDT_MEMERA, SEL_UPL, 1, 1);
+ setsegment(&gdt[GUCODEBIG_SEL].sd, 0, x86_btop(VM_MAXUSER_ADDRESS) - 1,
SDT_MEMERA, SEL_UPL, 1, 1);
setsegment(&gdt[GUDATA_SEL].sd, 0, x86_btop(VM_MAXUSER_ADDRESS) - 1,
SDT_MEMRWA, SEL_UPL, 1, 1);
@@ -1980,6 +1988,7 @@ init386(first_avail)
SDT_SYS386CGT, SEL_UPL, GSEL(GCODE_SEL, SEL_KPL));
ldt[LUCODE_SEL] = gdt[GUCODE_SEL];
+ ldt[LUCODEBIG_SEL] = gdt[GUCODEBIG_SEL];
ldt[LUDATA_SEL] = gdt[GUDATA_SEL];
ldt[LSOL26CALLS_SEL] = ldt[LBSDICALLS_SEL] = ldt[LSYS5CALLS_SEL];
diff --git a/sys/arch/i386/i386/pmap.c b/sys/arch/i386/i386/pmap.c
index c1a2a2a00cf..d55b590b77f 100644
--- a/sys/arch/i386/i386/pmap.c
+++ b/sys/arch/i386/i386/pmap.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.156 2003/07/22 13:55:31 yamt Exp $ */
+/* $NetBSD: pmap.c,v 1.157 2003/08/24 17:52:31 chs Exp $ */
/*
*
@@ -60,7 +60,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.156 2003/07/22 13:55:31 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.157 2003/08/24 17:52:31 chs Exp $");
#include "opt_cputype.h"
#include "opt_user_ldt.h"
@@ -703,6 +703,68 @@ pmap_unmap_ptes(pmap)
}
}
+__inline static void
+pmap_exec_account(struct pmap *pm, vaddr_t va, pt_entry_t opte, pt_entry_t npte)
+{
+ if (curproc == NULL || curproc->p_vmspace == NULL ||
+ pm != vm_map_pmap(&curproc->p_vmspace->vm_map))
+ return;
+
+ if ((opte ^ npte) & PG_X)
+ pmap_update_pg(va);
+
+ /*
+ * Executability was removed on the last executable change.
+ * Reset the code segment to something conservative and
+ * let the trap handler deal with setting the right limit.
+ * We can't do that because of locking constraints on the vm map.
+ */
+
+ if ((opte & PG_X) && (npte & PG_X) == 0 && va == pm->pm_hiexec) {
+ struct trapframe *tf = curlwp->l_md.md_regs;
+ struct pcb *pcb = &curlwp->l_addr->u_pcb;
+
+ pcb->pcb_cs = tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
+ pm->pm_hiexec = I386_MAX_EXE_ADDR;
+ }
+}
+
+/*
+ * Fixup the code segment to cover all potential executable mappings.
+ * returns 0 if no changes to the code segment were made.
+ */
+
+int
+pmap_exec_fixup(struct vm_map *map, struct trapframe *tf, struct pcb *pcb)
+{
+ struct vm_map_entry *ent;
+ struct pmap *pm = vm_map_pmap(map);
+ vaddr_t va = 0;
+
+ vm_map_lock_read(map);
+ for (ent = (&map->header)->next; ent != &map->header; ent = ent->next) {
+
+ /*
+ * This entry has greater va than the entries before.
+ * We need to make it point to the last page, not past it.
+ */
+
+ if (ent->protection & VM_PROT_EXECUTE)
+ va = trunc_page(ent->end) - PAGE_SIZE;
+ }
+ vm_map_unlock_read(map);
+ if (va == pm->pm_hiexec)
+ return (0);
+
+ pm->pm_hiexec = va;
+ if (pm->pm_hiexec > I386_MAX_EXE_ADDR) {
+ pcb->pcb_cs = tf->tf_cs = GSEL(GUCODEBIG_SEL, SEL_UPL);
+ } else {
+ pcb->pcb_cs = tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
+ }
+ return (1);
+}
+
/*
* p m a p k e n t e r f u n c t i o n s
*
@@ -836,13 +898,13 @@ pmap_bootstrap(kva_start)
*/
protection_codes[VM_PROT_NONE] = 0; /* --- */
- protection_codes[VM_PROT_EXECUTE] = PG_RO; /* --x */
+ protection_codes[VM_PROT_EXECUTE] = PG_X; /* --x */
protection_codes[VM_PROT_READ] = PG_RO; /* -r- */
- protection_codes[VM_PROT_READ|VM_PROT_EXECUTE] = PG_RO; /* -rx */
+ protection_codes[VM_PROT_READ|VM_PROT_EXECUTE] = PG_RO|PG_X;/* -rx */
protection_codes[VM_PROT_WRITE] = PG_RW; /* w-- */
- protection_codes[VM_PROT_WRITE|VM_PROT_EXECUTE] = PG_RW;/* w-x */
+ protection_codes[VM_PROT_WRITE|VM_PROT_EXECUTE] = PG_RW|PG_X;/* w-x */
protection_codes[VM_PROT_WRITE|VM_PROT_READ] = PG_RW; /* wr- */
- protection_codes[VM_PROT_ALL] = PG_RW; /* wrx */
+ protection_codes[VM_PROT_ALL] = PG_RW|PG_X; /* wrx */
/*
* now we init the kernel's pmap
@@ -1614,6 +1676,7 @@ pmap_create()
pmap->pm_stats.wired_count = 0;
pmap->pm_stats.resident_count = 1; /* count the PDP allocd below */
pmap->pm_ptphint = NULL;
+ pmap->pm_hiexec = 0;
pmap->pm_flags = 0;
/* init the LDT */
@@ -2114,6 +2177,7 @@ pmap_remove_ptes(pmap, ptp, ptpva, startva, endva, cpumaskp, flags)
/* atomically save the old PTE and zap! it */
opte = x86_atomic_testset_ul(pte, 0);
+ pmap_exec_account(pmap, startva, opte, 0);
if (opte & PG_W)
pmap->pm_stats.wired_count--;
@@ -2196,6 +2260,7 @@ pmap_remove_pte(pmap, ptp, pte, va, cpumaskp, flags)
/* atomically save the old PTE and zap! it */
opte = x86_atomic_testset_ul(pte, 0);
+ pmap_exec_account(pmap, va, opte, 0);
if (opte & PG_W)
pmap->pm_stats.wired_count--;
@@ -3042,6 +3107,7 @@ enter_now:
if (ptp)
ptp->wire_count += ptpdelta;
npte = pa | protection_codes[prot] | PG_V;
+ pmap_exec_account(pmap, va, opte, npte);
if (pvh)
npte |= PG_PVLIST;
if (wired)
diff --git a/sys/arch/i386/i386/svr4_machdep.c b/sys/arch/i386/i386/svr4_machdep.c
index 18e207e3d21..c4e1a28831e 100644
--- a/sys/arch/i386/i386/svr4_machdep.c
+++ b/sys/arch/i386/i386/svr4_machdep.c
@@ -1,4 +1,4 @@
-/* $NetBSD: svr4_machdep.c,v 1.68 2003/08/20 21:48:41 fvdl Exp $ */
+/* $NetBSD: svr4_machdep.c,v 1.69 2003/08/24 17:52:32 chs Exp $ */
/*-
* Copyright (c) 1994, 2000 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: svr4_machdep.c,v 1.68 2003/08/20 21:48:41 fvdl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: svr4_machdep.c,v 1.69 2003/08/24 17:52:32 chs Exp $");
#if defined(_KERNEL_OPT)
#include "opt_vm86.h"
@@ -125,12 +125,14 @@ svr4_setregs(l, epp, stack)
u_long stack;
{
register struct pcb *pcb = &l->l_addr->u_pcb;
+ struct trapframe *tf = l->l_md.md_regs;
setregs(l, epp, stack);
if (i386_use_fxsave)
pcb->pcb_savefpu.sv_xmm.sv_env.en_cw = __SVR4_NPXCW__;
else
pcb->pcb_savefpu.sv_87.sv_env.en_cw = __SVR4_NPXCW__;
+ tf->tf_cs = GSEL(LUCODEBIG_SEL, SEL_UPL);
}
void *
@@ -436,7 +438,7 @@ svr4_sendsig(sig, mask, code)
tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
tf->tf_eip = (int)p->p_sigctx.ps_sigcode;
- tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
+ tf->tf_cs = GSEL(GUCODEBIG_SEL, SEL_UPL);
tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
tf->tf_esp = (int)fp;
tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
diff --git a/sys/arch/i386/i386/trap.c b/sys/arch/i386/i386/trap.c
index 6d698283546..ed22dfd1a02 100644
--- a/sys/arch/i386/i386/trap.c
+++ b/sys/arch/i386/i386/trap.c
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.184 2003/08/20 21:48:43 fvdl Exp $ */
+/* $NetBSD: trap.c,v 1.185 2003/08/24 17:52:32 chs Exp $ */
/*-
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -75,7 +75,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.184 2003/08/20 21:48:43 fvdl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.185 2003/08/24 17:52:32 chs Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@@ -393,6 +393,12 @@ copyfault:
goto out;
}
#endif
+ /* If pmap_exec_fixup does something, let's retry the trap. */
+ if (pmap_exec_fixup(&p->p_vmspace->vm_map, frame,
+ &l->l_addr->u_pcb)) {
+ goto out;
+ }
+
case T_TSSFLT|T_USER:
case T_SEGNPFLT|T_USER:
case T_STKFLT|T_USER:
diff --git a/sys/arch/i386/include/pcb.h b/sys/arch/i386/include/pcb.h
index 73c6888ddb3..cd6d3b2e0a2 100644
--- a/sys/arch/i386/include/pcb.h
+++ b/sys/arch/i386/include/pcb.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pcb.h,v 1.34 2003/08/07 16:27:59 agc Exp $ */
+/* $NetBSD: pcb.h,v 1.35 2003/08/24 17:52:33 chs Exp $ */
/*-
* Copyright (c) 1998 The NetBSD Foundation, Inc.
@@ -95,6 +95,7 @@ struct pcb {
#define pcb_cr3 pcb_tss.tss_cr3
#define pcb_esp pcb_tss.tss_esp
#define pcb_ebp pcb_tss.tss_ebp
+#define pcb_cs pcb_tss.__tss_cs
#define pcb_ldt_sel pcb_tss.tss_ldt
int pcb_cr0; /* saved image of CR0 */
int pcb_cr2; /* page fault address (CR2) */
diff --git a/sys/arch/i386/include/pmap.h b/sys/arch/i386/include/pmap.h
index cd7ae103322..cc38cdae994 100644
--- a/sys/arch/i386/include/pmap.h
+++ b/sys/arch/i386/include/pmap.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.74 2003/07/22 13:55:33 yamt Exp $ */
+/* $NetBSD: pmap.h,v 1.75 2003/08/24 17:52:33 chs Exp $ */
/*
*
@@ -206,7 +206,7 @@
#define PG_W PG_AVAIL1 /* "wired" mapping */
#define PG_PVLIST PG_AVAIL2 /* mapping has entry on pvlist */
-/* PG_AVAIL3 not used */
+#define PG_X PG_AVAIL3 /* executable mapping */
/*
* Number of PTE's per cache line. 4 byte pte, 32-byte cache line
@@ -247,6 +247,7 @@ struct pmap {
struct vm_page *pm_ptphint; /* pointer to a PTP in our pmap */
struct pmap_statistics pm_stats; /* pmap stats (lck by object lock) */
+ vaddr_t pm_hiexec; /* highest executable mapping */
int pm_flags; /* see below */
union descriptor *pm_ldt; /* user-set LDT */
@@ -346,6 +347,8 @@ void pmap_remove __P((struct pmap *, vaddr_t, vaddr_t));
boolean_t pmap_test_attrs __P((struct vm_page *, int));
void pmap_write_protect __P((struct pmap *, vaddr_t,
vaddr_t, vm_prot_t));
+int pmap_exec_fixup(struct vm_map *, struct trapframe *,
+ struct pcb *);
vaddr_t reserve_dumppages __P((vaddr_t)); /* XXX: not a pmap fn */
diff --git a/sys/arch/i386/include/pte.h b/sys/arch/i386/include/pte.h
index e085955fe17..3d85f942559 100644
--- a/sys/arch/i386/include/pte.h
+++ b/sys/arch/i386/include/pte.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pte.h,v 1.13 2003/04/02 07:35:59 thorpej Exp $ */
+/* $NetBSD: pte.h,v 1.14 2003/08/24 17:52:33 chs Exp $ */
/*
*
@@ -163,7 +163,7 @@ typedef u_int32_t pt_entry_t; /* PTE */
#define PG_RO 0x00000000 /* read-only page */
#define PG_RW 0x00000002 /* read-write page */
#define PG_u 0x00000004 /* user accessible page */
-#define PG_PROT 0x00000006 /* all protection bits */
+#define PG_PROT 0x00000806 /* all protection bits */
#define PG_N 0x00000018 /* non-cacheable */
#define PG_U 0x00000020 /* has been used */
#define PG_M 0x00000040 /* has been modified */
diff --git a/sys/arch/i386/include/segments.h b/sys/arch/i386/include/segments.h
index e797320c57b..223bcb6c290 100644
--- a/sys/arch/i386/include/segments.h
+++ b/sys/arch/i386/include/segments.h
@@ -1,4 +1,4 @@
-/* $NetBSD: segments.h,v 1.37 2003/08/07 16:28:00 agc Exp $ */
+/* $NetBSD: segments.h,v 1.38 2003/08/24 17:52:33 chs Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@@ -288,7 +288,8 @@ void idt_vec_free __P((int));
#define GPNPBIOSTRAMP_SEL 17
#define GTRAPTSS_SEL 18
#define GIPITSS_SEL 19
-#define NGDT 20
+#define GUCODEBIG_SEL 20 /* User code with executable stack */
+#define NGDT 21
/*
* Entries in the Local Descriptor Table (LDT)
@@ -298,6 +299,7 @@ void idt_vec_free __P((int));
#define LUCODE_SEL 2 /* User code descriptor */
#define LUDATA_SEL 3 /* User data descriptor */
#define LSOL26CALLS_SEL 4 /* Solaris 2.6 system call gate */
+#define LUCODEBIG_SEL 5 /* User code with executable stack */
#define LBSDICALLS_SEL 16 /* BSDI system call gate */
#define NLDT 17
diff --git a/sys/arch/i386/include/vmparam.h b/sys/arch/i386/include/vmparam.h
index 22c52062ad3..4988fbf12a0 100644
--- a/sys/arch/i386/include/vmparam.h
+++ b/sys/arch/i386/include/vmparam.h
@@ -1,4 +1,4 @@
-/* $NetBSD: vmparam.h,v 1.53 2003/08/07 16:28:00 agc Exp $ */
+/* $NetBSD: vmparam.h,v 1.54 2003/08/24 17:52:33 chs Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
@@ -75,6 +75,14 @@
#endif
/*
+ * IA-32 can't do per-page execute permission, so instead we implement
+ * two executable segments for %cs, one that covers everything and one
+ * that excludes some of the address space (currently just the stack).
+ * I386_MAX_EXE_ADDR is the upper boundary for the smaller segment.
+ */
+#define I386_MAX_EXE_ADDR (USRSTACK - MAXSSIZ)
+
+/*
* Size of shared memory map
*/
#ifndef SHMMAXPGS
@@ -107,7 +115,7 @@
#define __HAVE_TOPDOWN_VM
#ifdef USE_TOPDOWN_VM
#define VM_DEFAULT_ADDRESS(da, sz) \
- trunc_page(VM_MAXUSER_ADDRESS - MAXSSIZ - (sz))
+ trunc_page(USRSTACK - MAXSSIZ - (sz))
#endif
/* XXX max. amount of KVM to be used by buffers. */
diff --git a/sys/arch/powerpc/ibm4xx/pmap.c b/sys/arch/powerpc/ibm4xx/pmap.c
index 414c8d5a744..09d0b5678db 100644
--- a/sys/arch/powerpc/ibm4xx/pmap.c
+++ b/sys/arch/powerpc/ibm4xx/pmap.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.25 2003/08/12 05:06:58 matt Exp $ */
+/* $NetBSD: pmap.c,v 1.26 2003/08/24 17:52:34 chs Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.25 2003/08/12 05:06:58 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.26 2003/08/24 17:52:34 chs Exp $");
#include <sys/param.h>
#include <sys/malloc.h>
@@ -827,13 +827,8 @@ pmap_enter(struct pmap *pm, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
/*
* Generate TTE.
- *
- * XXXX
- *
- * Since the kernel does not handle execution privileges properly,
- * we will handle read and execute permissions together.
*/
- tte = TTE_PA(pa) | TTE_EX;
+ tte = TTE_PA(pa);
/* XXXX -- need to support multiple page sizes. */
tte |= TTE_SZ_16K;
#ifdef DIAGNOSTIC
@@ -859,6 +854,9 @@ pmap_enter(struct pmap *pm, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
if (flags & VM_PROT_WRITE)
tte |= TTE_WR;
+ if (flags & VM_PROT_EXECUTE)
+ tte |= TTE_EX;
+
/*
* Now record mapping for later back-translation.
*/
@@ -1051,21 +1049,31 @@ void
pmap_protect(struct pmap *pm, vaddr_t sva, vaddr_t eva, vm_prot_t prot)
{
volatile u_int *ptp;
- int s;
+ int s, bic;
- if (prot & VM_PROT_READ) {
- s = splvm();
- while (sva < eva) {
- if ((ptp = pte_find(pm, sva)) != NULL) {
- *ptp &= ~TTE_WR;
- ppc4xx_tlb_flush(sva, pm->pm_ctx);
- }
- sva += PAGE_SIZE;
- }
- splx(s);
+ if ((prot & VM_PROT_READ) == 0) {
+ pmap_remove(pm, sva, eva);
return;
}
- pmap_remove(pm, sva, eva);
+ bic = 0;
+ if ((prot & VM_PROT_WRITE) == 0) {
+ bic |= TTE_WR;
+ }
+ if ((prot & VM_PROT_EXECUTE) == 0) {
+ bic |= TTE_EX;
+ }
+ if (bic == 0) {
+ return;
+ }
+ s = splvm();
+ while (sva < eva) {
+ if ((ptp = pte_find(pm, sva)) != NULL) {
+ *ptp &= ~bic;
+ ppc4xx_tlb_flush(sva, pm->pm_ctx);
+ }
+ sva += PAGE_SIZE;
+ }
+ splx(s);
}
boolean_t
@@ -1118,14 +1126,14 @@ pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
pm = pv->pv_pm;
va = pv->pv_va;
- pmap_protect(pm, va, va+PAGE_SIZE, prot);
+ pmap_protect(pm, va, va + PAGE_SIZE, prot);
}
/* Now check the head pv */
if (pvh->pv_pm) {
pv = pvh;
pm = pv->pv_pm;
va = pv->pv_va;
- pmap_protect(pm, va, va+PAGE_SIZE, prot);
+ pmap_protect(pm, va, va + PAGE_SIZE, prot);
}
}
@@ -1165,7 +1173,6 @@ pmap_procwr(struct proc *p, vaddr_t va, size_t len)
struct pmap *pm = p->p_vmspace->vm_map.pmap;
int msr, ctx, opid, step;
-
step = CACHELINESIZE;
/*
@@ -1207,7 +1214,8 @@ ppc4xx_tlb_flush(vaddr_t va, int pid)
u_long msr;
/* If there's no context then it can't be mapped. */
- if (!pid) return;
+ if (!pid)
+ return;
asm("mfpid %1;" /* Save PID */
"mfmsr %2;" /* Save MSR */
diff --git a/sys/arch/powerpc/ibm4xx/trap.c b/sys/arch/powerpc/ibm4xx/trap.c
index 6c8f9a5edcf..1e4d29a25b4 100644
--- a/sys/arch/powerpc/ibm4xx/trap.c
+++ b/sys/arch/powerpc/ibm4xx/trap.c
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.14 2003/07/15 02:54:44 lukem Exp $ */
+/* $NetBSD: trap.c,v 1.15 2003/08/24 17:52:34 chs Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.14 2003/07/15 02:54:44 lukem Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.15 2003/08/24 17:52:34 chs Exp $");
#include "opt_altivec.h"
#include "opt_ddb.h"
@@ -246,13 +246,13 @@ trap(struct trapframe *frame)
}
KERNEL_PROC_UNLOCK(l);
break;
+
case EXC_ITMISS|EXC_USER:
case EXC_ISI|EXC_USER:
KERNEL_PROC_LOCK(l);
- ftype = VM_PROT_READ | VM_PROT_EXECUTE;
+ ftype = VM_PROT_EXECUTE;
DBPRINTF(TDB_ALL,
- ("trap(EXC_ISI|EXC_USER) at %lx %s fault on %lx tf %p\n",
- frame->srr0, (ftype & VM_PROT_WRITE) ? "write" : "read",
+ ("trap(EXC_ISI|EXC_USER) at %lx execute fault tf %p\n",
frame->srr0, frame));
rv = uvm_fault(&p->p_vmspace->vm_map, trunc_page(frame->srr0),
0, ftype);
diff --git a/sys/arch/powerpc/include/oea/pmap.h b/sys/arch/powerpc/include/oea/pmap.h
index 67aa2cb1bc2..61a66ff7b47 100644
--- a/sys/arch/powerpc/include/oea/pmap.h
+++ b/sys/arch/powerpc/include/oea/pmap.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.4 2003/04/09 22:37:32 matt Exp $ */
+/* $NetBSD: pmap.h,v 1.5 2003/08/24 17:52:34 chs Exp $ */
/*-
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -42,6 +42,7 @@
*/
struct pmap {
register_t pm_sr[16]; /* segments used in this pmap */
+ int pm_exec[16]; /* counts of exec mappings */
int pm_refs; /* ref count */
struct pmap_statistics pm_stats; /* pmap statistics */
unsigned int pm_evictions; /* pvo's not in page table */
@@ -74,7 +75,7 @@ pmap_remove_all(struct pmap *pmap)
/* Nothing. */
}
-void pmap_bootstrap (vaddr_t kernelstart, vaddr_t kernelend);
+void pmap_bootstrap (vaddr_t, vaddr_t);
boolean_t pmap_extract (struct pmap *, vaddr_t, paddr_t *);
boolean_t pmap_query_bit (struct vm_page *, int);
boolean_t pmap_clear_bit (struct vm_page *, int);
@@ -84,16 +85,15 @@ boolean_t pmap_pageidlezero (paddr_t);
void pmap_syncicache (paddr_t, psize_t);
#define PMAP_NEED_PROCWR
-void pmap_procwr (struct proc *, vaddr_t, size_t);
+void pmap_procwr(struct proc *, vaddr_t, size_t);
-int pmap_pte_spill(struct pmap *, vaddr_t);
+int pmap_pte_spill(struct pmap *, vaddr_t, boolean_t);
#define PMAP_NC 0x1000
#define PMAP_STEAL_MEMORY
static __inline paddr_t vtophys (vaddr_t);
-#if 1
/*
* Alternate mapping hooks for pool pages. Avoids thrashing the TLB.
*
@@ -103,10 +103,8 @@ static __inline paddr_t vtophys (vaddr_t);
*/
#define PMAP_MAP_POOLPAGE(pa) (pa)
#define PMAP_UNMAP_POOLPAGE(pa) (pa)
-#endif
#define POOL_VTOPHYS(va) vtophys((vaddr_t) va)
-
static __inline paddr_t
vtophys(vaddr_t va)
{
diff --git a/sys/arch/powerpc/include/oea/pte.h b/sys/arch/powerpc/include/oea/pte.h
index 7bca941be09..79370cc82a8 100644
--- a/sys/arch/powerpc/include/oea/pte.h
+++ b/sys/arch/powerpc/include/oea/pte.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pte.h,v 1.2 2003/02/05 07:05:19 matt Exp $ */
+/* $NetBSD: pte.h,v 1.3 2003/08/24 17:52:34 chs Exp $ */
/*-
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -77,7 +77,7 @@ struct pteg {
#define PTE_RW PTE_BW
#define PTE_RO PTE_BR
-#define PTE_EXEC 0x00000200 /* pseudo bit in attrs; page is exec */
+#define PTE_EXEC 0x00000200 /* pseudo bit; page is exec */
/*
* Extract bits from address
diff --git a/sys/arch/powerpc/oea/pmap.c b/sys/arch/powerpc/oea/pmap.c
index 6794ee0f864..86bdd7e7fd5 100644
--- a/sys/arch/powerpc/oea/pmap.c
+++ b/sys/arch/powerpc/oea/pmap.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.13 2003/08/12 05:06:57 matt Exp $ */
+/* $NetBSD: pmap.c,v 1.14 2003/08/24 17:52:35 chs Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -67,7 +67,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.13 2003/08/12 05:06:57 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.14 2003/08/24 17:52:35 chs Exp $");
#include "opt_altivec.h"
#include "opt_pmap.h"
@@ -245,6 +245,9 @@ STATIC int pmap_pvo_enter(pmap_t, struct pool *, struct pvo_head *,
STATIC void pmap_pvo_remove(struct pvo_entry *, int);
STATIC struct pvo_entry *pmap_pvo_find_va(pmap_t, vaddr_t, int *);
STATIC volatile struct pte *pmap_pvo_to_pte(const struct pvo_entry *, int);
+#define pmap_pvo_reclaim(pm) NULL
+STATIC void pvo_set_exec(struct pvo_entry *);
+STATIC void pvo_clear_exec(struct pvo_entry *);
STATIC void tlbia(void);
@@ -760,8 +763,9 @@ pmap_pte_insert(int ptegidx, struct pte *pvo_pt)
* kernel's pte entries. In either case, interrupts are already
* disabled.
*/
+
int
-pmap_pte_spill(struct pmap *pm, vaddr_t addr)
+pmap_pte_spill(struct pmap *pm, vaddr_t addr, boolean_t exec)
{
struct pvo_entry *source_pvo, *victim_pvo, *next_pvo;
struct pvo_entry *pvo;
@@ -846,6 +850,9 @@ pmap_pte_spill(struct pmap *pm, vaddr_t addr)
return 1;
}
source_pvo = pvo;
+ if (exec && !PVO_ISEXECUTABLE(source_pvo)) {
+ return 0;
+ }
if (victim_pvo != NULL)
break;
}
@@ -970,14 +977,12 @@ pmap_real_memory(paddr_t *start, psize_t *size)
void
pmap_init(void)
{
- int s;
#ifdef __HAVE_PMAP_PHYSSEG
struct pvo_tqhead *pvoh;
int bank;
long sz;
char *attr;
- s = splvm();
pvoh = pmap_physseg.pvoh;
attr = pmap_physseg.attrs;
for (bank = 0; bank < vm_nphysseg; bank++) {
@@ -989,10 +994,8 @@ pmap_init(void)
*attr = 0;
}
}
- splx(s);
#endif
- s = splvm();
pool_init(&pmap_mpvo_pool, sizeof(struct pvo_entry),
sizeof(struct pvo_entry), 0, 0, "pmap_mpvopl",
&pmap_pool_mallocator);
@@ -1000,7 +1003,6 @@ pmap_init(void)
pool_setlowat(&pmap_mpvo_pool, 1008);
pmap_initialized = 1;
- splx(s);
#ifdef PMAPCOUNTERS
evcnt_attach_static(&pmap_evcnt_mappings);
@@ -1138,7 +1140,8 @@ pmap_pinit(pmap_t pm)
hash &= PTE_VSID >> (PTE_VSID_SHFT + SR_KEY_LEN);
pmap_vsid_bitmap[n] |= mask;
for (i = 0; i < 16; i++)
- pm->pm_sr[i] = VSID_MAKE(i, hash) | SR_PRKEY;
+ pm->pm_sr[i] = VSID_MAKE(i, hash) | SR_PRKEY |
+ SR_NOEXEC;
return;
}
panic("pmap_pinit: out of segments");
@@ -1493,10 +1496,8 @@ pmap_pvo_enter(pmap_t pm, struct pool *pl, struct pvo_head *pvo_head,
pvo = pool_get(pl, poolflags);
msr = pmap_interrupts_off();
if (pvo == NULL) {
-#if 0
pvo = pmap_pvo_reclaim(pm);
if (pvo == NULL) {
-#endif
if ((flags & PMAP_CANFAIL) == 0)
panic("pmap_pvo_enter: failed");
#if defined(DIAGNOSTIC) || defined(DEBUG) || defined(PMAPCHECK)
@@ -1504,16 +1505,14 @@ pmap_pvo_enter(pmap_t pm, struct pool *pl, struct pvo_head *pvo_head,
#endif
pmap_interrupts_restore(msr);
return ENOMEM;
-#if 0
}
-#endif
}
pvo->pvo_vaddr = va;
pvo->pvo_pmap = pm;
pvo->pvo_vaddr &= ~ADDR_POFF;
if (flags & VM_PROT_EXECUTE) {
PMAPCOUNT(exec_mappings);
- pvo->pvo_vaddr |= PVO_EXECUTABLE;
+ pvo_set_exec(pvo);
}
if (flags & PMAP_WIRED)
pvo->pvo_vaddr |= PVO_WIRED;
@@ -1559,7 +1558,7 @@ pmap_pvo_enter(pmap_t pm, struct pool *pl, struct pvo_head *pvo_head,
* If this is a kernel page, make sure it's active.
*/
if (pm == pmap_kernel()) {
- i = pmap_pte_spill(pm, va);
+ i = pmap_pte_spill(pm, va, FALSE);
KASSERT(i);
}
}
@@ -1611,7 +1610,13 @@ pmap_pvo_remove(struct pvo_entry *pvo, int pteidx)
}
/*
- * Update our statistics
+ * Account for executable mappings.
+ */
+ if (PVO_ISEXECUTABLE(pvo))
+ pvo_clear_exec(pvo);
+
+ /*
+ * Update our statistics.
*/
pvo->pvo_pmap->pm_stats.resident_count--;
if (pvo->pvo_pte.pte_lo & PVO_WIRED)
@@ -1645,6 +1650,48 @@ pmap_pvo_remove(struct pvo_entry *pvo, int pteidx)
}
/*
+ * Mark a mapping as executable.
+ * If this is the first executable mapping in the segment,
+ * clear the noexec flag.
+ */
+STATIC void
+pvo_set_exec(struct pvo_entry *pvo)
+{
+ struct pmap *pm = pvo->pvo_pmap;
+ int sr;
+
+ if (pm == pmap_kernel() || PVO_ISEXECUTABLE(pvo)) {
+ return;
+ }
+ pvo->pvo_vaddr |= PVO_EXECUTABLE;
+ sr = PVO_VADDR(pvo) >> ADDR_SR_SHFT;
+ if (pm->pm_exec[sr]++ == 0) {
+ pm->pm_sr[sr] &= ~SR_NOEXEC;
+ }
+}
+
+/*
+ * Mark a mapping as non-executable.
+ * If this was the last executable mapping in the segment,
+ * set the noexec flag.
+ */
+STATIC void
+pvo_clear_exec(struct pvo_entry *pvo)
+{
+ struct pmap *pm = pvo->pvo_pmap;
+ int sr;
+
+ if (pm == pmap_kernel() || !PVO_ISEXECUTABLE(pvo)) {
+ return;
+ }
+ pvo->pvo_vaddr &= ~PVO_EXECUTABLE;
+ sr = PVO_VADDR(pvo) >> ADDR_SR_SHFT;
+ if (--pm->pm_exec[sr] == 0) {
+ pm->pm_sr[sr] |= SR_NOEXEC;
+ }
+}
+
+/*
* Insert physical page at pa into the given pmap at virtual address va.
*/
int
@@ -1655,7 +1702,6 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
struct vm_page *pg;
struct pool *pl;
register_t pte_lo;
- int s;
int error;
u_int pvo_flags;
u_int was_exec = 0;
@@ -1714,17 +1760,6 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
if (flags & (VM_PROT_READ|VM_PROT_WRITE))
pte_lo |= PTE_REF;
-#if 0
- if (pm == pmap_kernel()) {
- if ((prot & (VM_PROT_READ|VM_PROT_WRITE)) == VM_PROT_READ)
- printf("pmap_pvo_enter: Kernel RO va %#lx pa %#lx\n",
- va, pa);
- if ((prot & (VM_PROT_READ|VM_PROT_WRITE)) == VM_PROT_NONE)
- printf("pmap_pvo_enter: Kernel N/A va %#lx pa %#lx\n",
- va, pa);
- }
-#endif
-
/*
* We need to know if this page can be executable
*/
@@ -1734,9 +1769,7 @@ pmap_enter(pmap_t pm, vaddr_t va, paddr_t pa, vm_prot_t prot, int flags)
* Record mapping for later back-translation and pte spilling.
* This will overwrite any existing mapping.
*/
- s = splvm();
error = pmap_pvo_enter(pm, pl, pvo_head, va, pa, pte_lo, flags);
- splx(s);
/*
* Flush the real page from the instruction cache if this page is
@@ -1774,9 +1807,7 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot)
{
struct mem_region *mp;
register_t pte_lo;
- register_t msr;
int error;
- int s;
if (va < VM_MIN_KERNEL_ADDRESS)
panic("pmap_kenter_pa: attempt to enter "
@@ -1808,12 +1839,8 @@ pmap_kenter_pa(vaddr_t va, paddr_t pa, vm_prot_t prot)
/*
* We don't care about REF/CHG on PVOs on the unmanaged list.
*/
- s = splvm();
- msr = pmap_interrupts_off();
error = pmap_pvo_enter(pmap_kernel(), &pmap_upvo_pool,
&pmap_pvo_kunmanaged, va, pa, pte_lo, prot|PMAP_WIRED);
- pmap_interrupts_restore(msr);
- splx(s);
if (error != 0)
panic("pmap_kenter_pa: failed to enter va %#lx pa %#lx: %d",
@@ -1840,18 +1867,15 @@ pmap_remove(pmap_t pm, vaddr_t va, vaddr_t endva)
struct pvo_entry *pvo;
register_t msr;
int pteidx;
- int s;
+ msr = pmap_interrupts_off();
for (; va < endva; va += PAGE_SIZE) {
- s = splvm();
- msr = pmap_interrupts_off();
pvo = pmap_pvo_find_va(pm, va, &pteidx);
if (pvo != NULL) {
pmap_pvo_remove(pvo, pteidx);
}
- pmap_interrupts_restore(msr);
- splx(s);
}
+ pmap_interrupts_restore(msr);
}
/*
@@ -1862,7 +1886,6 @@ pmap_extract(pmap_t pm, vaddr_t va, paddr_t *pap)
{
struct pvo_entry *pvo;
register_t msr;
- int s;
/*
* If this is a kernel pmap lookup, also check the battable
@@ -1884,7 +1907,6 @@ pmap_extract(pmap_t pm, vaddr_t va, paddr_t *pap)
return FALSE;
}
- s = splvm();
msr = pmap_interrupts_off();
pvo = pmap_pvo_find_va(pm, va & ~ADDR_POFF, NULL);
if (pvo != NULL) {
@@ -1892,15 +1914,11 @@ pmap_extract(pmap_t pm, vaddr_t va, paddr_t *pap)
*pap = (pvo->pvo_pte.pte_lo & PTE_RPGN) | (va & ADDR_POFF);
}
pmap_interrupts_restore(msr);
- splx(s);
return pvo != NULL;
}
/*
* Lower the protection on the specified range of this pmap.
- *
- * There are only two cases: either the protection is going to 0,
- * or it is going to read-only.
*/
void
pmap_protect(pmap_t pm, vaddr_t va, vaddr_t endva, vm_prot_t prot)
@@ -1908,14 +1926,13 @@ pmap_protect(pmap_t pm, vaddr_t va, vaddr_t endva, vm_prot_t prot)
struct pvo_entry *pvo;
volatile struct pte *pt;
register_t msr;
- int s;
int pteidx;
/*
* Since this routine only downgrades protection, we should
- * always be called without WRITE permisison.
+ * always be called with at least one bit not set.
*/
- KASSERT((prot & VM_PROT_WRITE) == 0);
+ KASSERT(prot != VM_PROT_ALL);
/*
* If there is no protection, this is equivalent to
@@ -1926,9 +1943,7 @@ pmap_protect(pmap_t pm, vaddr_t va, vaddr_t endva, vm_prot_t prot)
return;
}
- s = splvm();
msr = pmap_interrupts_off();
-
for (; va < endva; va += PAGE_SIZE) {
pvo = pmap_pvo_find_va(pm, va, &pteidx);
if (pvo == NULL)
@@ -1939,7 +1954,7 @@ pmap_protect(pmap_t pm, vaddr_t va, vaddr_t endva, vm_prot_t prot)
* Revoke executable if asked to do so.
*/
if ((prot & VM_PROT_EXECUTE) == 0)
- pvo->pvo_vaddr &= ~PVO_EXECUTABLE;
+ pvo_clear_exec(pvo);
#if 0
/*
@@ -1972,9 +1987,7 @@ pmap_protect(pmap_t pm, vaddr_t va, vaddr_t endva, vm_prot_t prot)
PMAP_PVO_CHECK(pvo); /* sanity check */
}
-
pmap_interrupts_restore(msr);
- splx(s);
}
void
@@ -1982,11 +1995,8 @@ pmap_unwire(pmap_t pm, vaddr_t va)
{
struct pvo_entry *pvo;
register_t msr;
- int s;
- s = splvm();
msr = pmap_interrupts_off();
-
pvo = pmap_pvo_find_va(pm, va, NULL);
if (pvo != NULL) {
if (pvo->pvo_vaddr & PVO_WIRED) {
@@ -1995,16 +2005,11 @@ pmap_unwire(pmap_t pm, vaddr_t va)
}
PMAP_PVO_CHECK(pvo); /* sanity check */
}
-
pmap_interrupts_restore(msr);
- splx(s);
}
/*
* Lower the protection on the specified physical page.
- *
- * There are only two cases: either the protection is going to 0,
- * or it is going to read-only.
*/
void
pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
@@ -2013,18 +2018,8 @@ pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
struct pvo_entry *pvo, *next_pvo;
volatile struct pte *pt;
register_t msr;
- int s;
-
- /*
- * Since this routine only downgrades protection, if the
- * maximal protection is desired, there isn't any change
- * to be made.
- */
- KASSERT((prot & VM_PROT_WRITE) == 0);
- if ((prot & (VM_PROT_READ|VM_PROT_WRITE)) == (VM_PROT_READ|VM_PROT_WRITE))
- return;
- s = splvm();
+ KASSERT(prot != VM_PROT_ALL);
msr = pmap_interrupts_off();
/*
@@ -2059,7 +2054,7 @@ pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
* flag in the PVO.
*/
if ((prot & VM_PROT_EXECUTE) == 0)
- pvo->pvo_vaddr &= ~PVO_EXECUTABLE;
+ pvo_clear_exec(pvo);
/*
* If this entry is already RO, don't diddle with the
@@ -2085,9 +2080,7 @@ pmap_page_protect(struct vm_page *pg, vm_prot_t prot)
}
PMAP_PVO_CHECK(pvo); /* sanity check */
}
-
pmap_interrupts_restore(msr);
- splx(s);
}
/*
@@ -2123,11 +2116,10 @@ pmap_query_bit(struct vm_page *pg, int ptebit)
struct pvo_entry *pvo;
volatile struct pte *pt;
register_t msr;
- int s;
if (pmap_attr_fetch(pg) & ptebit)
return TRUE;
- s = splvm();
+
msr = pmap_interrupts_off();
LIST_FOREACH(pvo, vm_page_to_pvoh(pg), pvo_vlink) {
PMAP_PVO_CHECK(pvo); /* sanity check */
@@ -2139,7 +2131,6 @@ pmap_query_bit(struct vm_page *pg, int ptebit)
pmap_attr_save(pg, ptebit);
PMAP_PVO_CHECK(pvo); /* sanity check */
pmap_interrupts_restore(msr);
- splx(s);
return TRUE;
}
}
@@ -2163,13 +2154,11 @@ pmap_query_bit(struct vm_page *pg, int ptebit)
pmap_attr_save(pg, ptebit);
PMAP_PVO_CHECK(pvo); /* sanity check */
pmap_interrupts_restore(msr);
- splx(s);
return TRUE;
}
}
}
pmap_interrupts_restore(msr);
- splx(s);
return FALSE;
}
@@ -2181,9 +2170,7 @@ pmap_clear_bit(struct vm_page *pg, int ptebit)
volatile struct pte *pt;
register_t msr;
int rv = 0;
- int s;
- s = splvm();
msr = pmap_interrupts_off();
/*
@@ -2231,7 +2218,7 @@ pmap_clear_bit(struct vm_page *pg, int ptebit)
PMAP_PVO_CHECK(pvo); /* sanity check */
}
pmap_interrupts_restore(msr);
- splx(s);
+
/*
* If we are clearing the modify bit and this page was marked EXEC
* and the user of the page thinks the page was modified, then we
diff --git a/sys/arch/powerpc/powerpc/trap.c b/sys/arch/powerpc/powerpc/trap.c
index 21cd790d700..f86e086ee81 100644
--- a/sys/arch/powerpc/powerpc/trap.c
+++ b/sys/arch/powerpc/powerpc/trap.c
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.84 2003/08/12 05:06:56 matt Exp $ */
+/* $NetBSD: trap.c,v 1.85 2003/08/24 17:52:35 chs Exp $ */
/*
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -32,7 +32,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.84 2003/08/12 05:06:56 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.85 2003/08/24 17:52:35 chs Exp $");
#include "opt_altivec.h"
#include "opt_ddb.h"
@@ -122,7 +122,7 @@ trap(struct trapframe *frame)
if ((frame->dsisr & DSISR_NOTFOUND) &&
vm_map_pmap(map)->pm_evictions > 0 &&
pmap_pte_spill(vm_map_pmap(map),
- trunc_page(va))) {
+ trunc_page(va), FALSE)) {
/* KERNEL_PROC_UNLOCK(l); */
KERNEL_UNLOCK();
return;
@@ -179,6 +179,7 @@ trap(struct trapframe *frame)
ftype = VM_PROT_WRITE;
else
ftype = VM_PROT_READ;
+
/*
* Try to spill an evicted pte into the page table
* if this wasn't a protection fault and the pmap
@@ -187,7 +188,8 @@ trap(struct trapframe *frame)
map = &p->p_vmspace->vm_map;
if ((frame->dsisr & DSISR_NOTFOUND) &&
vm_map_pmap(map)->pm_evictions > 0 &&
- pmap_pte_spill(vm_map_pmap(map), trunc_page(frame->dar))) {
+ pmap_pte_spill(vm_map_pmap(map), trunc_page(frame->dar),
+ FALSE)) {
KERNEL_PROC_UNLOCK(l);
break;
}
@@ -232,20 +234,20 @@ trap(struct trapframe *frame)
case EXC_ISI|EXC_USER:
KERNEL_PROC_LOCK(l);
ci->ci_ev_isi.ev_count++;
+
/*
* Try to spill an evicted pte into the page table
* if this wasn't a protection fault and the pmap
* has some evicted pte's.
*/
map = &p->p_vmspace->vm_map;
- if ((frame->srr1 & DSISR_NOTFOUND) &&
- vm_map_pmap(map)->pm_evictions > 0 &&
- pmap_pte_spill(vm_map_pmap(map), trunc_page(frame->srr0))) {
+ if (pmap_pte_spill(vm_map_pmap(map), trunc_page(frame->srr0),
+ TRUE)) {
KERNEL_PROC_UNLOCK(l);
break;
}
- ftype = VM_PROT_READ | VM_PROT_EXECUTE;
+ ftype = VM_PROT_EXECUTE;
rv = uvm_fault(map, trunc_page(frame->srr0), 0, ftype);
if (rv == 0) {
KERNEL_PROC_UNLOCK(l);
@@ -254,7 +256,7 @@ trap(struct trapframe *frame)
ci->ci_ev_isi_fatal.ev_count++;
if (cpu_printfataltraps) {
printf("trap: pid %d.%d (%s): user ISI trap @ %#lx "
- "(SSR1=%#lx)\n", p->p_pid, l->l_lid, p->p_comm,
+ "(SRR1=%#lx)\n", p->p_pid, l->l_lid, p->p_comm,
frame->srr0, frame->srr1);
}
trapsignal(l, SIGSEGV, EXC_ISI);
diff --git a/sys/arch/sparc/sparc/pmap.c b/sys/arch/sparc/sparc/pmap.c
index 2fe99e09c74..6721b96a975 100644
--- a/sys/arch/sparc/sparc/pmap.c
+++ b/sys/arch/sparc/sparc/pmap.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.268 2003/08/21 09:36:28 pk Exp $ */
+/* $NetBSD: pmap.c,v 1.269 2003/08/24 17:52:36 chs Exp $ */
/*
* Copyright (c) 1996
@@ -56,7 +56,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.268 2003/08/21 09:36:28 pk Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.269 2003/08/24 17:52:36 chs Exp $");
#include "opt_ddb.h"
#include "opt_kgdb.h"
@@ -892,6 +892,59 @@ setpte4m(va, pte)
}
/*
+ * Translation table for kernel vs. PTE protection bits.
+ */
+u_int protection_codes[2][8];
+#define pte_prot4m(pm, prot) \
+ (protection_codes[(pm) == pmap_kernel() ? 0 : 1][(prot)])
+
+static void
+sparc_protection_init4m(void)
+{
+ u_int prot, *kp, *up;
+
+ kp = protection_codes[0];
+ up = protection_codes[1];
+
+ for (prot = 0; prot < 8; prot++) {
+ switch (prot) {
+ case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
+ kp[prot] = PPROT_N_RWX;
+ up[prot] = PPROT_RWX_RWX;
+ break;
+ case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_NONE:
+ kp[prot] = PPROT_N_RWX;
+ up[prot] = PPROT_RW_RW;
+ break;
+ case VM_PROT_READ | VM_PROT_NONE | VM_PROT_EXECUTE:
+ kp[prot] = PPROT_N_RX;
+ up[prot] = PPROT_RX_RX;
+ break;
+ case VM_PROT_READ | VM_PROT_NONE | VM_PROT_NONE:
+ kp[prot] = PPROT_N_RX;
+ up[prot] = PPROT_R_R;
+ break;
+ case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_EXECUTE:
+ kp[prot] = PPROT_N_RWX;
+ up[prot] = PPROT_RWX_RWX;
+ break;
+ case VM_PROT_NONE | VM_PROT_WRITE | VM_PROT_NONE:
+ kp[prot] = PPROT_N_RWX;
+ up[prot] = PPROT_RW_RW;
+ break;
+ case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_EXECUTE:
+ kp[prot] = PPROT_N_RX;
+ up[prot] = PPROT_X_X;
+ break;
+ case VM_PROT_NONE | VM_PROT_NONE | VM_PROT_NONE:
+ kp[prot] = PPROT_N_RX;
+ up[prot] = PPROT_N_RX;
+ break;
+ }
+ }
+}
+
+/*
* Page table pool back-end.
*/
void *
@@ -3875,6 +3928,7 @@ pmap_bootstrap4m(top)
* Now switch to kernel pagetables (finally!)
*/
mmu_install_tables(&cpuinfo);
+ sparc_protection_init4m();
}
static u_long prom_ctxreg;
@@ -5389,11 +5443,6 @@ out:
/*
* Lower (make more strict) the protection on the specified
* range of this pmap.
- *
- * There are only two cases: either the protection is going to 0
- * (in which case we call pmap_remove to do the dirty work), or
- * it is going from read/write to read-only. The latter is
- * fairly easy.
*/
void
pmap_protect4m(pm, sva, eva, prot)
@@ -5405,6 +5454,12 @@ pmap_protect4m(pm, sva, eva, prot)
int s, vr, vs;
struct regmap *rp;
struct segmap *sp;
+ int newprot;
+
+ /* XXX noexec stuff gets "Level 15 Interrupt" without this */
+ if (cpuinfo.cpu_type == CPUTYP_HS_MBUS) {
+ prot = VM_PROT_NONE;
+ }
if ((prot & VM_PROT_READ) == 0) {
pmap_remove(pm, sva, eva);
@@ -5414,11 +5469,14 @@ pmap_protect4m(pm, sva, eva, prot)
#ifdef DEBUG
if (pmapdebug & PDB_CHANGEPROT)
printf("pmap_protect[%d][curpid %d, ctx %d,%d](%lx, %lx, %x)\n",
- cpu_number(), getcontext4m(),
- curproc==NULL ? -1 : curproc->p_pid,
- pm->pm_ctx ? pm->pm_ctxnum : -1, sva, eva, prot);
+ cpu_number(), curproc->p_pid,
+ getcontext4m(), pm->pm_ctx ? pm->pm_ctxnum : -1,
+ sva, eva, prot);
#endif
+ newprot = pte_prot4m(pm, prot);
+
+ write_user_windows();
s = splvm();
PMAP_MAP_TO_HEAD_LOCK();
simple_lock(&pm->pm_lock);
@@ -5428,56 +5486,50 @@ pmap_protect4m(pm, sva, eva, prot)
vs = VA_VSEG(va);
rp = &pm->pm_regmap[vr];
nva = VSTOVA(vr,vs + 1);
- if (nva == 0) /* XXX */
- panic("pmap_protect: last segment"); /* cannot happen(why?)*/
if (nva > eva)
nva = eva;
if (rp->rg_nsegmap == 0) {
va = nva;
continue;
}
-#ifdef DEBUG
- if (rp->rg_segmap == NULL)
- panic("pmap_protect: no segments");
-#endif
sp = &rp->rg_segmap[vs];
if (sp->sg_npte == 0) {
va = nva;
continue;
}
-#ifdef DEBUG
- if (sp->sg_pte == NULL)
- panic("pmap_protect: no pages");
-#endif
+
/*
* pages loaded: take away write bits from MMU PTEs
*/
pmap_stats.ps_npg_prot_all += (nva - va) >> PGSHIFT;
for (; va < nva; va += NBPG) {
- int tpte;
+ int tpte, npte;
tpte = sp->sg_pte[VA_SUN4M_VPG(va)];
+ if ((tpte & SRMMU_PGTYPE) != PG_SUN4M_OBMEM)
+ continue;
+ npte = (tpte & ~SRMMU_PROT_MASK) | newprot;
+ if (npte == tpte)
+ continue;
+
/*
* Flush cache so that any existing cache
- * tags are updated. This is really only
- * needed for PTEs that lose PG_W.
+ * tags are updated.
*/
- if ((tpte & (PPROT_WRITE|SRMMU_PGTYPE)) ==
- (PPROT_WRITE|PG_SUN4M_OBMEM)) {
- pmap_stats.ps_npg_prot_actual++;
- if (pm->pm_ctx) {
- cache_flush_page(va, pm->pm_ctxnum);
+
+ pmap_stats.ps_npg_prot_actual++;
+ if (pm->pm_ctx) {
+ cache_flush_page(va, pm->pm_ctxnum);
#if !defined(MULTIPROCESSOR)
- /* Flush TLB entry */
- tlb_flush_page(va, pm->pm_ctxnum,
- PMAP_CPUSET(pm));
+ /* Flush TLB entry */
+ tlb_flush_page(va, pm->pm_ctxnum,
+ PMAP_CPUSET(pm));
#endif
- }
- updatepte4m(va, &sp->sg_pte[VA_SUN4M_VPG(va)],
- PPROT_WRITE, 0, pm->pm_ctxnum,
- PMAP_CPUSET(pm));
}
+ updatepte4m(va, &sp->sg_pte[VA_SUN4M_VPG(va)],
+ SRMMU_PROT_MASK, newprot, pm->pm_ctxnum,
+ PMAP_CPUSET(pm));
}
}
simple_unlock(&pm->pm_lock);
@@ -5507,10 +5559,7 @@ pmap_changeprot4m(pm, va, prot, flags)
cpu_number(), pm, va, prot, flags);
#endif
- if (pm == pmap_kernel())
- newprot = prot & VM_PROT_WRITE ? PPROT_N_RWX : PPROT_N_RX;
- else
- newprot = prot & VM_PROT_WRITE ? PPROT_RWX_RWX : PPROT_RX_RX;
+ newprot = pte_prot4m(pm, prot);
pmap_stats.ps_changeprots++;
@@ -6189,12 +6238,10 @@ pmap_enter4m(pm, va, pa, prot, flags)
" MicroSPARC");
}
#endif
+ pteproto |= SRMMU_TEPTE;
pteproto |= PMAP_T2PTE_SRMMU(pa);
-
- /* Make sure we get a pte with appropriate perms! */
- pteproto |= SRMMU_TEPTE | PPROT_RX_RX;
-
pa &= ~PMAP_TNC_SRMMU;
+
/*
* Set up prototype for new PTE. Cannot set PG_NC from PV_NC yet
* since the pvlist no-cache bit might change as a result of the
@@ -6202,8 +6249,8 @@ pmap_enter4m(pm, va, pa, prot, flags)
*/
pteproto |= (atop(pa) << SRMMU_PPNSHIFT);
- if (prot & VM_PROT_WRITE)
- pteproto |= PPROT_WRITE;
+ /* Make sure we get a pte with appropriate perms! */
+ pteproto |= pte_prot4m(pm, prot);
if (pm == pmap_kernel())
error = pmap_enk4m(pm, va, prot, flags, pg, pteproto | PPROT_S);
@@ -6524,12 +6571,10 @@ pmap_kenter_pa4m(va, pa, prot)
/* Initialise pteproto with cache bit */
pteproto = (pa & PMAP_NC) == 0 ? SRMMU_PG_C : 0;
+ pteproto |= SRMMU_TEPTE | PPROT_S;
pteproto |= PMAP_T2PTE_SRMMU(pa);
- pteproto |= SRMMU_TEPTE | PPROT_RX_RX;
pteproto |= (atop(pa & ~PMAP_TNC_SRMMU) << SRMMU_PPNSHIFT);
- if (prot & VM_PROT_WRITE)
- pteproto |= PPROT_WRITE;
- pteproto |= PPROT_S;
+ pteproto |= pte_prot4m(pm, prot);
vr = VA_VREG(va);
vs = VA_VSEG(va);
@@ -6641,7 +6686,7 @@ pmap_kprotect4m(vaddr_t va, vsize_t size, vm_prot_t prot)
struct segmap *sp;
size = roundup(size,NBPG);
- newprot = prot & VM_PROT_WRITE ? PPROT_N_RWX : PPROT_N_RX;
+ newprot = pte_prot4m(pm, prot);
while (size > 0) {
rp = &pm->pm_regmap[VA_VREG(va)];
@@ -6739,7 +6784,6 @@ pmap_extract4_4c(pm, va, pap)
return (FALSE);
}
sp = &rp->rg_segmap[vs];
-
ptep = sp->sg_pte;
if (ptep == NULL) {
#ifdef DEBUG
@@ -7544,11 +7588,6 @@ pmap_deactivate(l)
pmap_t pm;
struct proc *p;
-#ifdef DIAGNOSTIC
- if (l == NULL)
- panic("pmap_deactivate: l==NULL");
-#endif
-
p = l->l_proc;
if (p->p_vmspace &&
(pm = p->p_vmspace->vm_map.pmap) != pmap_kernel()) {
diff --git a/sys/arch/sparc/sparc/trap.c b/sys/arch/sparc/sparc/trap.c
index 9349920bdea..cd56f5fcfb0 100644
--- a/sys/arch/sparc/sparc/trap.c
+++ b/sys/arch/sparc/sparc/trap.c
@@ -1,4 +1,4 @@
-/* $NetBSD: trap.c,v 1.138 2003/08/12 15:34:32 pk Exp $ */
+/* $NetBSD: trap.c,v 1.139 2003/08/24 17:52:37 chs Exp $ */
/*
* Copyright (c) 1996
@@ -49,7 +49,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.138 2003/08/12 15:34:32 pk Exp $");
+__KERNEL_RCSID(0, "$NetBSD: trap.c,v 1.139 2003/08/24 17:52:37 chs Exp $");
#include "opt_ddb.h"
#include "opt_ktrace.h"
@@ -1170,7 +1170,17 @@ mem_access_fault4m(type, sfsr, sfva, tf)
}
/* Now munch on protections... */
- atype = sfsr & SFSR_AT_STORE ? VM_PROT_WRITE : VM_PROT_READ;
+ if (sfsr & SFSR_AT_STORE) {
+ /* stores are never text faults. */
+ atype = VM_PROT_WRITE;
+ } else {
+ if ((sfsr & SFSR_AT_TEXT) || type == T_TEXTFAULT) {
+ atype = VM_PROT_EXECUTE;
+ } else {
+ atype = VM_PROT_READ;
+ }
+ }
+
if (psr & PSR_PS) {
extern char Lfsbail[];
if (sfsr & SFSR_AT_TEXT || type == T_TEXTFAULT) {
diff --git a/sys/arch/sparc64/include/pmap.h b/sys/arch/sparc64/include/pmap.h
index fcdd2320f9c..e9d7354ca0b 100644
--- a/sys/arch/sparc64/include/pmap.h
+++ b/sys/arch/sparc64/include/pmap.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.h,v 1.28 2003/08/10 02:30:51 chs Exp $ */
+/* $NetBSD: pmap.h,v 1.29 2003/08/24 17:52:37 chs Exp $ */
/*-
* Copyright (C) 1995, 1996 Wolfgang Solfrank.
@@ -199,6 +199,7 @@ int pmap_dumpmmu __P((int (*)__P((dev_t, daddr_t, caddr_t, size_t)),
daddr_t));
int pmap_pa_exists __P((paddr_t));
void switchexit __P((struct lwp *, int));
+void pmap_kprotect(vaddr_t, vm_prot_t);
/* SPARC64 specific */
int ctx_alloc __P((struct pmap *));
diff --git a/sys/arch/sparc64/sparc64/clock.c b/sys/arch/sparc64/sparc64/clock.c
index 17db9a1f6bf..5f3f4d06200 100644
--- a/sys/arch/sparc64/sparc64/clock.c
+++ b/sys/arch/sparc64/sparc64/clock.c
@@ -1,4 +1,4 @@
-/* $NetBSD: clock.c,v 1.60 2003/07/15 03:36:08 lukem Exp $ */
+/* $NetBSD: clock.c,v 1.61 2003/08/24 17:52:38 chs Exp $ */
/*
* Copyright (c) 1992, 1993
@@ -55,7 +55,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.60 2003/07/15 03:36:08 lukem Exp $");
+__KERNEL_RCSID(0, "$NetBSD: clock.c,v 1.61 2003/08/24 17:52:38 chs Exp $");
#include "opt_multiprocessor.h"
@@ -260,9 +260,9 @@ clockattach_sbus(parent, self, aux)
if (sbus_bus_map(bt,
sa->sa_slot,
- (sa->sa_offset & ~PAGE_SIZE),
+ (sa->sa_offset & ~(PAGE_SIZE - 1)),
sz,
- BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_READONLY,
+ BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY,
&ci.ci_bh) != 0) {
printf("%s: can't map register\n", self->dv_xname);
return;
@@ -284,30 +284,28 @@ clock_wenable(handle, onoff)
struct todr_chip_handle *handle;
int onoff;
{
- register int s, err = 0;
- register int prot;/* nonzero => change prot */
+ struct clock_info *ci;
+ vm_prot_t prot;
+ vaddr_t va;
+ int s, err = 0;
static int writers;
s = splhigh();
if (onoff)
- prot = writers++ == 0 ?
- VM_PROT_READ|VM_PROT_WRITE|PMAP_WIRED : 0;
+ prot = writers++ == 0 ? VM_PROT_READ|VM_PROT_WRITE : 0;
else
- prot = --writers == 0 ?
- VM_PROT_READ|PMAP_WIRED : 0;
+ prot = --writers == 0 ? VM_PROT_READ : 0;
splx(s);
- if (prot) {
- struct clock_info *ci =
- (struct clock_info *)handle->bus_cookie;
- vaddr_t vaddr =
- (vaddr_t)bus_space_vaddr(ci->ci_bt, ci->ci_bh);
-
- if (vaddr)
- pmap_protect(pmap_kernel(), vaddr, vaddr+PAGE_SIZE,
- prot);
- else
- printf("clock_wenable: WARNING -- cannot get va\n");
+ if (prot == VM_PROT_NONE) {
+ return 0;
}
+ ci = (struct clock_info *)handle->bus_cookie;
+ va = (vaddr_t)bus_space_vaddr(ci->ci_bt, ci->ci_bh);
+ if (va == NULL) {
+ printf("clock_wenable: WARNING -- cannot get va\n");
+ return EIO;
+ }
+ pmap_kprotect(va, prot);
return (err);
}
@@ -440,7 +438,7 @@ clockattach_rtc(parent, self, aux)
#endif
printf(": %s\n", model);
- /*
+ /*
* Turn interrupts off, just in case. (Although they shouldn't
* be wired to an interrupt controller on sparcs).
*/
diff --git a/sys/arch/sparc64/sparc64/db_interface.c b/sys/arch/sparc64/sparc64/db_interface.c
index dc1471dc66d..2ee601ca348 100644
--- a/sys/arch/sparc64/sparc64/db_interface.c
+++ b/sys/arch/sparc64/sparc64/db_interface.c
@@ -1,4 +1,4 @@
-/* $NetBSD: db_interface.c,v 1.70 2003/07/15 03:36:08 lukem Exp $ */
+/* $NetBSD: db_interface.c,v 1.71 2003/08/24 17:52:38 chs Exp $ */
/*
* Copyright (c) 1996-2002 Eduardo Horvath. All rights reserved.
@@ -34,7 +34,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.70 2003/07/15 03:36:08 lukem Exp $");
+__KERNEL_RCSID(0, "$NetBSD: db_interface.c,v 1.71 2003/08/24 17:52:38 chs Exp $");
#include "opt_ddb.h"
@@ -556,35 +556,38 @@ int64_t pseg_get __P((struct pmap *, vaddr_t));
void
db_dump_pmap(pm)
-struct pmap* pm;
+ struct pmap *pm;
{
/* print all valid pages in the kernel pmap */
- long i, j, k, n;
+ unsigned long long i, j, k, n, data0, data1;
paddr_t *pdir, *ptbl;
- /* Almost the same as pmap_collect() */
n = 0;
- for (i=0; i<STSZ; i++) {
- if((pdir = (paddr_t *)(u_long)ldxa((vaddr_t)&pm->pm_segs[i], ASI_PHYS_CACHED))) {
- db_printf("pdir %ld at %lx:\n", i, (long)pdir);
- for (k=0; k<PDSZ; k++) {
- if ((ptbl = (paddr_t *)(u_long)ldxa((vaddr_t)&pdir[k], ASI_PHYS_CACHED))) {
- db_printf("\tptable %ld:%ld at %lx:\n", i, k, (long)ptbl);
- for (j=0; j<PTSZ; j++) {
- int64_t data0, data1;
- data0 = ldxa((vaddr_t)&ptbl[j], ASI_PHYS_CACHED);
- j++;
- data1 = ldxa((vaddr_t)&ptbl[j], ASI_PHYS_CACHED);
- if (data0 || data1) {
- db_printf("%llx: %llx\t",
- (unsigned long long)(((u_int64_t)i<<STSHIFT)|(k<<PDSHIFT)|((j-1)<<PTSHIFT)),
- (unsigned long long)(data0));
- db_printf("%llx: %llx\n",
- (unsigned long long)(((u_int64_t)i<<STSHIFT)|(k<<PDSHIFT)|(j<<PTSHIFT)),
- (unsigned long long)(data1));
- }
- }
+ for (i = 0; i < STSZ; i++) {
+ pdir = (paddr_t *)(u_long)ldxa((vaddr_t)&pm->pm_segs[i], ASI_PHYS_CACHED);
+ if (!pdir) {
+ continue;
+ }
+ db_printf("pdir %lld at %lx:\n", i, (long)pdir);
+ for (k = 0; k < PDSZ; k++) {
+ ptbl = (paddr_t *)(u_long)ldxa((vaddr_t)&pdir[k], ASI_PHYS_CACHED);
+ if (!ptbl) {
+ continue;
+ }
+ db_printf("\tptable %lld:%lld at %lx:\n", i, k, (long)ptbl);
+ for (j = 0; j < PTSZ; j++) {
+ data0 = ldxa((vaddr_t)&ptbl[j], ASI_PHYS_CACHED);
+ j++;
+ data1 = ldxa((vaddr_t)&ptbl[j], ASI_PHYS_CACHED);
+ if (!data0 && !data1) {
+ continue;
}
+ db_printf("%016llx: %016llx\t",
+ (i << STSHIFT) | (k << PDSHIFT) | ((j - 1) << PTSHIFT),
+ data0);
+ db_printf("%016llx: %016llx\n",
+ (i << STSHIFT) | (k << PDSHIFT) | (j << PTSHIFT),
+ data1);
}
}
}
@@ -725,22 +728,22 @@ db_dump_dtsb(addr, have_addr, count, modif)
db_expr_t count;
char *modif;
{
- extern pte_t *tsb;
+ extern pte_t *tsb_dmmu;
extern int tsbsize;
-#define TSBENTS (512<<tsbsize)
+#define TSBENTS (512 << tsbsize)
int i;
db_printf("TSB:\n");
- for (i=0; i<TSBENTS; i++) {
+ for (i = 0; i < TSBENTS; i++) {
db_printf("%4d:%4d:%08x %08x:%08x ", i,
- (int)((tsb[i].tag&TSB_TAG_G)?-1:TSB_TAG_CTX(tsb[i].tag)),
- (int)((i<<13)|TSB_TAG_VA(tsb[i].tag)),
- (int)(tsb[i].data>>32), (int)tsb[i].data);
+ (int)((tsb_dmmu[i].tag&TSB_TAG_G)?-1:TSB_TAG_CTX(tsb_dmmu[i].tag)),
+ (int)((i<<13)|TSB_TAG_VA(tsb_dmmu[i].tag)),
+ (int)(tsb_dmmu[i].data>>32), (int)tsb_dmmu[i].data);
i++;
db_printf("%4d:%4d:%08x %08x:%08x\n", i,
- (int)((tsb[i].tag&TSB_TAG_G)?-1:TSB_TAG_CTX(tsb[i].tag)),
- (int)((i<<13)|TSB_TAG_VA(tsb[i].tag)),
- (int)(tsb[i].data>>32), (int)tsb[i].data);
+ (int)((tsb_dmmu[i].tag&TSB_TAG_G)?-1:TSB_TAG_CTX(tsb_dmmu[i].tag)),
+ (int)((i<<13)|TSB_TAG_VA(tsb_dmmu[i].tag)),
+ (int)(tsb_dmmu[i].data>>32), (int)tsb_dmmu[i].data);
}
}
diff --git a/sys/arch/sparc64/sparc64/locore.s b/sys/arch/sparc64/sparc64/locore.s
index 5a11e6359b0..51f2a1ee366 100644
--- a/sys/arch/sparc64/sparc64/locore.s
+++ b/sys/arch/sparc64/sparc64/locore.s
@@ -1,4 +1,4 @@
-/* $NetBSD: locore.s,v 1.178 2003/07/08 22:09:26 cdi Exp $ */
+/* $NetBSD: locore.s,v 1.179 2003/08/24 17:52:38 chs Exp $ */
/*
* Copyright (c) 1996-2002 Eduardo Horvath
@@ -2296,6 +2296,7 @@ data_miss:
sll %g6, 3, %g6
brz,pn %g4, data_nfo ! NULL entry? check somewhere else
add %g6, %g4, %g6
+
1:
ldxa [%g6] ASI_PHYS_CACHED, %g4
brgez,pn %g4, data_nfo ! Entry invalid? Punt
@@ -2308,9 +2309,9 @@ data_miss:
cmp %g4, %g7
bne,pn %xcc, 1b
or %g4, TTE_ACCESS, %g4 ! Update the access bit
+
1:
stx %g1, [%g2] ! Update TSB entry tag
-
stx %g4, [%g2+8] ! Update TSB entry data
#ifdef DEBUG
set DATA_START, %g6 ! debug
@@ -3256,7 +3257,14 @@ instr_miss:
1:
ldxa [%g6] ASI_PHYS_CACHED, %g4
brgez,pn %g4, textfault
- or %g4, TTE_ACCESS, %g7 ! Update accessed bit
+ nop
+
+ /* Check if it's an executable mapping. */
+ andcc %g4, TTE_EXEC, %g0
+ bz,pn %xcc, textfault
+ nop
+
+ or %g4, TTE_ACCESS, %g7 ! Update accessed bit
btst TTE_ACCESS, %g4 ! Need to update access git?
bne,pt %xcc, 1f
nop
@@ -5942,44 +5950,32 @@ _C_LABEL(cpu_initialize):
flushw
/*
- * Step 7: change the trap base register, and install our TSB
- *
- * XXXX -- move this to CPUINFO_VA+32KB?
+ * Step 7: change the trap base register, and install our TSB pointers
*/
sethi %hi(0x1fff), %l2
- set _C_LABEL(tsb), %l0
+ set _C_LABEL(tsb_dmmu), %l0
LDPTR [%l0], %l0
set _C_LABEL(tsbsize), %l1
or %l2, %lo(0x1fff), %l2
ld [%l1], %l1
andn %l0, %l2, %l0 ! Mask off size and split bits
or %l0, %l1, %l0 ! Make a TSB pointer
-! srl %l0, 0, %l0 ! DEBUG -- make sure this is a valid pointer by zeroing the high bits
-
-#ifdef DEBUG
- set _C_LABEL(pmapdebug), %o1
- ld [%o1], %o1
- sethi %hi(0x40000), %o2
- btst %o2, %o1
- bz 0f
-
- set 1f, %o0 ! Debug printf
- srlx %l0, 32, %o1
- call _C_LABEL(prom_printf)
- srl %l0, 0, %o2
- .data
-1:
- .asciz "Setting TSB pointer %08x %08x\r\n"
- _ALIGN
- .text
-0:
-#endif
-
set TSB, %l2
- stxa %l0, [%l2] ASI_IMMU ! Install insn TSB pointer
- membar #Sync ! We may need more membar #Sync in here
stxa %l0, [%l2] ASI_DMMU ! Install data TSB pointer
membar #Sync
+
+ sethi %hi(0x1fff), %l2
+ set _C_LABEL(tsb_immu), %l0
+ LDPTR [%l0], %l0
+ set _C_LABEL(tsbsize), %l1
+ or %l2, %lo(0x1fff), %l2
+ ld [%l1], %l1
+ andn %l0, %l2, %l0 ! Mask off size and split bits
+ or %l0, %l1, %l0 ! Make a TSB pointer
+ set TSB, %l2
+ stxa %l0, [%l2] ASI_IMMU ! Install instruction TSB pointer
+ membar #Sync
+
set _C_LABEL(trapbase), %l1
call _C_LABEL(prom_set_trap_table) ! Now we should be running 100% from our handlers
mov %l1, %o0
@@ -5994,17 +5990,6 @@ _C_LABEL(cpu_initialize):
wrpr %g0, 0, %tstate
#endif
-#ifdef NOTDEF_DEBUG
- set 1f, %o0 ! Debug printf
- srax %l0, 32, %o1
- call _C_LABEL(prom_printf)
- srl %l0, 0, %o2
- .data
-1:
- .asciz "Our trap handler is enabled\r\n"
- _ALIGN
- .text
-#endif
/*
* Call our startup routine.
*/
diff --git a/sys/arch/sparc64/sparc64/pmap.c b/sys/arch/sparc64/sparc64/pmap.c
index 491315a39af..be28430d4bd 100644
--- a/sys/arch/sparc64/sparc64/pmap.c
+++ b/sys/arch/sparc64/sparc64/pmap.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pmap.c,v 1.142 2003/07/15 03:36:09 lukem Exp $ */
+/* $NetBSD: pmap.c,v 1.143 2003/08/24 17:52:39 chs Exp $ */
/*
*
* Copyright (C) 1996-1999 Eduardo Horvath.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.142 2003/07/15 03:36:09 lukem Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pmap.c,v 1.143 2003/08/24 17:52:39 chs Exp $");
#undef NO_VCACHE /* Don't forget the locked TLB in dostart */
#define HWREF
@@ -139,7 +139,8 @@ u_int64_t first_phys_addr;
/*
* Here's the CPU TSB stuff. It's allocated in pmap_bootstrap.
*/
-pte_t *tsb;
+pte_t *tsb_dmmu;
+pte_t *tsb_immu;
int tsbsize; /* tsbents = 512 * 2^^tsbsize */
#define TSBENTS (512<<tsbsize)
#define TSBSIZE (TSBENTS * 16)
@@ -173,10 +174,29 @@ static int memh = 0, vmemh = 0; /* Handles to OBP devices */
paddr_t avail_start, avail_end; /* These are used by ps & family */
-static int ptelookup_va __P((vaddr_t va)); /* sun4u */
-#if notyet
-static void tsb_enter __P((int ctx, int64_t va, int64_t data));
-#endif
+static int ptelookup_va __P((vaddr_t va));
+
+static __inline void
+clrx(void *addr)
+{
+ __asm __volatile("clrx [%0]" : : "r" (addr) : "memory");
+}
+
+static __inline void
+tsb_invalidate(int ctx, vaddr_t va)
+{
+ int i;
+ int64_t tag;
+
+ i = ptelookup_va(va);
+ tag = TSB_TAG(0, ctx, va);
+ if (tsb_dmmu[i].tag == tag) {
+ clrx(&tsb_dmmu[i].data);
+ }
+ if (tsb_immu[i].tag == tag) {
+ clrx(&tsb_immu[i].data);
+ }
+}
struct pmap_stats {
int ps_unlink_pvfirst; /* # of pv_unlinks on head */
@@ -950,9 +970,10 @@ remap_data:
*/
BDPRINTF(PDB_BOOT1, ("firstaddr before TSB=%lx\r\n",
(u_long)firstaddr));
- firstaddr = ((firstaddr + TSBSIZE - 1) & ~(TSBSIZE-1));
+ firstaddr = ((firstaddr + TSBSIZE - 1) & ~(TSBSIZE - 1));
#ifdef DEBUG
- i = (firstaddr + (PAGE_SIZE-1)) & ~(PAGE_SIZE-1); /* First, page align */
+ /* First, page align */
+ i = (firstaddr + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
if ((int)firstaddr < i) {
prom_printf("TSB alloc fixup failed\r\n");
prom_printf("frobbed i, firstaddr before TSB=%x, %lx\r\n",
@@ -963,12 +984,14 @@ remap_data:
#endif
BDPRINTF(PDB_BOOT, ("frobbed i, firstaddr before TSB=%x, %lx\r\n",
(int)i, (u_long)firstaddr));
- valloc(tsb, pte_t, TSBSIZE);
- bzero(tsb, TSBSIZE);
+ valloc(tsb_dmmu, pte_t, TSBSIZE);
+ bzero(tsb_dmmu, TSBSIZE);
+ valloc(tsb_immu, pte_t, TSBSIZE);
+ bzero(tsb_immu, TSBSIZE);
BDPRINTF(PDB_BOOT1, ("firstaddr after TSB=%lx\r\n", (u_long)firstaddr));
- BDPRINTF(PDB_BOOT1, ("TSB allocated at %p size %08x\r\n", (void*)tsb,
- (int)TSBSIZE));
+ BDPRINTF(PDB_BOOT1, ("TSB allocated at %p/%p size %08x\r\n",
+ tsb_dmmu, tsb_immu, TSBSIZE));
first_phys_addr = mem->start;
BDPRINTF(PDB_BOOT1, ("firstaddr after pmap=%08lx\r\n",
@@ -1202,13 +1225,13 @@ remap_data:
va += PAGE_SIZE;
msgbufsiz -= PAGE_SIZE;
phys_msgbuf += PAGE_SIZE;
- } while (psize-=PAGE_SIZE);
+ } while (psize -= PAGE_SIZE);
}
BDPRINTF(PDB_BOOT1, ("Done inserting mesgbuf into pmap_kernel()\r\n"));
BDPRINTF(PDB_BOOT1, ("Inserting PROM mappings into pmap_kernel()\r\n"));
for (i = 0; i < prom_map_size; i++)
- if (prom_map[i].vstart && ((prom_map[i].vstart>>32) == 0))
+ if (prom_map[i].vstart && ((prom_map[i].vstart >> 32) == 0))
for (j = 0; j < prom_map[i].vsize; j += PAGE_SIZE) {
int k;
@@ -1225,7 +1248,7 @@ remap_data:
#endif
/* Enter PROM map into pmap_kernel() */
pmap_enter_kpage(prom_map[i].vstart + j,
- (prom_map[i].tte + j)|
+ (prom_map[i].tte + j) | TLB_EXEC |
page_size_map[k].code);
}
BDPRINTF(PDB_BOOT1, ("Done inserting PROM mappings into pmap_kernel()\r\n"));
@@ -1697,7 +1720,6 @@ pmap_kenter_pa(va, pa, prot)
if (prot & VM_PROT_WRITE)
tte.data |= TLB_REAL_W|TLB_W;
tte.data |= TLB_TSB_LOCK; /* wired */
- KASSERT((tte.data & TLB_NFO) == 0);
ptp = 0;
retry:
@@ -1721,19 +1743,19 @@ pmap_kenter_pa(va, pa, prot)
i = ptelookup_va(va);
if (pmapdebug & PDB_ENTER)
prom_printf("pmap_kenter_pa: va=%08x data=%08x:%08x "
- "tsb[%d]=%08x\r\n", va, (int)(tte.data>>32),
- (int)tte.data, i, &tsb[i]);
- if (pmapdebug & PDB_MMU_STEAL && tsb[i].data) {
+ "tsb_dmmu[%d]=%08x\r\n", va, (int)(tte.data>>32),
+ (int)tte.data, i, &tsb_dmmu[i]);
+ if (pmapdebug & PDB_MMU_STEAL && tsb_dmmu[i].data) {
prom_printf("pmap_kenter_pa: evicting entry tag=%x:%08x "
- "data=%08x:%08x tsb[%d]=%08x\r\n",
- (int)(tsb[i].tag>>32), (int)tsb[i].tag,
- (int)(tsb[i].data>>32), (int)tsb[i].data,
- i, &tsb[i]);
- prom_printf("with va=%08x data=%08x:%08x tsb[%d]=%08x\r\n",
- va, (int)(tte.data>>32), (int)tte.data, i, &tsb[i]);
+ "data=%08x:%08x tsb_dmmu[%d]=%08x\r\n",
+ (int)(tsb_dmmu[i].tag>>32), (int)tsb_dmmu[i].tag,
+ (int)(tsb_dmmu[i].data>>32), (int)tsb_dmmu[i].data,
+ i, &tsb_dmmu[i]);
+ prom_printf("with va=%08x data=%08x:%08x tsb_dmmu[%d]=%08x\r\n",
+ va, (int)(tte.data>>32), (int)tte.data, i,
+ &tsb_dmmu[i]);
}
#endif
- KASSERT((tsb[i].data & TLB_NFO) == 0);
}
/*
@@ -1752,7 +1774,6 @@ pmap_kremove(va, size)
vaddr_t flushva = va;
vsize_t flushsize = size;
paddr_t pa;
- int i;
boolean_t flush = FALSE;
KASSERT(va < INTSTACK || va > EINTSTACK);
@@ -1793,12 +1814,7 @@ pmap_kremove(va, size)
(int)va_to_pte(va)));
REMOVE_STAT(removes);
- i = ptelookup_va(va);
- if (tsb[i].tag > 0 &&
- tsb[i].tag == TSB_TAG(0, pm->pm_ctx, va)) {
- tsb[i].data = 0;
- KASSERT((tsb[i].data & TLB_NFO) == 0);
- }
+ tsb_invalidate(pm->pm_ctx, va);
REMOVE_STAT(tflushes);
/*
@@ -1818,6 +1834,7 @@ pmap_kremove(va, size)
* Insert physical page at pa into the given pmap at virtual address va.
* Supports 64-bit pa so we can map I/O space.
*/
+
int
pmap_enter(pm, va, pa, prot, flags)
struct pmap *pm;
@@ -1924,6 +1941,8 @@ pmap_enter(pm, va, pa, prot, flags)
#ifdef HWREF
if (prot & VM_PROT_WRITE)
tte.data |= TLB_REAL_W;
+ if (prot & VM_PROT_EXECUTE)
+ tte.data |= TLB_EXEC;
#else
/* If it needs ref accounting do nothing. */
if (!(flags & VM_PROT_READ)) {
@@ -1939,7 +1958,6 @@ pmap_enter(pm, va, pa, prot, flags)
}
if (wired)
tte.data |= TLB_TSB_LOCK;
- KASSERT((tte.data & TLB_NFO) == 0);
ptp = 0;
retry:
@@ -2000,18 +2018,21 @@ pmap_enter(pm, va, pa, prot, flags)
i = ptelookup_va(va);
if (pmapdebug & PDB_ENTER)
prom_printf("pmap_enter: va=%08x data=%08x:%08x "
- "tsb[%d]=%08x\r\n", va, (int)(tte.data>>32),
- (int)tte.data, i, &tsb[i]);
- if (pmapdebug & PDB_MMU_STEAL && tsb[i].data) {
+ "tsb_dmmu[%d]=%08x\r\n", va, (int)(tte.data>>32),
+ (int)tte.data, i, &tsb_dmmu[i]);
+ if (pmapdebug & PDB_MMU_STEAL && tsb_dmmu[i].data) {
prom_printf("pmap_enter: evicting entry tag=%x:%08x "
- "data=%08x:%08x tsb[%d]=%08x\r\n",
- (int)(tsb[i].tag>>32), (int)tsb[i].tag,
- (int)(tsb[i].data>>32), (int)tsb[i].data, i, &tsb[i]);
- prom_printf("with va=%08x data=%08x:%08x tsb[%d]=%08x\r\n",
- va, (int)(tte.data>>32), (int)tte.data, i, &tsb[i]);
+ "data=%08x:%08x tsb_dmmu[%d]=%08x\r\n",
+ (int)(tsb_dmmu[i].tag>>32), (int)tsb_dmmu[i].tag,
+ (int)(tsb_dmmu[i].data>>32), (int)tsb_dmmu[i].data, i,
+ &tsb_dmmu[i]);
+ prom_printf("with va=%08x data=%08x:%08x tsb_dmmu[%d]=%08x\r\n",
+ va, (int)(tte.data>>32), (int)tte.data, i,
+ &tsb_dmmu[i]);
}
#endif
- if (flags & (VM_PROT_READ | VM_PROT_WRITE)) {
+
+ if (flags & (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)) {
/*
* preload the TSB with the new entry,
@@ -2021,9 +2042,16 @@ pmap_enter(pm, va, pa, prot, flags)
i = ptelookup_va(va);
tte.tag = TSB_TAG(0, pm->pm_ctx, va);
s = splhigh();
- tsb[i].tag = tte.tag;
- __asm __volatile("" : : : "memory");
- tsb[i].data = tte.data;
+ if (flags & (VM_PROT_READ | VM_PROT_WRITE)) {
+ tsb_dmmu[i].tag = tte.tag;
+ __asm __volatile("" : : : "memory");
+ tsb_dmmu[i].data = tte.data;
+ }
+ if (flags & VM_PROT_EXECUTE) {
+ tsb_immu[i].tag = tte.tag;
+ __asm __volatile("" : : : "memory");
+ tsb_immu[i].data = tte.data;
+ }
/*
* it's only necessary to flush the TLB if this page was
@@ -2034,14 +2062,9 @@ pmap_enter(pm, va, pa, prot, flags)
tlb_flush_pte(va, pm->pm_ctx);
splx(s);
} else if (wasmapped && (pm->pm_ctx || pm == pmap_kernel())) {
- i = ptelookup_va(va);
- if (tsb[i].tag > 0 &&
- tsb[i].tag == TSB_TAG(0, pm->pm_ctx, va)) {
- tsb[i].data = 0;
- }
/* Force reload -- protections may be changed */
+ tsb_invalidate(pm->pm_ctx, va);
tlb_flush_pte(va, pm->pm_ctx);
- KASSERT((tsb[i].data & TLB_NFO) == 0);
}
/* We will let the fast mmu miss interrupt load the new translation */
@@ -2075,7 +2098,6 @@ pmap_remove(pm, va, endva)
paddr_t pa;
struct vm_page *pg;
pv_entry_t pv;
- int i;
boolean_t flush = FALSE;
/*
@@ -2135,22 +2157,22 @@ pmap_remove(pm, va, endva)
if (!pm->pm_ctx && pm != pmap_kernel())
continue;
- i = ptelookup_va(va);
- if (tsb[i].tag > 0 &&
- tsb[i].tag == TSB_TAG(0, pm->pm_ctx, va)) {
- DPRINTF(PDB_REMOVE, (" clearing TSB [%d]\n", i));
- tsb[i].data = 0;
- }
- REMOVE_STAT(tflushes);
+
+ /*
+ * if the pmap is being torn down, don't bother flushing.
+ */
+
+ if (!pm->pm_refs)
+ continue;
/*
* Here we assume nothing can get into the TLB
* unless it has a PTE.
*/
- if (pm->pm_refs) {
- tlb_flush_pte(va, pm->pm_ctx);
- }
+ tsb_invalidate(pm->pm_ctx, va);
+ REMOVE_STAT(tflushes);
+ tlb_flush_pte(va, pm->pm_ctx);
}
simple_unlock(&pm->pm_lock);
if (flush && pm->pm_refs) {
@@ -2174,14 +2196,10 @@ pmap_protect(pm, sva, eva, prot)
int64_t data;
struct vm_page *pg;
pv_entry_t pv;
- int i;
-
+
KASSERT(pm != pmap_kernel() || eva < INTSTACK || sva > EINTSTACK);
KASSERT(pm != pmap_kernel() || eva < kdata || sva > ekdata);
- if ((prot & (VM_PROT_WRITE|PMAP_WIRED)) == VM_PROT_WRITE)
- return;
-
if (prot == VM_PROT_NONE) {
pmap_remove(pm, sva, eva);
return;
@@ -2216,15 +2234,6 @@ pmap_protect(pm, sva, eva, prot)
(u_int)sva, (long long)pa, (int)va_to_seg(sva),
(int)va_to_pte(sva)));
-#ifdef DEBUG
- /* Catch this before the assertion */
- if (data & TLB_NFO) {
- printf("pmap_protect: pm=%p NFO mapping "
- "va=%x data=%08llx\n",
- pm, (u_int)sva, (long long)data);
- Debugger();
- }
-#endif
pg = PHYS_TO_VM_PAGE(pa);
if (pg) {
/* Save REF/MOD info */
@@ -2236,12 +2245,11 @@ pmap_protect(pm, sva, eva, prot)
}
/* Just do the pmap and TSB, not the pv_list */
- data &= ~(TLB_W|TLB_REAL_W);
- /* Turn *ON* write to wired mappings. */
- if ((prot & (VM_PROT_WRITE|PMAP_WIRED)) ==
- (VM_PROT_WRITE|PMAP_WIRED))
- data |= (TLB_W|TLB_REAL_W);
- KASSERT((data & TLB_NFO) == 0);
+ if ((prot & VM_PROT_WRITE) == 0)
+ data &= ~(TLB_W|TLB_REAL_W);
+ if ((prot & VM_PROT_EXECUTE) == 0)
+ data &= ~(TLB_EXEC);
+
if (pseg_set(pm, sva, data, 0)) {
printf("pmap_protect: gotten pseg empty!\n");
Debugger();
@@ -2250,12 +2258,8 @@ pmap_protect(pm, sva, eva, prot)
if (!pm->pm_ctx && pm != pmap_kernel())
continue;
- i = ptelookup_va(sva);
- if (tsb[i].tag > 0 &&
- tsb[i].tag == TSB_TAG(0, pm->pm_ctx, sva)) {
- tsb[i].data = data;
- KASSERT((tsb[i].data & TLB_NFO) == 0);
- }
+
+ tsb_invalidate(pm->pm_ctx, sva);
tlb_flush_pte(sva, pm->pm_ctx);
}
simple_unlock(&pm->pm_lock);
@@ -2330,6 +2334,31 @@ pmap_extract(pm, va, pap)
}
/*
+ * Change protection on a kernel address.
+ * This should only be called from MD code.
+ */
+void
+pmap_kprotect(va, prot)
+ vaddr_t va;
+ vm_prot_t prot;
+{
+ struct pmap *pm = pmap_kernel();
+ int64_t data;
+
+ simple_lock(&pm->pm_lock);
+ data = pseg_get(pm, va);
+ if (prot & VM_PROT_WRITE) {
+ data |= (TLB_W|TLB_REAL_W);
+ } else {
+ data &= ~(TLB_W|TLB_REAL_W);
+ }
+ (void) pseg_set(pm, va, data, 0);
+ tsb_invalidate(pm->pm_ctx, va);
+ tlb_flush_pte(va, pm->pm_ctx);
+ simple_unlock(&pm->pm_lock);
+}
+
+/*
* Return the number bytes that pmap_dumpmmu() will dump.
*/
int
@@ -2508,33 +2537,6 @@ ptelookup_va(va)
return (tsbptr / sizeof(pte_t));
}
-#if notyet
-void
-tsb_enter(ctx, va, data)
- int ctx;
- int64_t va;
- int64_t data;
-{
- int i, s;
- int64_t pa;
-
- i = ptelookup_va(va);
- s = splvm();
- pa = tsb[i].data&TLB_PA_MASK;
-
- /*
- * If we use fast DMMU access fault handlers to track
- * referenced and modified bits, we should save the
- * TSB entry's state here. Since we don't, we don't.
- */
- /* Do not use global entries */
- tsb[i].tag = TSB_TAG(0,ctx,va);
- tsb[i].data = data;
- tlb_flush_pte(va, ctx); /* Force reload -- protections may be changed */
- splx(s);
-}
-#endif
-
/*
* Do whatever is needed to sync the MOD/REF flags
*/
@@ -2545,7 +2547,7 @@ pmap_clear_modify(pg)
{
paddr_t pa = VM_PAGE_TO_PHYS(pg);
pv_entry_t pv;
- int i, changed = 0;
+ int changed = 0;
#ifdef DEBUG
int modified = 0;
@@ -2587,16 +2589,13 @@ pmap_clear_modify(pg)
#else
data &= ~(TLB_MODIFY|TLB_W|TLB_REAL_W);
#endif
- KASSERT((data & TLB_NFO) == 0);
if (pseg_set(pmap, va, data, 0)) {
printf("pmap_clear_modify: pseg empty!\n");
Debugger();
/* panic? */
}
if (pmap->pm_ctx || pmap == pmap_kernel()) {
- i = ptelookup_va(va);
- if (tsb[i].tag == TSB_TAG(0, pmap->pm_ctx, va))
- tsb[i].data = 0;
+ tsb_invalidate(pmap->pm_ctx, va);
tlb_flush_pte(va, pmap->pm_ctx);
}
/* Then clear the mod bit in the pv */
@@ -2638,7 +2637,7 @@ pmap_clear_reference(pg)
{
paddr_t pa = VM_PAGE_TO_PHYS(pg);
pv_entry_t pv;
- int i, changed = 0;
+ int changed = 0;
#ifdef DEBUG
int referenced = 0;
#endif
@@ -2649,10 +2648,6 @@ pmap_clear_reference(pg)
#endif
/* Clear all references */
pv = &pg->mdpage.mdpg_pvh;
-#ifdef NOT_DEBUG
- if (pv->pv_va & PV_MOD)
- printf("pmap_clear_reference(): pg %p still modified\n", pg);
-#endif
if (pv->pv_va & PV_REF)
changed |= 1;
pv->pv_va &= ~(PV_REF);
@@ -2683,19 +2678,13 @@ pmap_clear_reference(pg)
changed |= 1;
data = 0;
#endif
- KASSERT((data & TLB_NFO) == 0);
if (pseg_set(pmap, va, data, 0)) {
printf("pmap_clear_reference: pseg empty!\n");
Debugger();
/* panic? */
}
if (pmap->pm_ctx || pmap == pmap_kernel()) {
- i = ptelookup_va(va);
-
- /* Invalidate our TSB entry since ref info
- is in the PTE */
- if (tsb[i].tag == TSB_TAG(0, pmap->pm_ctx, va))
- tsb[i].data = 0;
+ tsb_invalidate(pmap->pm_ctx, va);
tlb_flush_pte(va, pmap->pm_ctx);
}
if (pv->pv_va & PV_REF)
@@ -2869,7 +2858,6 @@ pmap_page_protect(pg, prot)
pv_entry_t pv, npv, firstpv;
struct pmap *pmap;
vaddr_t va;
- int i;
boolean_t needflush = FALSE;
DPRINTF(PDB_CHANGEPROT,
@@ -2914,7 +2902,6 @@ pmap_page_protect(pg, prot)
data &= ~clear;
data |= set;
- KASSERT((data & TLB_NFO) == 0);
if (pseg_set(pmap, va, data, 0)) {
printf("pmap_page_protect: "
"pseg empty!\n");
@@ -2922,17 +2909,7 @@ pmap_page_protect(pg, prot)
/* panic? */
}
if (pmap->pm_ctx || pmap == pmap_kernel()) {
- i = ptelookup_va(va);
-
- /*
- * since we already know the va
- * for each mapping, we don't need to
- * scan the entire TSB.
- */
-
- if (tsb[i].tag ==
- TSB_TAG(0, pmap->pm_ctx, va))
- tsb[i].data = 0;
+ tsb_invalidate(pmap->pm_ctx, va);
tlb_flush_pte(va, pmap->pm_ctx);
}
simple_unlock(&pmap->pm_lock);
@@ -2972,17 +2949,7 @@ pmap_page_protect(pg, prot)
/* panic? */
}
if (pmap->pm_ctx || pmap == pmap_kernel()) {
- /* clear the entry in the TSB */
- i = ptelookup_va(va);
-
- /*
- * since we already know the va for
- * each mapping we don't need to scan
- * the entire TSB.
- */
-
- if (tsb[i].tag == TSB_TAG(0, pmap->pm_ctx, va))
- tsb[i].data = 0;
+ tsb_invalidate(pmap->pm_ctx, va);
tlb_flush_pte(va, pmap->pm_ctx);
}
if (pmap->pm_refs > 0) {
@@ -3027,16 +2994,7 @@ pmap_page_protect(pg, prot)
}
if (pv->pv_pmap->pm_ctx ||
pv->pv_pmap == pmap_kernel()) {
- i = ptelookup_va(va);
-
- /*
- * since we already know the va for
- * each mapping we don't need to scan
- * the entire TSB.
- */
-
- if (tsb[i].tag == TSB_TAG(0, pmap->pm_ctx, va))
- tsb[i].data = 0;
+ tsb_invalidate(pmap->pm_ctx, va);
tlb_flush_pte(va, pmap->pm_ctx);
}
if (pmap->pm_refs > 0) {
@@ -3169,7 +3127,6 @@ int
ctx_alloc(pm)
struct pmap *pm;
{
- int64_t *tsbaddr;
int i, ctx;
KASSERT(pm != pmap_kernel());
@@ -3188,10 +3145,11 @@ ctx_alloc(pm)
ctx_free(LIST_FIRST(&pmap_ctxlist));
}
for (i = TSBENTS - 1; i >= 0; i--) {
- if (TSB_TAG_CTX(tsb[i].tag) != 0) {
- tsbaddr = &tsb[i].data;
- __asm __volatile("clrx [%0]"
- : : "r" (tsbaddr) : "memory");
+ if (TSB_TAG_CTX(tsb_dmmu[i].tag) != 0) {
+ clrx(&tsb_dmmu[i].data);
+ }
+ if (TSB_TAG_CTX(tsb_immu[i].tag) != 0) {
+ clrx(&tsb_immu[i].data);
}
}
tlb_flush_all();
@@ -3398,7 +3356,6 @@ pmap_page_cache(pm, pa, mode)
struct vm_page *pg;
pv_entry_t pv;
vaddr_t va;
- int i;
DPRINTF(PDB_ENTER, ("pmap_page_uncache(%llx)\n",
(unsigned long long)pa));
@@ -3437,13 +3394,9 @@ pmap_page_cache(pm, pa, mode)
if (pv->pv_pmap != pm)
simple_unlock(&pv->pv_pmap->pm_lock);
if (pv->pv_pmap->pm_ctx || pv->pv_pmap == pmap_kernel()) {
- i = ptelookup_va(va);
- if (tsb[i].tag > 0 && tsb[i].tag ==
- TSB_TAG(0, pv->pv_pmap->pm_ctx, va)) {
- tsb[i].data = 0;
- }
/* Force reload -- cache bits have changed */
- tlb_flush_pte(va, pv->pv_pmap->pm_ctx);
+ tsb_invalidate(pv->pv_pmap->pm_ctx, va);
+ tlb_flush_pte(va, pv->pv_pmap->pm_ctx);
}
pv = pv->pv_next;
}
diff --git a/sys/compat/aout/aout_exec.c b/sys/compat/aout/aout_exec.c
index d64203387ef..15c7e56f97c 100644
--- a/sys/compat/aout/aout_exec.c
+++ b/sys/compat/aout/aout_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: aout_exec.c,v 1.15 2002/11/01 19:26:21 jdolecek Exp $ */
+/* $NetBSD: aout_exec.c,v 1.16 2003/08/24 17:52:40 chs Exp $ */
/*-
* Copyright (c) 1998, 2000 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: aout_exec.c,v 1.15 2002/11/01 19:26:21 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: aout_exec.c,v 1.16 2003/08/24 17:52:40 chs Exp $");
#if defined(_KERNEL_OPT)
#include "opt_syscall_debug.h"
@@ -62,7 +62,9 @@ void syscall_intern __P((struct proc *));
void syscall __P((void));
#endif
-struct emul emul_netbsd_aout = {
+struct uvm_object *emul_netbsd_aout_object;
+
+const struct emul emul_netbsd_aout = {
"netbsd",
"/emul/aout",
#ifndef __HAVE_MINIMAL_EMUL
@@ -81,6 +83,7 @@ struct emul emul_netbsd_aout = {
trapsignal,
sigcode,
esigcode,
+ &emul_netbsd_aout_object,
setregs,
NULL,
NULL,
diff --git a/sys/compat/aoutm68k/aoutm68k_exec.c b/sys/compat/aoutm68k/aoutm68k_exec.c
index 80bb5f50088..e7c1df81549 100644
--- a/sys/compat/aoutm68k/aoutm68k_exec.c
+++ b/sys/compat/aoutm68k/aoutm68k_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: aoutm68k_exec.c,v 1.12 2002/11/10 20:59:04 jdolecek Exp $ */
+/* $NetBSD: aoutm68k_exec.c,v 1.13 2003/08/24 17:52:40 chs Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: aoutm68k_exec.c,v 1.12 2002/11/10 20:59:04 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: aoutm68k_exec.c,v 1.13 2003/08/24 17:52:40 chs Exp $");
#if defined(_KERNEL_OPT)
#include "opt_syscall_debug.h"
@@ -59,7 +59,9 @@ extern const char * const aoutm68k_syscallnames[];
extern char sigcode[], esigcode[];
void aoutm68k_syscall_intern __P((struct proc *));
-struct emul emul_netbsd_aoutm68k = {
+struct uvm_object *emul_netbsd_aoutm68k_object;
+
+const struct emul emul_netbsd_aoutm68k = {
"aoutm68k",
"/emul/aout",
#ifndef __HAVE_MINIMAL_EMUL
@@ -78,6 +80,7 @@ struct emul emul_netbsd_aoutm68k = {
trapsignal,
sigcode,
esigcode,
+ &emul_netbsd_aoutm68k_object,
setregs,
NULL,
NULL,
diff --git a/sys/compat/darwin/darwin_exec.c b/sys/compat/darwin/darwin_exec.c
index 1e9f1161b74..257053be570 100644
--- a/sys/compat/darwin/darwin_exec.c
+++ b/sys/compat/darwin/darwin_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: darwin_exec.c,v 1.16 2003/06/29 22:29:15 fvdl Exp $ */
+/* $NetBSD: darwin_exec.c,v 1.17 2003/08/24 17:52:40 chs Exp $ */
/*-
* Copyright (c) 2002 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
#include "opt_compat_darwin.h" /* For COMPAT_DARWIN in mach_port.h */
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: darwin_exec.c,v 1.16 2003/06/29 22:29:15 fvdl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: darwin_exec.c,v 1.17 2003/08/24 17:52:40 chs Exp $");
#include "opt_syscall_debug.h"
@@ -80,6 +80,8 @@ void syscall(void);
void mach_syscall_intern(struct proc *);
#endif
+struct uvm_object *emul_darwin_object;
+
const struct emul emul_darwin = {
"darwin",
"/emul/darwin",
@@ -99,6 +101,7 @@ const struct emul emul_darwin = {
trapsignal,
sigcode,
esigcode,
+ &emul_darwin_object,
setregs,
darwin_e_proc_exec,
darwin_e_proc_fork,
diff --git a/sys/compat/freebsd/freebsd_exec.c b/sys/compat/freebsd/freebsd_exec.c
index 5bdc2b69947..3e8970dd184 100644
--- a/sys/compat/freebsd/freebsd_exec.c
+++ b/sys/compat/freebsd/freebsd_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: freebsd_exec.c,v 1.19 2002/11/01 19:26:21 jdolecek Exp $ */
+/* $NetBSD: freebsd_exec.c,v 1.20 2003/08/24 17:52:41 chs Exp $ */
/*
* Copyright (c) 1993, 1994 Christopher G. Demetriou
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: freebsd_exec.c,v 1.19 2002/11/01 19:26:21 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: freebsd_exec.c,v 1.20 2003/08/24 17:52:41 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -50,6 +50,8 @@ void syscall_intern __P((struct proc *));
void syscall __P((void));
#endif
+struct uvm_object *emul_freebsd_object;
+
const struct emul emul_freebsd = {
"freebsd",
"/emul/freebsd",
@@ -65,6 +67,7 @@ const struct emul emul_freebsd = {
trapsignal,
freebsd_sigcode,
freebsd_esigcode,
+ &emul_freebsd_object,
freebsd_setregs,
NULL,
NULL,
diff --git a/sys/compat/hpux/hpux_exec.c b/sys/compat/hpux/hpux_exec.c
index 2725c311074..07aef00ba70 100644
--- a/sys/compat/hpux/hpux_exec.c
+++ b/sys/compat/hpux/hpux_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: hpux_exec.c,v 1.37 2003/06/29 22:29:17 fvdl Exp $ */
+/* $NetBSD: hpux_exec.c,v 1.38 2003/08/24 17:52:41 chs Exp $ */
/*-
* Copyright (c) 1996, 1997 The NetBSD Foundation, Inc.
@@ -70,7 +70,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: hpux_exec.c,v 1.37 2003/06/29 22:29:17 fvdl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: hpux_exec.c,v 1.38 2003/08/24 17:52:41 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -108,6 +108,8 @@ void hpux_syscall_intern __P((struct proc *));
void syscall __P((void));
#endif
+struct uvm_object *emul_hpux_object;
+
const struct emul emul_hpux = {
"hpux",
"/emul/hpux",
@@ -123,6 +125,7 @@ const struct emul emul_hpux = {
trapsignal,
sigcode,
esigcode,
+ &emul_hpux_object,
hpux_setregs,
NULL,
NULL,
diff --git a/sys/compat/ibcs2/ibcs2_exec.c b/sys/compat/ibcs2/ibcs2_exec.c
index f9f799291e9..19b13519d68 100644
--- a/sys/compat/ibcs2/ibcs2_exec.c
+++ b/sys/compat/ibcs2/ibcs2_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ibcs2_exec.c,v 1.52 2002/12/21 15:48:57 kristerw Exp $ */
+/* $NetBSD: ibcs2_exec.c,v 1.53 2003/08/24 17:52:42 chs Exp $ */
/*
* Copyright (c) 1994, 1995, 1998 Scott Bartram
@@ -35,7 +35,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ibcs2_exec.c,v 1.52 2002/12/21 15:48:57 kristerw Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ibcs2_exec.c,v 1.53 2003/08/24 17:52:42 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -67,6 +67,8 @@ void syscall __P((void));
int ibcs2_debug = 1;
#endif
+struct uvm_object *emul_ibcs2_object;
+
const struct emul emul_ibcs2 = {
"ibcs2",
"/emul/ibcs2",
@@ -82,6 +84,7 @@ const struct emul emul_ibcs2 = {
trapsignal,
ibcs2_sigcode,
ibcs2_esigcode,
+ &emul_ibcs2_object,
ibcs2_setregs,
ibcs2_e_proc_exec,
NULL,
diff --git a/sys/compat/irix/irix_exec.c b/sys/compat/irix/irix_exec.c
index 52d291c2bfe..eea32b964e1 100644
--- a/sys/compat/irix/irix_exec.c
+++ b/sys/compat/irix/irix_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: irix_exec.c,v 1.29 2003/06/28 08:31:16 he Exp $ */
+/* $NetBSD: irix_exec.c,v 1.30 2003/08/24 17:52:42 chs Exp $ */
/*-
* Copyright (c) 2001-2002 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: irix_exec.c,v 1.29 2003/06/28 08:31:16 he Exp $");
+__KERNEL_RCSID(0, "$NetBSD: irix_exec.c,v 1.30 2003/08/24 17:52:42 chs Exp $");
#ifdef _KERNEL_OPT
#include "opt_syscall_debug.h"
@@ -98,6 +98,7 @@ const struct emul emul_irix = {
trapsignal,
NULL,
NULL,
+ NULL,
setregs,
irix_e_proc_exec,
irix_e_proc_fork,
diff --git a/sys/compat/irix/irix_exec.h b/sys/compat/irix/irix_exec.h
index b7b1c5c5eac..c8886aba089 100644
--- a/sys/compat/irix/irix_exec.h
+++ b/sys/compat/irix/irix_exec.h
@@ -1,4 +1,4 @@
-/* $NetBSD: irix_exec.h,v 1.19 2003/06/29 22:29:22 fvdl Exp $ */
+/* $NetBSD: irix_exec.h,v 1.20 2003/08/24 17:52:42 chs Exp $ */
/*-
* Copyright (c) 2001-2002 The NetBSD Foundation, Inc.
@@ -107,6 +107,5 @@ int irix_elf64_probe __P((struct proc *, struct exec_package *, void *,
void irix_n32_setregs __P((struct lwp *, struct exec_package *, u_long));
extern const struct emul emul_irix;
-extern const struct emul emul_irix;
#endif /* !_IRIX_EXEC_H_ */
diff --git a/sys/compat/linux/arch/i386/linux_machdep.c b/sys/compat/linux/arch/i386/linux_machdep.c
index b6f9497bc8c..245a29af05f 100644
--- a/sys/compat/linux/arch/i386/linux_machdep.c
+++ b/sys/compat/linux/arch/i386/linux_machdep.c
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_machdep.c,v 1.94 2003/08/21 08:36:56 hannken Exp $ */
+/* $NetBSD: linux_machdep.c,v 1.95 2003/08/24 17:52:43 chs Exp $ */
/*-
* Copyright (c) 1995, 2000 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.94 2003/08/21 08:36:56 hannken Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_machdep.c,v 1.95 2003/08/24 17:52:43 chs Exp $");
#if defined(_KERNEL_OPT)
#include "opt_vm86.h"
@@ -174,7 +174,7 @@ linux_setregs(l, epp, stack)
tf->tf_ecx = 0;
tf->tf_eax = 0;
tf->tf_eip = epp->ep_entry;
- tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
+ tf->tf_cs = GSEL(GUCODEBIG_SEL, SEL_UPL);
tf->tf_eflags = PSL_USERSET;
tf->tf_esp = stack;
tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
@@ -413,7 +413,7 @@ linux_old_sendsig(sig, mask, code)
tf->tf_es = GSEL(GUDATA_SEL, SEL_UPL);
tf->tf_ds = GSEL(GUDATA_SEL, SEL_UPL);
tf->tf_eip = (int)p->p_sigctx.ps_sigcode;
- tf->tf_cs = GSEL(GUCODE_SEL, SEL_UPL);
+ tf->tf_cs = GSEL(GUCODEBIG_SEL, SEL_UPL);
tf->tf_eflags &= ~(PSL_T|PSL_VM|PSL_AC);
tf->tf_esp = (int)fp;
tf->tf_ss = GSEL(GUDATA_SEL, SEL_UPL);
diff --git a/sys/compat/linux/common/linux_exec.c b/sys/compat/linux/common/linux_exec.c
index b61cb0f0b0e..8525d570fb3 100644
--- a/sys/compat/linux/common/linux_exec.c
+++ b/sys/compat/linux/common/linux_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: linux_exec.c,v 1.64 2003/06/29 22:29:26 fvdl Exp $ */
+/* $NetBSD: linux_exec.c,v 1.65 2003/08/24 17:52:43 chs Exp $ */
/*-
* Copyright (c) 1994, 1995, 1998, 2000 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: linux_exec.c,v 1.64 2003/06/29 22:29:26 fvdl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: linux_exec.c,v 1.65 2003/08/24 17:52:43 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -111,6 +111,9 @@ linux_sys_execve(l, v, retval)
/*
* Emulation switch.
*/
+
+struct uvm_object *emul_linux_object;
+
const struct emul emul_linux = {
"linux",
"/emul/linux",
@@ -126,6 +129,7 @@ const struct emul emul_linux = {
linux_trapsignal,
linux_sigcode,
linux_esigcode,
+ &emul_linux_object,
linux_setregs,
linux_e_proc_exec,
linux_e_proc_fork,
diff --git a/sys/compat/mach/mach_exec.c b/sys/compat/mach/mach_exec.c
index 4ddd949d945..cbd572b7c6f 100644
--- a/sys/compat/mach/mach_exec.c
+++ b/sys/compat/mach/mach_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: mach_exec.c,v 1.32 2003/06/29 22:29:34 fvdl Exp $ */
+/* $NetBSD: mach_exec.c,v 1.33 2003/08/24 17:52:44 chs Exp $ */
/*-
* Copyright (c) 2001-2003 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.32 2003/06/29 22:29:34 fvdl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: mach_exec.c,v 1.33 2003/08/24 17:52:44 chs Exp $");
#include "opt_syscall_debug.h"
@@ -78,6 +78,8 @@ void syscall(void);
void mach_syscall_intern(struct proc *);
#endif
+struct uvm_object *emul_mach_object;
+
const struct emul emul_mach = {
"mach",
"/emul/mach",
@@ -97,6 +99,7 @@ const struct emul emul_mach = {
trapsignal,
sigcode,
esigcode,
+ &emul_mach_object,
setregs,
mach_e_proc_exec,
mach_e_proc_fork,
diff --git a/sys/compat/netbsd32/netbsd32_netbsd.c b/sys/compat/netbsd32/netbsd32_netbsd.c
index 60ed7f75bff..6bacc27ff18 100644
--- a/sys/compat/netbsd32/netbsd32_netbsd.c
+++ b/sys/compat/netbsd32/netbsd32_netbsd.c
@@ -1,4 +1,4 @@
-/* $NetBSD: netbsd32_netbsd.c,v 1.73 2003/06/29 22:29:39 fvdl Exp $ */
+/* $NetBSD: netbsd32_netbsd.c,v 1.74 2003/08/24 17:52:44 chs Exp $ */
/*
* Copyright (c) 1998, 2001 Matthew R. Green
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: netbsd32_netbsd.c,v 1.73 2003/06/29 22:29:39 fvdl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: netbsd32_netbsd.c,v 1.74 2003/08/24 17:52:44 chs Exp $");
#if defined(_KERNEL_OPT)
#include "opt_ddb.h"
@@ -107,6 +107,8 @@ void netbsd32_syscall_intern __P((struct proc *));
void syscall __P((void));
#endif
+struct uvm_object *emul_netbsd32_object;
+
const struct emul emul_netbsd32 = {
"netbsd32",
"/emul/netbsd32",
@@ -126,6 +128,7 @@ const struct emul emul_netbsd32 = {
trapsignal,
netbsd32_sigcode,
netbsd32_esigcode,
+ &emul_netbsd32_object,
netbsd32_setregs,
NULL,
NULL,
diff --git a/sys/compat/osf1/osf1_exec.c b/sys/compat/osf1/osf1_exec.c
index 9e614a8b203..3a1d4f74c9b 100644
--- a/sys/compat/osf1/osf1_exec.c
+++ b/sys/compat/osf1/osf1_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: osf1_exec.c,v 1.31 2002/11/01 19:26:23 jdolecek Exp $ */
+/* $NetBSD: osf1_exec.c,v 1.32 2003/08/24 17:52:44 chs Exp $ */
/*
* Copyright (c) 1999 Christopher G. Demetriou. All rights reserved.
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: osf1_exec.c,v 1.31 2002/11/01 19:26:23 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: osf1_exec.c,v 1.32 2003/08/24 17:52:44 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -52,6 +52,8 @@ void osf1_syscall_intern __P((struct proc *));
void syscall __P((void));
#endif
+struct uvm_object *emul_osf1_object;
+
const struct emul emul_osf1 = {
"osf1",
"/emul/osf1",
@@ -67,6 +69,7 @@ const struct emul emul_osf1 = {
trapsignal,
osf1_sigcode,
osf1_esigcode,
+ &emul_osf1_object,
setregs,
NULL,
NULL,
diff --git a/sys/compat/pecoff/pecoff_emul.c b/sys/compat/pecoff/pecoff_emul.c
index 5b8c39e59b3..c974915f657 100644
--- a/sys/compat/pecoff/pecoff_emul.c
+++ b/sys/compat/pecoff/pecoff_emul.c
@@ -1,4 +1,4 @@
-/* $NetBSD: pecoff_emul.c,v 1.5 2003/06/23 15:10:03 martin Exp $ */
+/* $NetBSD: pecoff_emul.c,v 1.6 2003/08/24 17:52:45 chs Exp $ */
/*
* Copyright (c) 2000 Masaru OKI
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pecoff_emul.c,v 1.5 2003/06/23 15:10:03 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pecoff_emul.c,v 1.6 2003/08/24 17:52:45 chs Exp $");
/*#define DEBUG_PECOFF*/
@@ -75,6 +75,8 @@ void syscall_intern(struct proc *);
void syscall(void);
#endif
+struct uvm_object *emul_pecoff_object;
+
const struct emul emul_pecoff = {
"pecoff",
"/emul/pecoff",
@@ -94,6 +96,7 @@ const struct emul emul_pecoff = {
trapsignal,
sigcode,
esigcode,
+ &emul_pecoff_object,
setregs,
NULL,
NULL,
diff --git a/sys/compat/sunos/sunos_exec.c b/sys/compat/sunos/sunos_exec.c
index ed1bbc7863c..eb3280fba40 100644
--- a/sys/compat/sunos/sunos_exec.c
+++ b/sys/compat/sunos/sunos_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sunos_exec.c,v 1.40 2002/11/10 20:59:03 jdolecek Exp $ */
+/* $NetBSD: sunos_exec.c,v 1.41 2003/08/24 17:52:45 chs Exp $ */
/*
* Copyright (c) 1993 Theo de Raadt
@@ -28,7 +28,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunos_exec.c,v 1.40 2002/11/10 20:59:03 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunos_exec.c,v 1.41 2003/08/24 17:52:45 chs Exp $");
#if defined(_KERNEL_OPT)
#include "opt_syscall_debug.h"
@@ -57,7 +57,9 @@ void sunos_syscall_intern __P((struct proc *));
void syscall __P((void));
#endif
-struct emul emul_sunos = {
+struct uvm_object *emul_sunos_object;
+
+const struct emul emul_sunos = {
"sunos",
"/emul/sunos",
#ifndef __HAVE_MINIMAL_EMUL
@@ -76,6 +78,7 @@ struct emul emul_sunos = {
trapsignal,
sunos_sigcode,
sunos_esigcode,
+ &emul_sunos_object,
setregs,
NULL,
NULL,
diff --git a/sys/compat/sunos32/sunos32_exec.c b/sys/compat/sunos32/sunos32_exec.c
index f9dfe4a23b4..02c90bd27b9 100644
--- a/sys/compat/sunos32/sunos32_exec.c
+++ b/sys/compat/sunos32/sunos32_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: sunos32_exec.c,v 1.14 2002/11/10 20:59:04 jdolecek Exp $ */
+/* $NetBSD: sunos32_exec.c,v 1.15 2003/08/24 17:52:45 chs Exp $ */
/*
* Copyright (c) 2001 Matthew R. Green
@@ -29,7 +29,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sunos32_exec.c,v 1.14 2002/11/10 20:59:04 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sunos32_exec.c,v 1.15 2003/08/24 17:52:45 chs Exp $");
#if defined(_KERNEL_OPT)
#include "opt_syscall_debug.h"
@@ -51,6 +51,8 @@ extern const char * const sunos32_syscallnames[];
extern char sunos_sigcode[], sunos_esigcode[];
void syscall __P((void));
+struct uvm_object *emul_sunos32_object;
+
const struct emul emul_sunos = {
"sunos32",
"/emul/sunos",
@@ -70,6 +72,7 @@ const struct emul emul_sunos = {
trapsignal,
sunos_sigcode,
sunos_esigcode,
+ &emul_sunos32_object,
sunos32_setregs,
NULL,
NULL,
diff --git a/sys/compat/svr4/svr4_exec.c b/sys/compat/svr4/svr4_exec.c
index 71c09069af8..4b0470708f6 100644
--- a/sys/compat/svr4/svr4_exec.c
+++ b/sys/compat/svr4/svr4_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: svr4_exec.c,v 1.49 2002/11/01 19:26:23 jdolecek Exp $ */
+/* $NetBSD: svr4_exec.c,v 1.50 2003/08/24 17:52:46 chs Exp $ */
/*-
* Copyright (c) 1994, 2000 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: svr4_exec.c,v 1.49 2002/11/01 19:26:23 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: svr4_exec.c,v 1.50 2003/08/24 17:52:46 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -58,6 +58,8 @@ extern const char * const svr4_syscallnames[];
void syscall __P((void));
#endif
+struct uvm_object *emul_svr4_object;
+
const struct emul emul_svr4 = {
"svr4",
"/emul/svr4",
@@ -73,6 +75,7 @@ const struct emul emul_svr4 = {
trapsignal,
svr4_sigcode,
svr4_esigcode,
+ &emul_svr4_object,
svr4_setregs,
NULL,
NULL,
diff --git a/sys/compat/svr4_32/svr4_32_exec.c b/sys/compat/svr4_32/svr4_32_exec.c
index 186c178203e..0ccc85994a7 100644
--- a/sys/compat/svr4_32/svr4_32_exec.c
+++ b/sys/compat/svr4_32/svr4_32_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: svr4_32_exec.c,v 1.9 2002/11/01 19:26:24 jdolecek Exp $ */
+/* $NetBSD: svr4_32_exec.c,v 1.10 2003/08/24 17:52:46 chs Exp $ */
/*-
* Copyright (c) 1994, 2000 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: svr4_32_exec.c,v 1.9 2002/11/01 19:26:24 jdolecek Exp $");
+__KERNEL_RCSID(0, "$NetBSD: svr4_32_exec.c,v 1.10 2003/08/24 17:52:46 chs Exp $");
#define ELFSIZE 32 /* XXX should die */
@@ -60,6 +60,8 @@ extern const char * const svr4_32_syscallnames[];
void syscall __P((void));
#endif
+struct uvm_object *emul_svr4_32_object;
+
const struct emul emul_svr4_32 = {
"svr4_32",
"/emul/svr4_32",
@@ -75,6 +77,7 @@ const struct emul emul_svr4_32 = {
trapsignal,
svr4_32_sigcode,
svr4_32_esigcode,
+ &emul_svr4_32_object,
svr4_32_setregs,
NULL,
NULL,
diff --git a/sys/compat/ultrix/ultrix_misc.c b/sys/compat/ultrix/ultrix_misc.c
index e6dbd80a303..d4fbbea6bef 100644
--- a/sys/compat/ultrix/ultrix_misc.c
+++ b/sys/compat/ultrix/ultrix_misc.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ultrix_misc.c,v 1.86 2003/08/07 16:30:47 agc Exp $ */
+/* $NetBSD: ultrix_misc.c,v 1.87 2003/08/24 17:52:46 chs Exp $ */
/*
* Copyright (c) 1995, 1997 Jonathan Stone (hereinafter referred to as the author)
@@ -76,7 +76,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ultrix_misc.c,v 1.86 2003/08/07 16:30:47 agc Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ultrix_misc.c,v 1.87 2003/08/24 17:52:46 chs Exp $");
#if defined(_KERNEL_OPT)
#include "opt_nfsserver.h"
@@ -156,6 +156,8 @@ void syscall_intern(struct proc *);
void syscall __P((void));
#endif
+struct uvm_object *emul_ultrix_object;
+
const struct emul emul_ultrix = {
"ultrix",
"/emul/ultrix",
@@ -171,6 +173,7 @@ const struct emul emul_ultrix = {
trapsignal,
ultrix_sigcode,
ultrix_esigcode,
+ &emul_ultrix_object,
setregs,
NULL,
NULL,
diff --git a/sys/kern/exec_subr.c b/sys/kern/exec_subr.c
index 0c66a790564..e74eeab987a 100644
--- a/sys/kern/exec_subr.c
+++ b/sys/kern/exec_subr.c
@@ -1,4 +1,4 @@
-/* $NetBSD: exec_subr.c,v 1.39 2003/08/21 15:17:03 yamt Exp $ */
+/* $NetBSD: exec_subr.c,v 1.40 2003/08/24 17:52:47 chs Exp $ */
/*
* Copyright (c) 1993, 1994, 1996 Christopher G. Demetriou
@@ -31,7 +31,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: exec_subr.c,v 1.39 2003/08/21 15:17:03 yamt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: exec_subr.c,v 1.40 2003/08/24 17:52:47 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -121,7 +121,7 @@ kill_vmcmds(struct exec_vmcmd_set *evsp)
for (i = 0; i < evsp->evs_used; i++) {
vcp = &evsp->evs_cmds[i];
- if (vcp->ev_vp != NULLVP)
+ if (vcp->ev_vp != NULL)
vrele(vcp->ev_vp);
}
evsp->evs_used = evsp->evs_cnt = 0;
@@ -344,12 +344,11 @@ exec_setup_stack(struct proc *p, struct exec_package *epp)
access_size), noaccess_size);
if (noaccess_size > 0) {
NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, noaccess_size,
- noaccess_linear_min, NULLVP, 0, VM_PROT_NONE);
+ noaccess_linear_min, NULL, 0, VM_PROT_NONE);
}
KASSERT(access_size > 0);
NEW_VMCMD(&epp->ep_vmcmds, vmcmd_map_zero, access_size,
- access_linear_min, NULLVP, 0,
- VM_PROT_READ|VM_PROT_WRITE|VM_PROT_EXECUTE);
+ access_linear_min, NULL, 0, VM_PROT_READ | VM_PROT_WRITE);
return 0;
}
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 7343bd51d14..4e1656d8ca4 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_exec.c,v 1.170 2003/07/16 22:42:48 dsl Exp $ */
+/* $NetBSD: kern_exec.c,v 1.171 2003/08/24 17:52:47 chs Exp $ */
/*-
* Copyright (C) 1993, 1994, 1996 Christopher G. Demetriou
@@ -33,7 +33,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.170 2003/07/16 22:42:48 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.171 2003/08/24 17:52:47 chs Exp $");
#include "opt_ktrace.h"
#include "opt_syscall_debug.h"
@@ -68,6 +68,8 @@ __KERNEL_RCSID(0, "$NetBSD: kern_exec.c,v 1.170 2003/07/16 22:42:48 dsl Exp $");
#include <machine/cpu.h>
#include <machine/reg.h>
+static int exec_sigcode_map(struct proc *, const struct emul *);
+
#ifdef DEBUG_EXEC
#define DPRINTF(a) uprintf a
#else
@@ -129,6 +131,8 @@ void syscall_intern(struct proc *);
void syscall(void);
#endif
+struct uvm_object *emul_netbsd_object;
+
const struct emul emul_netbsd = {
"netbsd",
NULL, /* emulation path */
@@ -148,6 +152,7 @@ const struct emul emul_netbsd = {
trapsignal,
sigcode,
esigcode,
+ &emul_netbsd_object,
setregs,
NULL,
NULL,
@@ -629,7 +634,7 @@ sys_execve(struct lwp *l, void *v, register_t *retval)
* it's easy to decrement the stack pointer a little bit to
* allocate the space for these few words and pass the new
* stack pointer to _rtld. When the stack grows up, however,
- * a few words before argc is part of the signal trampoline,
+ * a few words before argc is part of the signal trampoline, XXX
* so we have a problem.
*
* Instead of changing how _rtld works, we take the easy way
@@ -664,21 +669,6 @@ sys_execve(struct lwp *l, void *v, register_t *retval)
goto exec_abort;
}
- /* copy out the process's signal trampoline code */
- if (szsigcode) {
- p->p_sigctx.ps_sigcode = STACK_ALLOC(STACK_MAX(p->p_psstr,
- sizeof(struct ps_strings)), szsigcode);
- if ((error = copyout((char *)pack.ep_es->es_emul->e_sigcode,
- p->p_sigctx.ps_sigcode, szsigcode)) != 0) {
- DPRINTF(("execve: sig trampoline copyout failed\n"));
- goto exec_abort;
- }
-#ifdef PMAP_NEED_PROCWR
- /* This is code. Let the pmap do what is needed. */
- pmap_procwr(p, (vaddr_t)p->p_sigctx.ps_sigcode, szsigcode);
-#endif
- }
-
stopprofclock(p); /* stop profiling */
fdcloseexec(p); /* handle close on exec */
execsigs(p); /* reset catched signals */
@@ -766,6 +756,10 @@ sys_execve(struct lwp *l, void *v, register_t *retval)
if (pack.ep_es->es_setregs)
(*pack.ep_es->es_setregs)(l, &pack, (u_long) stack);
+ /* map the process's signal trampoline code */
+ if (exec_sigcode_map(p, pack.ep_es->es_emul))
+ goto exec_abort;
+
if (p->p_flag & P_TRACED)
psignal(p, SIGTRAP);
@@ -1271,3 +1265,64 @@ exec_init(int init_boot)
}
#endif /* !LKM */
+
+static int
+exec_sigcode_map(struct proc *p, const struct emul *e)
+{
+ vaddr_t va;
+ vsize_t sz;
+ int error;
+ struct uvm_object *uobj;
+
+ if (e->e_sigobject == NULL) {
+ return 0;
+ }
+
+ /*
+ * If we don't have a sigobject for this emulation, create one.
+ *
+ * sigobject is an anonymous memory object (just like SYSV shared
+ * memory) that we keep a permanent reference to and that we map
+ * in all processes that need this sigcode. The creation is simple,
+ * we create an object, add a permanent reference to it, map it in
+ * kernel space, copy out the sigcode to it and unmap it.
+ * The we map it with PROT_READ|PROT_EXEC into the process just
+ * the way sys_mmap would map it.
+ */
+
+ sz = (vaddr_t)e->e_esigcode - (vaddr_t)e->e_sigcode;
+ uobj = *e->e_sigobject;
+ if (uobj == NULL) {
+ uobj = uao_create(sz, 0);
+ uao_reference(uobj);
+ va = vm_map_min(kernel_map);
+ if ((error = uvm_map(kernel_map, &va, round_page(sz),
+ uobj, 0, 0,
+ UVM_MAPFLAG(UVM_PROT_RW, UVM_PROT_RW,
+ UVM_INH_SHARE, UVM_ADV_RANDOM, 0)))) {
+ printf("kernel mapping failed %d\n", error);
+ (*uobj->pgops->pgo_detach)(uobj);
+ return (error);
+ }
+ memcpy((void *)va, e->e_sigcode, sz);
+#ifdef PMAP_NEED_PROCWR
+ pmap_procwr(&proc0, va, sz);
+#endif
+ uvm_unmap(kernel_map, va, va + round_page(sz));
+ *e->e_sigobject = uobj;
+ }
+
+ /* Just a hint to uvm_mmap where to put it. */
+ va = round_page((vaddr_t)p->p_vmspace->vm_daddr + MAXDSIZ);
+ (*uobj->pgops->pgo_reference)(uobj);
+ error = uvm_map(&p->p_vmspace->vm_map, &va, round_page(sz),
+ uobj, 0, 0,
+ UVM_MAPFLAG(UVM_PROT_RX, UVM_PROT_RX, UVM_INH_SHARE,
+ UVM_ADV_RANDOM, 0));
+ if (error) {
+ (*uobj->pgops->pgo_detach)(uobj);
+ return (error);
+ }
+ p->p_sigctx.ps_sigcode = (void *)va;
+ return (0);
+}
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
index d29582845eb..aa912d3b10b 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -1,4 +1,4 @@
-/* $NetBSD: kern_resource.c,v 1.72 2003/08/07 16:31:48 agc Exp $ */
+/* $NetBSD: kern_resource.c,v 1.73 2003/08/24 17:52:47 chs Exp $ */
/*-
* Copyright (c) 1982, 1986, 1991, 1993
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.72 2003/08/07 16:31:48 agc Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_resource.c,v 1.73 2003/08/24 17:52:47 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -323,7 +323,7 @@ dosetrlimit(p, cred, which, limp)
vm_prot_t prot;
if (limp->rlim_cur > alimp->rlim_cur) {
- prot = VM_PROT_ALL;
+ prot = VM_PROT_READ | VM_PROT_WRITE;
size = limp->rlim_cur - alimp->rlim_cur;
addr = USRSTACK - limp->rlim_cur;
} else {
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index a949e80f23d..9d64fe9af50 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -1,4 +1,4 @@
-/* $NetBSD: proc.h,v 1.168 2003/08/07 16:34:10 agc Exp $ */
+/* $NetBSD: proc.h,v 1.169 2003/08/24 17:52:47 chs Exp $ */
/*-
* Copyright (c) 1986, 1989, 1991, 1993
@@ -104,6 +104,7 @@ struct emul {
char *e_sigcode; /* Start of sigcode */
char *e_esigcode; /* End of sigcode */
/* Set registers before execution */
+ struct uvm_object **e_sigobject;/* shared sigcode object */
void (*e_setregs) __P((struct lwp *, struct exec_package *,
u_long));
diff --git a/sys/uvm/uvm_unix.c b/sys/uvm/uvm_unix.c
index 069d60ace14..b21a67626f4 100644
--- a/sys/uvm/uvm_unix.c
+++ b/sys/uvm/uvm_unix.c
@@ -1,4 +1,4 @@
-/* $NetBSD: uvm_unix.c,v 1.28 2003/05/25 13:00:40 simonb Exp $ */
+/* $NetBSD: uvm_unix.c,v 1.29 2003/08/24 17:52:48 chs Exp $ */
/*
* Copyright (c) 1997 Charles D. Cranor and Washington University.
@@ -50,7 +50,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: uvm_unix.c,v 1.28 2003/05/25 13:00:40 simonb Exp $");
+__KERNEL_RCSID(0, "$NetBSD: uvm_unix.c,v 1.29 2003/08/24 17:52:48 chs Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -95,12 +95,14 @@ sys_obreak(l, v, retval)
/*
* grow or shrink?
*/
+
if (new > old) {
error = uvm_map(&vm->vm_map, &old, new - old, NULL,
UVM_UNKNOWN_OFFSET, 0,
- UVM_MAPFLAG(UVM_PROT_ALL, UVM_PROT_ALL, UVM_INH_COPY,
- UVM_ADV_NORMAL, UVM_FLAG_AMAPPAD|UVM_FLAG_FIXED|
- UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW));
+ UVM_MAPFLAG(UVM_PROT_READ | UVM_PROT_WRITE, UVM_PROT_ALL,
+ UVM_INH_COPY,
+ UVM_ADV_NORMAL, UVM_FLAG_AMAPPAD|UVM_FLAG_FIXED|
+ UVM_FLAG_OVERLAY|UVM_FLAG_COPYONW));
if (error) {
uprintf("sbrk: grow %ld failed, error = %d\n",
new - old, error);