Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752189AbdFNNwU (ORCPT ); Wed, 14 Jun 2017 09:52:20 -0400 Received: from mga14.intel.com ([192.55.52.115]:50513 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751907AbdFNNwS (ORCPT ); Wed, 14 Jun 2017 09:52:18 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.39,340,1493708400"; d="scan'208";a="1182395764" From: "Kirill A. Shutemov" To: Andrew Morton , Vlastimil Babka , Vineet Gupta , Russell King , Will Deacon , Catalin Marinas , Ralf Baechle , "David S. Miller" , Heiko Carstens Cc: "Aneesh Kumar K . V" , Martin Schwidefsky , Andrea Arcangeli , linux-arch@vger.kernel.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org, "Kirill A. Shutemov" , Ingo Molnar , "H . Peter Anvin" , Thomas Gleixner Subject: [PATCH 1/3] x86/mm: Provide pmdp_mknotpresent() helper Date: Wed, 14 Jun 2017 16:51:41 +0300 Message-Id: <20170614135143.25068-2-kirill.shutemov@linux.intel.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20170614135143.25068-1-kirill.shutemov@linux.intel.com> References: <20170614135143.25068-1-kirill.shutemov@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 2340 Lines: 77 We need an atomic way to make pmd page table entry not-present. This is required to implement pmdp_invalidate() that doesn't loose dirty or access bits. On x86, we need to clear two bits -- _PAGE_PRESENT and _PAGE_PROTNONE -- to make the entry non-present. The implementation uses cmpxchg() loop to make it atomically. PAE requires special treatment to avoid expensive cmpxchg8b(). Both bits are in the lower part of the entry, so we can use 4-byte cmpxchg() on this part of page table entry. Signed-off-by: Kirill A. Shutemov Cc: Ingo Molnar Cc: H. Peter Anvin Cc: Thomas Gleixner --- arch/x86/include/asm/pgtable-3level.h | 17 +++++++++++++++++ arch/x86/include/asm/pgtable.h | 13 +++++++++++++ 2 files changed, 30 insertions(+) diff --git a/arch/x86/include/asm/pgtable-3level.h b/arch/x86/include/asm/pgtable-3level.h index 50d35e3185f5..b6efa955ecd0 100644 --- a/arch/x86/include/asm/pgtable-3level.h +++ b/arch/x86/include/asm/pgtable-3level.h @@ -176,8 +176,25 @@ static inline pmd_t native_pmdp_get_and_clear(pmd_t *pmdp) return res.pmd; } + +#define pmdp_mknotpresent pmdp_mknotpresent +static inline void pmdp_mknotpresent(pmd_t *pmdp) +{ + union split_pmd *p, old, new; + + p = (union split_pmd *)pmdp; + { + old = *p; + new.pmd = pmd_mknotpresent(old.pmd); + } while (cmpxchg(&p->pmd_low, old.pmd_low, new.pmd_low) != old.pmd_low); +} #else #define native_pmdp_get_and_clear(xp) native_local_pmdp_get_and_clear(xp) + +static inline void pmdp_mknotpresent(pmd_t *pmdp) +{ + *pmdp = pmd_mknotpresent(*pmdp); +} #endif #ifdef CONFIG_SMP diff --git a/arch/x86/include/asm/pgtable.h b/arch/x86/include/asm/pgtable.h index f5af95a0c6b8..576420df12b8 100644 --- a/arch/x86/include/asm/pgtable.h +++ b/arch/x86/include/asm/pgtable.h @@ -1092,6 +1092,19 @@ static inline void pmdp_set_wrprotect(struct mm_struct *mm, clear_bit(_PAGE_BIT_RW, (unsigned long *)pmdp); } +#ifndef pmdp_mknotpresent +#define pmdp_mknotpresent pmdp_mknotpresent +static inline void pmdp_mknotpresent(pmd_t *pmdp) +{ + pmd_t old, new; + + { + old = *pmdp; + new = pmd_mknotpresent(old); + } while (pmd_val(cmpxchg(pmdp, old, new)) != pmd_val(old)); +} +#endif + /* * clone_pgd_range(pgd_t *dst, pgd_t *src, int count); * -- 2.11.0