From owner-svn-src-stable@freebsd.org Wed Feb 14 15:14:21 2018 Return-Path: Delivered-To: svn-src-stable@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id D813AF0634C; Wed, 14 Feb 2018 15:14:20 +0000 (UTC) (envelope-from skra@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 8972A7D105; Wed, 14 Feb 2018 15:14:20 +0000 (UTC) (envelope-from skra@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 84535117F6; Wed, 14 Feb 2018 15:14:20 +0000 (UTC) (envelope-from skra@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w1EFEK5j049711; Wed, 14 Feb 2018 15:14:20 GMT (envelope-from skra@FreeBSD.org) Received: (from skra@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w1EFEKxg049710; Wed, 14 Feb 2018 15:14:20 GMT (envelope-from skra@FreeBSD.org) Message-Id: <201802141514.w1EFEKxg049710@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: skra set sender to skra@FreeBSD.org using -f From: Svatopluk Kraus Date: Wed, 14 Feb 2018 15:14:20 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r329263 - stable/11/sys/arm/arm X-SVN-Group: stable-11 X-SVN-Commit-Author: skra X-SVN-Commit-Paths: stable/11/sys/arm/arm X-SVN-Commit-Revision: 329263 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-stable@freebsd.org X-Mailman-Version: 2.1.25 Precedence: list List-Id: SVN commit messages for all the -stable branches of the src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 14 Feb 2018 15:14:21 -0000 Author: skra Date: Wed Feb 14 15:14:20 2018 New Revision: 329263 URL: https://svnweb.freebsd.org/changeset/base/329263 Log: MFC r325321: Take into account race conditions in case of accessed or modified bit emulation in fast path of data/prefetch abort common routine. Process these bits only if related page table entries are consistent with provided abort info. In case of inconsistency, do nothing and let processor to signal new abort if still needed. Modified: stable/11/sys/arm/arm/pmap-v6.c Directory Properties: stable/11/ (props changed) Modified: stable/11/sys/arm/arm/pmap-v6.c ============================================================================== --- stable/11/sys/arm/arm/pmap-v6.c Wed Feb 14 15:12:09 2018 (r329262) +++ stable/11/sys/arm/arm/pmap-v6.c Wed Feb 14 15:14:20 2018 (r329263) @@ -6433,6 +6433,22 @@ pmap_fault(pmap_t pmap, vm_offset_t far, uint32_t fsr, */ PMAP_LOCK(pmap); +#ifdef INVARIANTS + pte1 = pte1_load(pmap_pte1(pmap, far)); + if (pte1_is_link(pte1)) { + /* + * Check in advance that associated L2 page table is mapped into + * PT2MAP space. Note that faulty access to not mapped L2 page + * table is caught in more general check above where "far" is + * checked that it does not lay in PT2MAP space. Note also that + * L1 page table and PT2TAB always exist and are mapped. + */ + pte2 = pt2tab_load(pmap_pt2tab_entry(pmap, far)); + if (!pte2_is_valid(pte2)) + panic("%s: missing L2 page table (%p, %#x)", + __func__, pmap, far); + } +#endif #ifdef SMP /* * Special treatment is due to break-before-make approach done when @@ -6453,10 +6469,23 @@ pmap_fault(pmap_t pmap, vm_offset_t far, uint32_t fsr, * for aborts from user mode. */ if (idx == FAULT_ACCESS_L2) { - pte2p = pt2map_entry(far); - pte2 = pte2_load(pte2p); - if (pte2_is_valid(pte2)) { - pte2_store(pte2p, pte2 | PTE2_A); + pte1 = pte1_load(pmap_pte1(pmap, far)); + if (pte1_is_link(pte1)) { + /* L2 page table should exist and be mapped. */ + pte2p = pt2map_entry(far); + pte2 = pte2_load(pte2p); + if (pte2_is_valid(pte2)) { + pte2_store(pte2p, pte2 | PTE2_A); + PMAP_UNLOCK(pmap); + return (KERN_SUCCESS); + } + } else { + /* + * We got L2 access fault but PTE1 is not a link. + * Probably some race happened, do nothing. + */ + CTR3(KTR_PMAP, "%s: FAULT_ACCESS_L2 - pmap %#x far %#x", + __func__, pmap, far); PMAP_UNLOCK(pmap); return (KERN_SUCCESS); } @@ -6468,6 +6497,15 @@ pmap_fault(pmap_t pmap, vm_offset_t far, uint32_t fsr, pte1_store(pte1p, pte1 | PTE1_A); PMAP_UNLOCK(pmap); return (KERN_SUCCESS); + } else { + /* + * We got L1 access fault but PTE1 is not section + * mapping. Probably some race happened, do nothing. + */ + CTR3(KTR_PMAP, "%s: FAULT_ACCESS_L1 - pmap %#x far %#x", + __func__, pmap, far); + PMAP_UNLOCK(pmap); + return (KERN_SUCCESS); } } @@ -6480,12 +6518,25 @@ pmap_fault(pmap_t pmap, vm_offset_t far, uint32_t fsr, * for aborts from user mode. */ if ((fsr & FSR_WNR) && (idx == FAULT_PERM_L2)) { - pte2p = pt2map_entry(far); - pte2 = pte2_load(pte2p); - if (pte2_is_valid(pte2) && !(pte2 & PTE2_RO) && - (pte2 & PTE2_NM)) { - pte2_store(pte2p, pte2 & ~PTE2_NM); - tlb_flush(trunc_page(far)); + pte1 = pte1_load(pmap_pte1(pmap, far)); + if (pte1_is_link(pte1)) { + /* L2 page table should exist and be mapped. */ + pte2p = pt2map_entry(far); + pte2 = pte2_load(pte2p); + if (pte2_is_valid(pte2) && !(pte2 & PTE2_RO) && + (pte2 & PTE2_NM)) { + pte2_store(pte2p, pte2 & ~PTE2_NM); + tlb_flush(trunc_page(far)); + PMAP_UNLOCK(pmap); + return (KERN_SUCCESS); + } + } else { + /* + * We got L2 permission fault but PTE1 is not a link. + * Probably some race happened, do nothing. + */ + CTR3(KTR_PMAP, "%s: FAULT_PERM_L2 - pmap %#x far %#x", + __func__, pmap, far); PMAP_UNLOCK(pmap); return (KERN_SUCCESS); } @@ -6493,10 +6544,20 @@ pmap_fault(pmap_t pmap, vm_offset_t far, uint32_t fsr, if ((fsr & FSR_WNR) && (idx == FAULT_PERM_L1)) { pte1p = pmap_pte1(pmap, far); pte1 = pte1_load(pte1p); - if (pte1_is_section(pte1) && !(pte1 & PTE1_RO) && - (pte1 & PTE1_NM)) { - pte1_store(pte1p, pte1 & ~PTE1_NM); - tlb_flush(pte1_trunc(far)); + if (pte1_is_section(pte1)) { + if (!(pte1 & PTE1_RO) && (pte1 & PTE1_NM)) { + pte1_store(pte1p, pte1 & ~PTE1_NM); + tlb_flush(pte1_trunc(far)); + PMAP_UNLOCK(pmap); + return (KERN_SUCCESS); + } + } else { + /* + * We got L1 permission fault but PTE1 is not section + * mapping. Probably some race happened, do nothing. + */ + CTR3(KTR_PMAP, "%s: FAULT_PERM_L1 - pmap %#x far %#x", + __func__, pmap, far); PMAP_UNLOCK(pmap); return (KERN_SUCCESS); } @@ -6507,33 +6568,6 @@ pmap_fault(pmap_t pmap, vm_offset_t far, uint32_t fsr, * modify bits aborts, could be moved to ASM. Now we are * starting to deal with not fast aborts. */ - -#ifdef INVARIANTS - /* - * Read an entry in PT2TAB associated with both pmap and far. - * It's safe because PT2TAB is always mapped. - */ - pte2 = pt2tab_load(pmap_pt2tab_entry(pmap, far)); - if (pte2_is_valid(pte2)) { - /* - * Now, when we know that L2 page table is allocated, - * we can use PT2MAP to get L2 page table entry. - */ - pte2 = pte2_load(pt2map_entry(far)); - if (pte2_is_valid(pte2)) { - /* - * If L2 page table entry is valid, make sure that - * L1 page table entry is valid too. Note that we - * leave L2 page entries untouched when promoted. - */ - pte1 = pte1_load(pmap_pte1(pmap, far)); - if (!pte1_is_valid(pte1)) { - panic("%s: missing L1 page entry (%p, %#x)", - __func__, pmap, far); - } - } - } -#endif PMAP_UNLOCK(pmap); return (KERN_FAILURE); }