From patchwork Wed Jul 19 13:54:50 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ryan Roberts X-Patchwork-Id: 13319022 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 47CDBC001B0 for ; Wed, 19 Jul 2023 13:55:18 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id D7DCA280060; Wed, 19 Jul 2023 09:55:17 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id D2F0028004C; Wed, 19 Jul 2023 09:55:17 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id C2788280060; Wed, 19 Jul 2023 09:55:17 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id B17DD28004C for ; Wed, 19 Jul 2023 09:55:17 -0400 (EDT) Received: from smtpin17.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay07.hostedemail.com (Postfix) with ESMTP id 911E016035F for ; Wed, 19 Jul 2023 13:55:17 +0000 (UTC) X-FDA: 81028508274.17.049C616 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by imf16.hostedemail.com (Postfix) with ESMTP id BB310180005 for ; Wed, 19 Jul 2023 13:55:15 +0000 (UTC) Authentication-Results: imf16.hostedemail.com; dkim=none; spf=pass (imf16.hostedemail.com: domain of ryan.roberts@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=ryan.roberts@arm.com; dmarc=pass (policy=none) header.from=arm.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1689774915; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=G2GF+BZHvW+OuduMU+juyHwMecPdL/HtveJeza/m3Jw=; b=SObHX62Aclqh8LbgUuDvTMH3b087lPTEYTFWPjRILmTqEHrWsBf741LBcN6xuKYhaDE7CJ k9jFuWEZFISCg7Vmgq+laYAQRmTO1pZACHsKD3jUKmICX45BcZqXXZJDoHhNLzsltqOY2a sPTTJcO3ATY7ll3vlN4VpfsTbGA9Hbw= ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1689774915; a=rsa-sha256; cv=none; b=TE1F/uJXayU3H1aVBkQBfnTqrsaqJ9HUGpHckuItX4oJZraO5RTI4aCr7CfHRnEDmNn0UC Fn4Do3hzIGV+T3sJsIc/OIfxWeeCfMKZvpqcaMRkjuP0A1Fwa446JsTIrZdfMnyuVTaZ5v wQgdJfk2pANtJzpUoTQZVDzriKdZq8k= ARC-Authentication-Results: i=1; imf16.hostedemail.com; dkim=none; spf=pass (imf16.hostedemail.com: domain of ryan.roberts@arm.com designates 217.140.110.172 as permitted sender) smtp.mailfrom=ryan.roberts@arm.com; dmarc=pass (policy=none) header.from=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 1A0532F4; Wed, 19 Jul 2023 06:55:58 -0700 (PDT) Received: from e125769.cambridge.arm.com (e125769.cambridge.arm.com [10.1.196.26]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 3DE203F6C4; Wed, 19 Jul 2023 06:55:08 -0700 (PDT) From: Ryan Roberts To: Andrew Morton , Matthew Wilcox , Yin Fengwei , David Hildenbrand , Yu Zhao , Yang Shi , "Huang, Ying" , Zi Yan Cc: Ryan Roberts , linux-kernel@vger.kernel.org, linux-mm@kvack.org Subject: [PATCH v2 3/3] mm: Batch-zap large anonymous folio PTE mappings Date: Wed, 19 Jul 2023 14:54:50 +0100 Message-Id: <20230719135450.545227-4-ryan.roberts@arm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20230719135450.545227-1-ryan.roberts@arm.com> References: <20230719135450.545227-1-ryan.roberts@arm.com> MIME-Version: 1.0 X-Rspamd-Queue-Id: BB310180005 X-Rspam-User: X-Rspamd-Server: rspam11 X-Stat-Signature: 1efzabie3cropu6amopfd6fk35nbujpb X-HE-Tag: 1689774915-217083 X-HE-Meta: U2FsdGVkX18s7cydk6je/6s6Ib9MZZoWwURltF/LAKyHB5x2LYj8QgGeqRHqbvCYbanNKOn7ETEUFlfPH129uui6CiYJaCVUQKNe8mAZFlEykeO8qaV28sfCIGRgIOuUAt4IqohV/qtM2hznKbV2NKoG93whyFExriiYe5TOB5YrR/D2QKG9UesTbragjIbufNYMvJJb6YAmdiRnol1d6+L4Bapend+2Bo1nswORafkZii7mNiSxu9yj5BWjlUKLMwiQ1KLlX2XzBj/1OamLXtxcQ/7HaqZ5/8Op1x/d705iInUVl0aQRDC5yVnufz9vvGlr9P1Q3DBMvK/+Dh0A7vTFb2j1sORg0i0Q7ytMaydT6UmD0LQx0zd2CJrOhprArPBgk2HaNcnHwZIvTpIk2lsBpMnvEQ3gv+K3S56AbuXdyO38Gy4peMV8NrigRbVom274zB5NDGABWxk5yHlD3QZAkiq0zkHXeDHRP++2Y5ueySpPQEdbzGRFxfbEalvL64bkkrJpMbbcjST0l1Ex5onx8M2sXuv5cY/OeWdTNgGyPZ3EFt6uijNaHtBPqhal5x2LMFecRnZsfNhq/LUm9U4yla+PYC8SQZVVa8ZVLWivd4WDsSSwKZilMxHLoxEqvLiAYKi6erZhSu6NVbn61UfokuJMCdJ3rKIgPgtGvIFlmd3Elmm6a3v7HYe+KrD4TPeqiy5go1N7IobtQ2ZVS25kfGtVkCry/Qaj+Xmxc9p0aSb3FqYn08sbI3SbOnAHwoW6GUqnB1UqRpzmy4cYjIIxGjHcr3NljkKeOWy+w8MLLeFeGTNgsQUUbkDku6HQ8FmHJaWFyYRzNAMGzP6chTG1cNfhd5mYLUDTNKFzqI118gwqlOr9GPqFXPLgk65OghePd81k0i3bQkGwoSW8X5igeSjPhym0jtdqSZqi2eNxxDNGpwXYgHVEwluvbkB0r/kSVE4NntcuTyv72Jy Kq6tJXHg Z1CuEuo/VxWQQLAtpbI8cGpVaUOBO1M60KJ7bZfzr40rq7WAkCMjxgLa7x8uggGc8ENSycyEiFx1lXNCHuRpsev52O5j2a1+tG22ksC7FFeEDZ7DAxc8h6xJY0krb7AtvSGPpAUZ8w92YvF5UFS/wzqKejxA5SpQOMjQR X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: This allows batching the rmap removal with folio_remove_rmap_range(), which means we avoid spuriously adding a partially unmapped folio to the deferred split queue in the common case, which reduces split queue lock contention. Previously each page was removed from the rmap individually with page_remove_rmap(). If the first page belonged to a large folio, this would cause page_remove_rmap() to conclude that the folio was now partially mapped and add the folio to the deferred split queue. But subsequent calls would cause the folio to become fully unmapped, meaning there is no value to adding it to the split queue. Signed-off-by: Ryan Roberts --- mm/memory.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 120 insertions(+) diff --git a/mm/memory.c b/mm/memory.c index 01f39e8144ef..189b1cfd823d 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1391,6 +1391,94 @@ zap_install_uffd_wp_if_needed(struct vm_area_struct *vma, pte_install_uffd_wp_if_needed(vma, addr, pte, pteval); } +static inline unsigned long page_cont_mapped_vaddr(struct page *page, + struct page *anchor, unsigned long anchor_vaddr) +{ + unsigned long offset; + unsigned long vaddr; + + offset = (page_to_pfn(page) - page_to_pfn(anchor)) << PAGE_SHIFT; + vaddr = anchor_vaddr + offset; + + if (anchor > page) { + if (vaddr > anchor_vaddr) + return 0; + } else { + if (vaddr < anchor_vaddr) + return ULONG_MAX; + } + + return vaddr; +} + +static int folio_nr_pages_cont_mapped(struct folio *folio, + struct page *page, pte_t *pte, + unsigned long addr, unsigned long end) +{ + pte_t ptent; + int floops; + int i; + unsigned long pfn; + struct page *folio_end; + + if (!folio_test_large(folio)) + return 1; + + folio_end = &folio->page + folio_nr_pages(folio); + end = min(page_cont_mapped_vaddr(folio_end, page, addr), end); + floops = (end - addr) >> PAGE_SHIFT; + pfn = page_to_pfn(page); + pfn++; + pte++; + + for (i = 1; i < floops; i++) { + ptent = ptep_get(pte); + + if (!pte_present(ptent) || pte_pfn(ptent) != pfn) + break; + + pfn++; + pte++; + } + + return i; +} + +static unsigned long try_zap_anon_pte_range(struct mmu_gather *tlb, + struct vm_area_struct *vma, + struct folio *folio, + struct page *page, pte_t *pte, + unsigned long addr, int nr_pages, + struct zap_details *details) +{ + struct mm_struct *mm = tlb->mm; + pte_t ptent; + bool full; + int i; + + for (i = 0; i < nr_pages;) { + ptent = ptep_get_and_clear_full(mm, addr, pte, tlb->fullmm); + tlb_remove_tlb_entry(tlb, pte, addr); + zap_install_uffd_wp_if_needed(vma, addr, pte, details, ptent); + full = __tlb_remove_page(tlb, page, 0); + + if (unlikely(page_mapcount(page) < 1)) + print_bad_pte(vma, addr, ptent, page); + + i++; + page++; + pte++; + addr += PAGE_SIZE; + + if (unlikely(full)) + break; + } + + folio_remove_rmap_range(folio, page - i, i, vma); + + return i; +} + static unsigned long zap_pte_range(struct mmu_gather *tlb, struct vm_area_struct *vma, pmd_t *pmd, unsigned long addr, unsigned long end, @@ -1428,6 +1516,38 @@ static unsigned long zap_pte_range(struct mmu_gather *tlb, page = vm_normal_page(vma, addr, ptent); if (unlikely(!should_zap_page(details, page))) continue; + + /* + * Batch zap large anonymous folio mappings. This allows + * batching the rmap removal, which means we avoid + * spuriously adding a partially unmapped folio to the + * deferrred split queue in the common case, which + * reduces split queue lock contention. + */ + if (page && PageAnon(page)) { + struct folio *folio = page_folio(page); + int nr_pages_req, nr_pages; + + nr_pages_req = folio_nr_pages_cont_mapped( + folio, page, pte, addr, end); + + nr_pages = try_zap_anon_pte_range(tlb, vma, + folio, page, pte, addr, + nr_pages_req, details); + + rss[mm_counter(page)] -= nr_pages; + nr_pages--; + pte += nr_pages; + addr += nr_pages << PAGE_SHIFT; + + if (unlikely(nr_pages < nr_pages_req)) { + force_flush = 1; + addr += PAGE_SIZE; + break; + } + continue; + } + ptent = ptep_get_and_clear_full(mm, addr, pte, tlb->fullmm); tlb_remove_tlb_entry(tlb, pte, addr);