From owner-svn-src-all@FreeBSD.ORG Thu Aug 12 10:09:28 2010 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 723961065675; Thu, 12 Aug 2010 10:09:28 +0000 (UTC) (envelope-from jchandra@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 5616D8FC0C; Thu, 12 Aug 2010 10:09:28 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o7CA9SGW046047; Thu, 12 Aug 2010 10:09:28 GMT (envelope-from jchandra@svn.freebsd.org) Received: (from jchandra@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o7CA9Sqf046043; Thu, 12 Aug 2010 10:09:28 GMT (envelope-from jchandra@svn.freebsd.org) Message-Id: <201008121009.o7CA9Sqf046043@svn.freebsd.org> From: "Jayachandran C." Date: Thu, 12 Aug 2010 10:09:28 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r211217 - in head/sys/mips: include mips X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 12 Aug 2010 10:09:28 -0000 Author: jchandra Date: Thu Aug 12 10:09:28 2010 New Revision: 211217 URL: http://svn.freebsd.org/changeset/base/211217 Log: Implement pmap changes suggested by alc@: 1. Move dirty bit emulation code that is duplicted for kernel and user in trap.c to a function pmap_emulate_modified() in pmap.c. 2. While doing dirty bit emulation, it is not necessary to update the TLB entry on all CPUs using smp_rendezvous(), we can just update the TLB entry on the current CPU, and let the other CPUs update their TLB entry lazily if they get an exception. Reviewed by: alc, neel Modified: head/sys/mips/include/pmap.h head/sys/mips/mips/pmap.c head/sys/mips/mips/trap.c Modified: head/sys/mips/include/pmap.h ============================================================================== --- head/sys/mips/include/pmap.h Thu Aug 12 09:15:27 2010 (r211216) +++ head/sys/mips/include/pmap.h Thu Aug 12 10:09:28 2010 (r211217) @@ -157,16 +157,14 @@ void pmap_bootstrap(void); void *pmap_mapdev(vm_offset_t, vm_size_t); void pmap_unmapdev(vm_offset_t, vm_size_t); vm_offset_t pmap_steal_memory(vm_size_t size); -void pmap_set_modified(vm_offset_t pa); int page_is_managed(vm_offset_t pa); void pmap_kenter(vm_offset_t va, vm_paddr_t pa); void pmap_kremove(vm_offset_t va); void *pmap_kenter_temporary(vm_paddr_t pa, int i); void pmap_kenter_temporary_free(vm_paddr_t pa); int pmap_compute_pages_to_dump(void); -void pmap_update_page(pmap_t pmap, vm_offset_t va, pt_entry_t pte); void pmap_flush_pvcache(vm_page_t m); - +int pmap_emulate_modified(pmap_t pmap, vm_offset_t va); #endif /* _KERNEL */ #endif /* !LOCORE */ Modified: head/sys/mips/mips/pmap.c ============================================================================== --- head/sys/mips/mips/pmap.c Thu Aug 12 09:15:27 2010 (r211216) +++ head/sys/mips/mips/pmap.c Thu Aug 12 10:09:28 2010 (r211217) @@ -180,6 +180,7 @@ static void pmap_remove_page(struct pmap static void pmap_remove_entry(struct pmap *pmap, vm_page_t m, vm_offset_t va); static boolean_t pmap_try_insert_pv_entry(pmap_t pmap, vm_page_t mpte, vm_offset_t va, vm_page_t m); +static void pmap_update_page(pmap_t pmap, vm_offset_t va, pt_entry_t pte); static void pmap_invalidate_all(pmap_t pmap); static void pmap_invalidate_page(pmap_t pmap, vm_offset_t va); static int _pmap_unwire_pte_hold(pmap_t pmap, vm_offset_t va, vm_page_t m); @@ -704,7 +705,7 @@ struct pmap_update_page_arg { pt_entry_t pte; }; -void +static void pmap_update_page(pmap_t pmap, vm_offset_t va, pt_entry_t pte) { struct pmap_update_page_arg arg; @@ -723,7 +724,7 @@ pmap_update_page_action(void *arg) pmap_update_page_local(p->pmap, p->va, p->pte); } #else -void +static void pmap_update_page(pmap_t pmap, vm_offset_t va, pt_entry_t pte) { @@ -3265,15 +3266,49 @@ init_pte_prot(vm_offset_t va, vm_page_t } /* - * pmap_set_modified: + * pmap_emulate_modified : do dirty bit emulation * - * Sets the page modified and reference bits for the specified page. + * On SMP, update just the local TLB, other CPUs will update their + * TLBs from PTE lazily, if they get the exception. + * Returns 0 in case of sucess, 1 if the page is read only and we + * need to fault. */ -void -pmap_set_modified(vm_offset_t pa) +int +pmap_emulate_modified(pmap_t pmap, vm_offset_t va) { + vm_page_t m; + pt_entry_t *pte; + vm_offset_t pa; - PHYS_TO_VM_PAGE(pa)->md.pv_flags |= (PV_TABLE_REF | PV_TABLE_MOD); + PMAP_LOCK(pmap); + pte = pmap_pte(pmap, va); + if (pte == NULL) + panic("pmap_emulate_modified: can't find PTE"); +#ifdef SMP + /* It is possible that some other CPU changed m-bit */ + if (!pte_test(pte, PTE_V) || pte_test(pte, PTE_D)) { + pmap_update_page_local(pmap, va, *pte); + PMAP_UNLOCK(pmap); + return (0); + } +#else + if (!pte_test(pte, PTE_V) || pte_test(pte, PTE_D)) + panic("pmap_emulate_modified: invalid pte"); +#endif + if (pte_test(pte, PTE_RO)) { + /* write to read only page in the kernel */ + PMAP_UNLOCK(pmap); + return (1); + } + pte_set(pte, PTE_D); + pmap_update_page_local(pmap, va, *pte); + pa = TLBLO_PTE_TO_PA(*pte); + if (!page_is_managed(pa)) + panic("pmap_emulate_modified: unmanaged page"); + m = PHYS_TO_VM_PAGE(pa); + m->md.pv_flags |= (PV_TABLE_REF | PV_TABLE_MOD); + PMAP_UNLOCK(pmap); + return (0); } /* Modified: head/sys/mips/mips/trap.c ============================================================================== --- head/sys/mips/mips/trap.c Thu Aug 12 09:15:27 2010 (r211216) +++ head/sys/mips/mips/trap.c Thu Aug 12 10:09:28 2010 (r211217) @@ -281,7 +281,6 @@ trap(struct trapframe *trapframe) struct thread *td = curthread; struct proc *p = curproc; vm_prot_t ftype; - pt_entry_t *pte; pmap_t pmap; int access_type; ksiginfo_t ksi; @@ -372,82 +371,24 @@ trap(struct trapframe *trapframe) case T_TLB_MOD: /* check for kernel address */ if (KERNLAND(trapframe->badvaddr)) { - vm_offset_t pa; - - PMAP_LOCK(kernel_pmap); - pte = pmap_pte(kernel_pmap, trapframe->badvaddr); - if (pte == NULL) - panic("trap: ktlbmod: can't find PTE"); -#ifdef SMP - /* It is possible that some other CPU changed m-bit */ - if (!pte_test(pte, PTE_V) || pte_test(pte, PTE_D)) { - pmap_update_page(kernel_pmap, - trapframe->badvaddr, *pte); - PMAP_UNLOCK(kernel_pmap); - return (trapframe->pc); - } -#else - if (!pte_test(pte, PTE_V) || pte_test(pte, PTE_D)) - panic("trap: ktlbmod: invalid pte"); -#endif - if (pte_test(pte, PTE_RO)) { - /* write to read only page in the kernel */ + if (pmap_emulate_modified(kernel_pmap, + trapframe->badvaddr) != 0) { ftype = VM_PROT_WRITE; - PMAP_UNLOCK(kernel_pmap); goto kernel_fault; } - pte_set(pte, PTE_D); - pmap_update_page(kernel_pmap, trapframe->badvaddr, *pte); - pa = TLBLO_PTE_TO_PA(*pte); - if (!page_is_managed(pa)) - panic("trap: ktlbmod: unmanaged page"); - pmap_set_modified(pa); - PMAP_UNLOCK(kernel_pmap); return (trapframe->pc); } /* FALLTHROUGH */ case T_TLB_MOD + T_USER: - { - vm_offset_t pa; - - pmap = &p->p_vmspace->vm_pmap; - - PMAP_LOCK(pmap); - pte = pmap_pte(pmap, trapframe->badvaddr); - if (pte == NULL) - panic("trap: utlbmod: can't find PTE"); -#ifdef SMP - /* It is possible that some other CPU changed m-bit */ - if (!pte_test(pte, PTE_V) || pte_test(pte, PTE_D)) { - pmap_update_page(pmap, trapframe->badvaddr, *pte); - PMAP_UNLOCK(pmap); - goto out; - } -#else - if (!pte_test(pte, PTE_V) || pte_test(pte, PTE_D)) - panic("trap: utlbmod: invalid pte"); -#endif - - if (pte_test(pte, PTE_RO)) { - /* write to read only page */ - ftype = VM_PROT_WRITE; - PMAP_UNLOCK(pmap); - goto dofault; - } - pte_set(pte, PTE_D); - pmap_update_page(pmap, trapframe->badvaddr, *pte); - pa = TLBLO_PTE_TO_PA(*pte); - if (!page_is_managed(pa)) - panic("trap: utlbmod: unmanaged page"); - pmap_set_modified(pa); - - PMAP_UNLOCK(pmap); - if (!usermode) { - return (trapframe->pc); - } - goto out; + pmap = &p->p_vmspace->vm_pmap; + if (pmap_emulate_modified(pmap, trapframe->badvaddr) != 0) { + ftype = VM_PROT_WRITE; + goto dofault; } + if (!usermode) + return (trapframe->pc); + goto out; case T_TLB_LD_MISS: case T_TLB_ST_MISS: