diff --git a/sys/arch/alpha/alpha/pmap.c b/sys/arch/alpha/alpha/pmap.c index 9fef3139fbf1..a2ab6f73a850 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 /* 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 #include @@ -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; + kp[prot] = PG_ASM; + up[prot] = 0; - 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; - - 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 c86e61eb618f..939bb67e016b 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 /* 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 #include @@ -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 ee2b255d34d9..f8e7b318fe09 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 e2be9a58f35f..a08be807a433 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 9f7787c11096..f7885dee81fd 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 -__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 37deec686a78..6c996afe40e4 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 -__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 c5a5f2305060..ee1dcaefd953 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 -__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 c1a2a2a00cf0..d55b590b77f2 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 -__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 18e207e3d211..c4e1a28831e3 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 -__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 6d698283546b..ed22dfd1a021 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 -__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 73c6888ddb3c..cd6d3b2e0a25 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 cd7ae1033221..cc38cdae9947 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 e085955fe178..3d85f9425598 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 e797320c57be..223bcb6c2907 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 22c52062ad35..4988fbf12a07 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. @@ -74,6 +74,14 @@ #define MAXSSIZ (32*1024*1024) /* max stack size */ #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 */ @@ -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 414c8d5a7442..09d0b5678db3 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 -__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 #include @@ -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 6c8f9a5edcf8..1e4d29a25b4d 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 -__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 67aa2cb1bc2e..61a66ff7b47a 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 7bca941be096..79370cc82a80 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 6794ee0f8645..86bdd7e7fd53 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 -__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) @@ -1644,6 +1649,48 @@ pmap_pvo_remove(struct pvo_entry *pvo, int pteidx) #endif } +/* + * 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. */ @@ -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 21cd790d700b..f86e086ee81c 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 -__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 2fe99e09c742..6721b96a975b 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 -__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" @@ -891,6 +891,59 @@ setpte4m(va, pte) setpgt4m(sp->sg_pte + VA_SUN4M_VPG(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. */ @@ -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 9349920bdeaa..cd56f5fcfb05 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 -__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 fcdd2320f9c5..e9d7354ca0b4 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 17db9a1f6bfe..5f3f4d062004 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 -__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 dc1471dc66dc..2ee601ca3480 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 -__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; ipm_segs[i], ASI_PHYS_CACHED))) { - db_printf("pdir %ld at %lx:\n", i, (long)pdir); - for (k=0; kpm_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<>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 5a11e6359b04..51f2a1ee3662 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 491315a39aff..be28430d4bdc 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 -__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<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); @@ -2329,6 +2333,31 @@ pmap_extract(pm, va, pap) return (TRUE); } +/* + * 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. */ @@ -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 d64203387ef4..15c7e56f97c2 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 -__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 80bb5f500885..e7c1df81549a 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 -__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 1e9f1161b747..257053be5701 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 -__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 5bdc2b699473..3e8970dd184b 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 -__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 #include @@ -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 2725c3110740..07aef00ba705 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 -__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 #include @@ -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 f9f799291e9c..19b13519d68b 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 -__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 #include @@ -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 52d291c2bfe0..eea32b964e14 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 -__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 b7b1c5c5eacc..c8886aba0893 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. @@ -106,7 +106,6 @@ 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 b6f9497bc8c0..245a29af05fc 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 -__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 b61cb0f0b0ef..8525d570fb30 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 -__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 #include @@ -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 4ddd949d9452..cbd572b7c6f6 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 -__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 60ed7f75bff5..6bacc27ff186 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 -__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 9e614a8b2035..3a1d4f74c9b4 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 -__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 #include @@ -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 5b8c39e59b3d..c974915f6571 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 -__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 ed1bbc7863cc..eb3280fba409 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 -__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 f9dfe4a23b4d..02c90bd27b96 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 -__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 71c09069af8a..4b0470708f63 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 -__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 #include @@ -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 186c178203e8..0ccc85994a7e 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 -__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 e6dbd80a3034..d4fbbea6bef0 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 -__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 0c66a7905643..e74eeab987a8 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 -__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 #include @@ -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 7343bd51d144..4e1656d8ca48 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 -__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 #include +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 d29582845ebe..aa912d3b10ba 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 -__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 #include @@ -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 a949e80f23da..9d64fe9af501 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 069d60ace148..b21a67626f4f 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 -__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 #include @@ -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);