Received: by 2002:a05:7412:2a91:b0:fc:a2b0:25d7 with SMTP id u17csp41492rdh; Tue, 13 Feb 2024 08:50:06 -0800 (PST) X-Forwarded-Encrypted: i=3; AJvYcCUUXrizJb29lNFCrJ+eSEzFzpwyhSWypOGikQbQaSMolkTaUDZMo5xv6jN4QVjjrCpbOBYvF/M5st17wvNWPiQbRDK9nRKiukZbfVn2gQ== X-Google-Smtp-Source: AGHT+IF//ZqiAvbPLrZxDvBhyW1eveHA4TH3BeBt+E8VaC21P5GVHoDzXWeXFBSRRF0+KkGpMV5B X-Received: by 2002:a05:620a:1a8a:b0:785:d804:26a9 with SMTP id bl10-20020a05620a1a8a00b00785d80426a9mr149399qkb.18.1707843005885; Tue, 13 Feb 2024 08:50:05 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1707843005; cv=pass; d=google.com; s=arc-20160816; b=v0N3EvLW9hC7IbMZTY+L+Zgc3JmWjBb4htPymtNaJDpX8gXq/iEj+frzsqwQjNHnoQ IsWdt/Wdzivp0UdcVFxiIAVBZB2eD15ERFpTXFcgc1ubWduZf+FrkjX7ur++bvudYX3j RjstTdc5TFuAybl2yzpHvOAtfz2DHFU0A47xttTGiHpDUu/QUMDuESKh011dr3uSxrrK 1K+lRLZB3dR9WN32nA6S5j2NLON8XUIGXPfxeOVvL88x5Pjw5/ltIdGoZ2tN2uKDCdCr 2+9q2X1ZwAoo5eY6MobxKxOWgFgCBcvfOkSoTNeEanrYcJWUyxmG9pJu/coqmlEgzywi J8MA== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:in-reply-to:from:references:cc:to :content-language:subject:user-agent:mime-version:list-unsubscribe :list-subscribe:list-id:precedence:date:message-id; bh=S5Qgd2h/TB4YoTN8C/XsFotDC25mSZ09EG/vV9H4ldM=; fh=yzFGHegSFk6UlcxxPpE3DfW++5FiteNIKrIstArv0mI=; b=Hf/ySbAnG7SOYn4ionUx+4UuZCrNIczkmxTeFISZAB/l4ysEcDfY9ATOixecWXNayh 1Vv2OtJv0VmRMFs10r1riD5JXQLgDbYQBspwQd83umNIRpzf1UEO6igkMXVLWVTNTTMI C0bgOfaej/r7ciVcI0VRSnAlbmN0UkHUruMy/uKBkmmHrrcqMbSglT7lMFc94YIxOd/O gG+Zgpvlv6Myw+gx26tbOnv8Rdj8+fF2hH4fon4VDx1LYKs2nBLhxFwFmLWUpSNEDOuG Z/gS7YMfe50h4N+Aj77q6pEnGzshpdERDjN2TaP1JUEBp93EpTzDQpp7zTd5wzu7ADrS Vulg==; dara=google.com ARC-Authentication-Results: i=2; mx.google.com; arc=pass (i=1 spf=pass spfdomain=arm.com dmarc=pass fromdomain=arm.com); spf=pass (google.com: domain of linux-kernel+bounces-63937-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-63937-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com X-Forwarded-Encrypted: i=2; AJvYcCXh7Yw4P6iPVP41zKY09QU17BCwVrZC1YhwvQbF7/EJjIAYBlEbTo9f4riI9s1I2Lod1pBZsY9yiqSwXXorb3NGc2nANNTnyIYBdXfKhw== Return-Path: Received: from ny.mirrors.kernel.org (ny.mirrors.kernel.org. [147.75.199.223]) by mx.google.com with ESMTPS id h8-20020a05620a13e800b00785d8aaec7dsi4324495qkl.365.2024.02.13.08.50.05 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 13 Feb 2024 08:50:05 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel+bounces-63937-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) client-ip=147.75.199.223; Authentication-Results: mx.google.com; arc=pass (i=1 spf=pass spfdomain=arm.com dmarc=pass fromdomain=arm.com); spf=pass (google.com: domain of linux-kernel+bounces-63937-linux.lists.archive=gmail.com@vger.kernel.org designates 147.75.199.223 as permitted sender) smtp.mailfrom="linux-kernel+bounces-63937-linux.lists.archive=gmail.com@vger.kernel.org"; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=arm.com Received: from smtp.subspace.kernel.org (wormhole.subspace.kernel.org [52.25.139.140]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ny.mirrors.kernel.org (Postfix) with ESMTPS id 16F6A1C236E0 for ; Tue, 13 Feb 2024 16:50:05 +0000 (UTC) Received: from localhost.localdomain (localhost.localdomain [127.0.0.1]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 9DE515FBA1; Tue, 13 Feb 2024 16:48:58 +0000 (UTC) Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id F173D5DF29 for ; Tue, 13 Feb 2024 16:48:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707842938; cv=none; b=m4zqc1BcpKXKPGnck6Lm5pW58ClQc4c2i3ZQbjQiJnMx8mQWWLZLGF7HD40JU6VUuzCh72396/NCPt1Zakgq0hW2rSZtLk6T8XrxO+N36olO4pQeUWZC5KVBXUqcr+YDZ5ZQoGI+m9w5GKF1h8e5ZfC8JodSHMCyJlzcYVzsrqU= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707842938; c=relaxed/simple; bh=0zU1P0q/AiovSFg302dxcukywFAagconXoCXEO9D95M=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=sfW3MN7gN1Gll9cEzUQxU3FffqZyyof1f+DiOLIUMm/DWR2DYAFI9mCDjQr4GBOl0Q2ndGoeDdZNUXS14Rr9RZMumPjefT6aUgo3e0rDHzt6cj21H0egqeI0TK/4BE8kki/8zoQjdybvHq3bfAfuR+x1ZWSQFFIGAmnrBiHz8X8= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 4E6F9DA7; Tue, 13 Feb 2024 08:49:36 -0800 (PST) Received: from [10.1.36.184] (XHFQ2J9959.cambridge.arm.com [10.1.36.184]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 4EA173F5A1; Tue, 13 Feb 2024 08:48:51 -0800 (PST) Message-ID: Date: Tue, 13 Feb 2024 16:48:50 +0000 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: Re: [PATCH v5 21/25] arm64/mm: Implement new [get_and_]clear_full_ptes() batch APIs Content-Language: en-GB To: Mark Rutland Cc: Catalin Marinas , Will Deacon , Ard Biesheuvel , Marc Zyngier , James Morse , Andrey Ryabinin , Andrew Morton , Matthew Wilcox , David Hildenbrand , Kefeng Wang , John Hubbard , Zi Yan , Barry Song <21cnbao@gmail.com>, Alistair Popple , Yang Shi , Nicholas Piggin , Christophe Leroy , "Aneesh Kumar K.V" , "Naveen N. Rao" , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , "H. Peter Anvin" , linux-arm-kernel@lists.infradead.org, x86@kernel.org, linuxppc-dev@lists.ozlabs.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org References: <20240202080756.1453939-1-ryan.roberts@arm.com> <20240202080756.1453939-22-ryan.roberts@arm.com> From: Ryan Roberts In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit On 13/02/2024 16:43, Mark Rutland wrote: > On Fri, Feb 02, 2024 at 08:07:52AM +0000, Ryan Roberts wrote: >> Optimize the contpte implementation to fix some of the >> exit/munmap/dontneed performance regression introduced by the initial >> contpte commit. Subsequent patches will solve it entirely. >> >> During exit(), munmap() or madvise(MADV_DONTNEED), mappings must be >> cleared. Previously this was done 1 PTE at a time. But the core-mm >> supports batched clear via the new [get_and_]clear_full_ptes() APIs. So >> let's implement those APIs and for fully covered contpte mappings, we no >> longer need to unfold the contpte. This significantly reduces unfolding >> operations, reducing the number of tlbis that must be issued. >> >> Tested-by: John Hubbard >> Signed-off-by: Ryan Roberts >> --- >> arch/arm64/include/asm/pgtable.h | 67 ++++++++++++++++++++++++++++++++ >> arch/arm64/mm/contpte.c | 17 ++++++++ >> 2 files changed, 84 insertions(+) >> >> diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h >> index c07f0d563733..ad04adb7b87f 100644 >> --- a/arch/arm64/include/asm/pgtable.h >> +++ b/arch/arm64/include/asm/pgtable.h >> @@ -965,6 +965,37 @@ static inline pte_t __ptep_get_and_clear(struct mm_struct *mm, >> return pte; >> } >> >> +static inline void __clear_full_ptes(struct mm_struct *mm, unsigned long addr, >> + pte_t *ptep, unsigned int nr, int full) >> +{ >> + for (;;) { >> + __ptep_get_and_clear(mm, addr, ptep); >> + if (--nr == 0) >> + break; >> + ptep++; >> + addr += PAGE_SIZE; >> + } >> +} > > The loop construct is a bit odd; can't this be: I found it a little odd at first, but its avoiding the ptep and addr increments the last time through the loop. Its the preferred pattern for these functions in core-mm. See default set_ptes(), wrprotect_ptes(), clear_full_ptes() in include/linux/pgtable.h. So I'd prefer to leave it as is so that we match them. What do you think? > > while (nr--) { > __ptep_get_and_clear(mm, addr, ptep); > ptep++; > addr += PAGE_SIZE; > } > > ... or: > > do { > __ptep_get_and_clear(mm, addr, ptep); > ptep++; > addr += PAGE_SIZE; > } while (--nr); > > ... ? > > Otherwise, this looks good to me. > > Mark. > >> + >> +static inline pte_t __get_and_clear_full_ptes(struct mm_struct *mm, >> + unsigned long addr, pte_t *ptep, >> + unsigned int nr, int full) >> +{ >> + pte_t pte, tmp_pte; >> + >> + pte = __ptep_get_and_clear(mm, addr, ptep); >> + while (--nr) { >> + ptep++; >> + addr += PAGE_SIZE; >> + tmp_pte = __ptep_get_and_clear(mm, addr, ptep); >> + if (pte_dirty(tmp_pte)) >> + pte = pte_mkdirty(pte); >> + if (pte_young(tmp_pte)) >> + pte = pte_mkyoung(pte); >> + } >> + return pte; >> +} >> + >> #ifdef CONFIG_TRANSPARENT_HUGEPAGE >> #define __HAVE_ARCH_PMDP_HUGE_GET_AND_CLEAR >> static inline pmd_t pmdp_huge_get_and_clear(struct mm_struct *mm, >> @@ -1167,6 +1198,11 @@ extern pte_t contpte_ptep_get(pte_t *ptep, pte_t orig_pte); >> extern pte_t contpte_ptep_get_lockless(pte_t *orig_ptep); >> extern void contpte_set_ptes(struct mm_struct *mm, unsigned long addr, >> pte_t *ptep, pte_t pte, unsigned int nr); >> +extern void contpte_clear_full_ptes(struct mm_struct *mm, unsigned long addr, >> + pte_t *ptep, unsigned int nr, int full); >> +extern pte_t contpte_get_and_clear_full_ptes(struct mm_struct *mm, >> + unsigned long addr, pte_t *ptep, >> + unsigned int nr, int full); >> extern int contpte_ptep_test_and_clear_young(struct vm_area_struct *vma, >> unsigned long addr, pte_t *ptep); >> extern int contpte_ptep_clear_flush_young(struct vm_area_struct *vma, >> @@ -1254,6 +1290,35 @@ static inline void pte_clear(struct mm_struct *mm, >> __pte_clear(mm, addr, ptep); >> } >> >> +#define clear_full_ptes clear_full_ptes >> +static inline void clear_full_ptes(struct mm_struct *mm, unsigned long addr, >> + pte_t *ptep, unsigned int nr, int full) >> +{ >> + if (likely(nr == 1)) { >> + contpte_try_unfold(mm, addr, ptep, __ptep_get(ptep)); >> + __clear_full_ptes(mm, addr, ptep, nr, full); >> + } else { >> + contpte_clear_full_ptes(mm, addr, ptep, nr, full); >> + } >> +} >> + >> +#define get_and_clear_full_ptes get_and_clear_full_ptes >> +static inline pte_t get_and_clear_full_ptes(struct mm_struct *mm, >> + unsigned long addr, pte_t *ptep, >> + unsigned int nr, int full) >> +{ >> + pte_t pte; >> + >> + if (likely(nr == 1)) { >> + contpte_try_unfold(mm, addr, ptep, __ptep_get(ptep)); >> + pte = __get_and_clear_full_ptes(mm, addr, ptep, nr, full); >> + } else { >> + pte = contpte_get_and_clear_full_ptes(mm, addr, ptep, nr, full); >> + } >> + >> + return pte; >> +} >> + >> #define __HAVE_ARCH_PTEP_GET_AND_CLEAR >> static inline pte_t ptep_get_and_clear(struct mm_struct *mm, >> unsigned long addr, pte_t *ptep) >> @@ -1338,6 +1403,8 @@ static inline int ptep_set_access_flags(struct vm_area_struct *vma, >> #define set_pte __set_pte >> #define set_ptes __set_ptes >> #define pte_clear __pte_clear >> +#define clear_full_ptes __clear_full_ptes >> +#define get_and_clear_full_ptes __get_and_clear_full_ptes >> #define __HAVE_ARCH_PTEP_GET_AND_CLEAR >> #define ptep_get_and_clear __ptep_get_and_clear >> #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG >> diff --git a/arch/arm64/mm/contpte.c b/arch/arm64/mm/contpte.c >> index c85e64baf03b..80346108450b 100644 >> --- a/arch/arm64/mm/contpte.c >> +++ b/arch/arm64/mm/contpte.c >> @@ -207,6 +207,23 @@ void contpte_set_ptes(struct mm_struct *mm, unsigned long addr, >> } >> EXPORT_SYMBOL(contpte_set_ptes); >> >> +void contpte_clear_full_ptes(struct mm_struct *mm, unsigned long addr, >> + pte_t *ptep, unsigned int nr, int full) >> +{ >> + contpte_try_unfold_partial(mm, addr, ptep, nr); >> + __clear_full_ptes(mm, addr, ptep, nr, full); >> +} >> +EXPORT_SYMBOL(contpte_clear_full_ptes); >> + >> +pte_t contpte_get_and_clear_full_ptes(struct mm_struct *mm, >> + unsigned long addr, pte_t *ptep, >> + unsigned int nr, int full) >> +{ >> + contpte_try_unfold_partial(mm, addr, ptep, nr); >> + return __get_and_clear_full_ptes(mm, addr, ptep, nr, full); >> +} >> +EXPORT_SYMBOL(contpte_get_and_clear_full_ptes); >> + >> int contpte_ptep_test_and_clear_young(struct vm_area_struct *vma, >> unsigned long addr, pte_t *ptep) >> { >> -- >> 2.25.1 >>