From patchwork Wed Jul 3 21:29:18 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Xu X-Patchwork-Id: 13722804 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 C65A6C2BD09 for ; Wed, 3 Jul 2024 21:29:50 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 439606B009C; Wed, 3 Jul 2024 17:29:45 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 3ECFB6B009D; Wed, 3 Jul 2024 17:29:45 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 213226B009E; Wed, 3 Jul 2024 17:29:45 -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 05E876B009C for ; Wed, 3 Jul 2024 17:29:45 -0400 (EDT) Received: from smtpin26.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay01.hostedemail.com (Postfix) with ESMTP id 7BFBD1C1A20 for ; Wed, 3 Jul 2024 21:29:44 +0000 (UTC) X-FDA: 82299733488.26.A6848B2 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by imf27.hostedemail.com (Postfix) with ESMTP id 3F14B4000F for ; Wed, 3 Jul 2024 21:29:42 +0000 (UTC) Authentication-Results: imf27.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=LoRntBCu; spf=pass (imf27.hostedemail.com: domain of peterx@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=peterx@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1720042169; 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-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=j2Zxgw15onbd0eMS/03kg+dHZsOcAz6IsQR1l1z1OuE=; b=rMJz4eh/spwXUKMZzrg4KKKiV2jMtQ98GSV0GqykveoYdNXy1gkgtX/8e/duA10PMNsvUC lBm/yprQO3x4+hfATcJW8mYQ69JCILg3fRadDEQFtseJYR9hQlGhXvPOp92Fb8MqtVaYZz hv4BGJ6UsQ6fhvMjVURBvAuWIRcU6zc= ARC-Authentication-Results: i=1; imf27.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=LoRntBCu; spf=pass (imf27.hostedemail.com: domain of peterx@redhat.com designates 170.10.129.124 as permitted sender) smtp.mailfrom=peterx@redhat.com; dmarc=pass (policy=none) header.from=redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1720042169; a=rsa-sha256; cv=none; b=UTAu/aytr2OmBtzyAi2aqyuwOWaKh1izjCxhMvtoWtA8HrFYVU30w6BoQbsDrNy+jHc2gf xGVIcSASkjF/wumK7L/QYFWnZkV0Y7Z2mdwkkSNih+jx9qthbvpBcwRs3axvP2Nt2IYPID VDhsWEHp0b9qdD1fMNqK21vqXRhvh/w= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1720042181; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=j2Zxgw15onbd0eMS/03kg+dHZsOcAz6IsQR1l1z1OuE=; b=LoRntBCuK5FTB0c0NjbQ+TQkcVOdJNntHrpJ3DNVwSOiLMgMUPYR5N7XjW1iWuUBrWz+Su QAgKCsYFRGZ6gHaDCaPaC6OeR4cznyUr/fjCr7RdGmRvgbPHfKgIDgD+isO4ffDeJ6aTtn 0Tf8X7/JK07wPYt6Tzpf47viTWkPqCs= Received: from mail-qt1-f200.google.com (mail-qt1-f200.google.com [209.85.160.200]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-253-AQm0WAoXM864bmyG2xCcbg-1; Wed, 03 Jul 2024 17:29:40 -0400 X-MC-Unique: AQm0WAoXM864bmyG2xCcbg-1 Received: by mail-qt1-f200.google.com with SMTP id d75a77b69052e-4464454e329so1958251cf.1 for ; Wed, 03 Jul 2024 14:29:40 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1720042180; x=1720646980; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=j2Zxgw15onbd0eMS/03kg+dHZsOcAz6IsQR1l1z1OuE=; b=Vk2AwMRxiM2sMq0NcJvFuXxYPS/IGojwsGTQug37t2vF0+VN1xNEj+V2wfTWB44e5K rMA2QWZkBl71q+RWcbfUP2tBo6/ZLko3hE6t3s1avVbuZs9PDpZndoBs/hKcgwM+gDUQ WW1SP42p2BY/jY7/Iy77STdT2w1iYHcyWvhwzdQ0fdWIKlyrxuTXfVayy6vm8kG+0KGN NkZKfyVHmb7ElQ+p9nrwCX+ZCWh2QTiYVZrIokyblsuDEWxatI1PTPbRs7w8SjDprKhd FNYanR/zHnI4BEKMQ4LDp/117mbBECTAtG64i5iMkC2TDHbArGkRw2FVxURLB9VakOe7 Ottg== X-Forwarded-Encrypted: i=1; AJvYcCVK/f6UfnBQnBPNQdnhIucFJpOSbB0VJdDn4ieY6gxku7+f+ui/kKER9Nrd7kxwKVYom+OFqrgd9cpLI/9Vpqfhr4I= X-Gm-Message-State: AOJu0Ywo4wyjKqZOIcYYzvm99qwP1WaTnPH3ztDAIuv+mduDcBEtNQih W3YSSXCUi+F6jSmDUrzK4fDajL24eFWR2xSv7vEps4nAwYTI0KERhjNrz9CluEqcdIJW1kX9hDA m58fmPnuhfn8atbbu4ZJbUQssoFpBMZ+0htR8IpIbFNB/1r/v X-Received: by 2002:a05:622a:8f:b0:446:3c97:d3ab with SMTP id d75a77b69052e-44662eb7436mr151118481cf.4.1720042179676; Wed, 03 Jul 2024 14:29:39 -0700 (PDT) X-Google-Smtp-Source: AGHT+IG9nYtpxfPIDPA/kSFmDjfHMlL7UyJZQtNoCKoRdFeJRABCZlINs1O4dDPbOXn5gaxSQwwtsA== X-Received: by 2002:a05:622a:8f:b0:446:3c97:d3ab with SMTP id d75a77b69052e-44662eb7436mr151118391cf.4.1720042179335; Wed, 03 Jul 2024 14:29:39 -0700 (PDT) Received: from x1n.redhat.com (pool-99-254-121-117.cpe.net.cable.rogers.com. [99.254.121.117]) by smtp.gmail.com with ESMTPSA id d75a77b69052e-4465143eb1csm54337481cf.57.2024.07.03.14.29.37 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 03 Jul 2024 14:29:39 -0700 (PDT) From: Peter Xu To: linux-kernel@vger.kernel.org, linux-mm@kvack.org Cc: Matthew Wilcox , Mel Gorman , Dave Jiang , linuxppc-dev@lists.ozlabs.org, Michael Ellerman , Rik van Riel , Vlastimil Babka , Nicholas Piggin , Christophe Leroy , Andrew Morton , Huang Ying , Oscar Salvador , "Aneesh Kumar K . V" , Thomas Gleixner , Dave Hansen , x86@kernel.org, Ingo Molnar , "Kirill A . Shutemov" , Dan Williams , Borislav Petkov , peterx@redhat.com, Hugh Dickins , Rick P Edgecombe Subject: [PATCH v2 8/8] mm/mprotect: fix dax pud handlings Date: Wed, 3 Jul 2024 17:29:18 -0400 Message-ID: <20240703212918.2417843-9-peterx@redhat.com> X-Mailer: git-send-email 2.45.0 In-Reply-To: <20240703212918.2417843-1-peterx@redhat.com> References: <20240703212918.2417843-1-peterx@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Rspamd-Server: rspam11 X-Rspamd-Queue-Id: 3F14B4000F X-Stat-Signature: 6r8dsr1c59bqu6foot11ia4djt6x6x96 X-Rspam-User: X-HE-Tag: 1720042182-809562 X-HE-Meta: U2FsdGVkX1+fqVPzSPqc4xUg+Iz1nVlkD7+A7rwElEoY275v+Y8hFFDRF4ut7VpTX5oiv4ynmDgDsxlliYVPY97io/GUiYUcD/RMafSyP1ELa6SYCzbH+RaVJArEtxMAIV6W1FNJJhnpidEB9SNMS6shUp6V4pOV47sV9hhCAPEwlM4gy1DbHiLtvf8msReMnH0JP167ZCAHsajXpmxqZtCYGY1CZYigDvhGHuSX4bfovQX3eVTy8O1K5x0THlQj9dDyfQ3yowBaZVOewpc8AnbF7imFjp7RJybb+6rSdSrVWBasW6OYed62G2iiJLROZ0NpuvWJop/QTJOmHp9SgLfxnyYjq2/ODSj1FRwl8ZEnAOwQ0vKOh0IRU85kiL7Aya1tiI/pyO9Q4NZHOkX3k3ckl5WlYHm95QU6WNcGd4DqF4/ENrZAlhGwfkBbvRd3ocJkxDPi9uEB/Lk+Het8ZRxoYuT23XJ+tbSDZnDcP+ej571NVA0rOtcpwet7r3iGV27cwQuX8oDaWt+pJTh+fwkK0G73oYBlav/JWTn2Y2Rg5DHF/SMDW0hUzonTtL9+qKGNYxh4uaG6aF+GC7/RNmoffGyDkc2fCjAQyKGlSdeoAh6fhIxHu5MCSE9nGEv/SIKuEOuAb+6H15grPuCGKMmvgCeSoBkpD1gI4bwLc2cXsUDnoiUxJtJjLzR3pI17DzDsX6DYCidiZwC75B/f31HBPGT18MguHsQkBpFwKZyAa/0YMS8fpvNs/fbyh3+DVPWdziegOBmSNxVmXMOiXf2fUtDyqDhDuAdGgNsQErEPvUbdIDSL4p3mAiNIu88u+LCZaCRGMK9k2/sJ7o45Xqa8NpxjZUffeM/0ObIvcgGbIghj4zGc+B1Jcc9zRQWF2vvnQ2cL7mdpJapHZAzDj08iYxCpNxLGz55ORUxWrRZG0ch/QaqzSPb0B1j0jeEi+RC+Mgjvu+adPS190Qz zQkUZKFn 030pYrLIcaVSvvKMggJV4hi3Ux9cHNljO2RTBgus7JRw1Lxbzdxi0jo1b02A/t3nFyJpqSppaZkbVxMXcm+hvwRTyWh+HpsO3u0OrjRfGuLuXnNQN8Uo6SXGKeBAmX4I2W6vFtXM1TWYrX/pBry9bQC3Mhcbo7RoXnMFqiZ50J8zh850JHLyZJWcLBc3iwz9ggZ6cgFGcUu4oTGqLnC+wkyQgvtVbh5l2piRQwl2bfyzjT2VLxOtrIqhduQOlZULUIX6xMeeeEkVF+B7l2qWVcg4v5jb4FrLHYpp7xJ1y97LC69MyKtJz9HMMNB6cSNnfVxtUpsvfqCZ2rFmj/hmP+Xwyl8gYSqGbFKcR9T+Ng/sp5kTEPyE+t1UwuWkN2zc6Ktqw9pSZO7i6ZTx/BX6zD7I+zTpzpNRK69H+xXI0k7MlIc6CGEOi/CkdzQ03+Y/0tFqojmCxsKZpjjUW0pd9ltnJdkVnpI63XqnM9/FSHJTVoszVWm9l9dXEuKeSP7S+c4pfSnjbjoJJdQBgDBEGGJHaluYU8bRZIjiE20T9iwY5D15G0dI9UDV8S1th/GtHxi0Z28K86CY/Wo4= 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: List-Subscribe: List-Unsubscribe: This is only relevant to the two archs that support PUD dax, aka, x86_64 and ppc64. PUD THPs do not yet exist elsewhere, and hugetlb PUDs do not count in this case. DAX have had PUD mappings for years, but change protection path never worked. When the path is triggered in any form (a simple test program would be: call mprotect() on a 1G dev_dax mapping), the kernel will report "bad pud". This patch should fix that. The new change_huge_pud() tries to keep everything simple. For example, it doesn't optimize write bit as that will need even more PUD helpers. It's not too bad anyway to have one more write fault in the worst case once for 1G range; may be a bigger thing for each PAGE_SIZE, though. Neither does it support userfault-wp bits, as there isn't such PUD mappings that is supported; file mappings always need a split there. The same to TLB shootdown: the pmd path (which was for x86 only) has the trick of using _ad() version of pmdp_invalidate*() which can avoid one redundant TLB, but let's also leave that for later. Again, the larger the mapping, the smaller of such effect. Another thing worth mention is this path needs to be careful on handling "retry" event for change_huge_pud() (where it can return 0): it isn't like change_huge_pmd(), as the pmd version is safe with all conditions handled in change_pte_range() later, thanks to Hugh's new pte_offset_map_lock(). In short, change_pte_range() is simply smarter than change_pmd_range() now after the shmem thp collapse rework. For that reason, change_pud_range() will need proper retry if it races with something else when a huge PUD changed from under us. Cc: Dan Williams Cc: Matthew Wilcox Cc: Dave Jiang Cc: Hugh Dickins Cc: Kirill A. Shutemov Cc: Vlastimil Babka Cc: Thomas Gleixner Cc: Ingo Molnar Cc: Borislav Petkov Cc: Dave Hansen Cc: Michael Ellerman Cc: Aneesh Kumar K.V Cc: Oscar Salvador Cc: x86@kernel.org Cc: linuxppc-dev@lists.ozlabs.org Fixes: a00cc7d9dd93 ("mm, x86: add support for PUD-sized transparent hugepages") Fixes: 27af67f35631 ("powerpc/book3s64/mm: enable transparent pud hugepage") Signed-off-by: Peter Xu --- include/linux/huge_mm.h | 24 +++++++++++++++++++ mm/huge_memory.c | 52 +++++++++++++++++++++++++++++++++++++++++ mm/mprotect.c | 40 ++++++++++++++++++++++++------- 3 files changed, 108 insertions(+), 8 deletions(-) diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h index cee3c5da8f0e..2ebebadfbe47 100644 --- a/include/linux/huge_mm.h +++ b/include/linux/huge_mm.h @@ -348,6 +348,17 @@ void split_huge_pmd_address(struct vm_area_struct *vma, unsigned long address, void __split_huge_pud(struct vm_area_struct *vma, pud_t *pud, unsigned long address); +#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD +int change_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma, + pud_t *pudp, unsigned long addr, pgprot_t newprot, + unsigned long cp_flags); +#else +static inline int +change_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma, + pud_t *pudp, unsigned long addr, pgprot_t newprot, + unsigned long cp_flags) { return 0; } +#endif + #define split_huge_pud(__vma, __pud, __address) \ do { \ pud_t *____pud = (__pud); \ @@ -591,6 +602,19 @@ static inline int next_order(unsigned long *orders, int prev) { return 0; } + +static inline void __split_huge_pud(struct vm_area_struct *vma, pud_t *pud, + unsigned long address) +{ +} + +static inline int change_huge_pud(struct mmu_gather *tlb, + struct vm_area_struct *vma, pud_t *pudp, + unsigned long addr, pgprot_t newprot, + unsigned long cp_flags) +{ + return 0; +} #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ static inline int split_folio_to_list_to_order(struct folio *folio, diff --git a/mm/huge_memory.c b/mm/huge_memory.c index 017377920d18..4998452f7c49 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -2099,6 +2099,53 @@ int change_huge_pmd(struct mmu_gather *tlb, struct vm_area_struct *vma, return ret; } +/* + * Returns: + * + * - 0: if pud leaf changed from under us + * - 1: if pud can be skipped + * - HPAGE_PUD_NR: if pud was successfully processed + */ +#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD +int change_huge_pud(struct mmu_gather *tlb, struct vm_area_struct *vma, + pud_t *pudp, unsigned long addr, pgprot_t newprot, + unsigned long cp_flags) +{ + struct mm_struct *mm = vma->vm_mm; + pud_t oldpud, entry; + spinlock_t *ptl; + + tlb_change_page_size(tlb, HPAGE_PUD_SIZE); + + /* NUMA balancing doesn't apply to dax */ + if (cp_flags & MM_CP_PROT_NUMA) + return 1; + + /* + * Huge entries on userfault-wp only works with anonymous, while we + * don't have anonymous PUDs yet. + */ + if (WARN_ON_ONCE(cp_flags & MM_CP_UFFD_WP_ALL)) + return 1; + + ptl = __pud_trans_huge_lock(pudp, vma); + if (!ptl) + return 0; + + /* + * Can't clear PUD or it can race with concurrent zapping. See + * change_huge_pmd(). + */ + oldpud = pudp_invalidate(vma, addr, pudp); + entry = pud_modify(oldpud, newprot); + set_pud_at(mm, addr, pudp, entry); + tlb_flush_pud_range(tlb, addr, HPAGE_PUD_SIZE); + + spin_unlock(ptl); + return HPAGE_PUD_NR; +} +#endif + #ifdef CONFIG_USERFAULTFD /* * The PT lock for src_pmd and dst_vma/src_vma (for reading) are locked by @@ -2329,6 +2376,11 @@ void __split_huge_pud(struct vm_area_struct *vma, pud_t *pud, spin_unlock(ptl); mmu_notifier_invalidate_range_end(&range); } +#else +void __split_huge_pud(struct vm_area_struct *vma, pud_t *pud, + unsigned long address) +{ +} #endif /* CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD */ static void __split_huge_zero_page_pmd(struct vm_area_struct *vma, diff --git a/mm/mprotect.c b/mm/mprotect.c index fb8bf3ff7cd9..694f13b83864 100644 --- a/mm/mprotect.c +++ b/mm/mprotect.c @@ -425,29 +425,53 @@ static inline long change_pud_range(struct mmu_gather *tlb, unsigned long end, pgprot_t newprot, unsigned long cp_flags) { struct mmu_notifier_range range; - pud_t *pud; + pud_t *pudp, pud; unsigned long next; long pages = 0, ret; range.start = 0; - pud = pud_offset(p4d, addr); + pudp = pud_offset(p4d, addr); do { +again: next = pud_addr_end(addr, end); - ret = change_prepare(vma, pud, pmd, addr, cp_flags); - if (ret) - return ret; - if (pud_none_or_clear_bad(pud)) + ret = change_prepare(vma, pudp, pmd, addr, cp_flags); + if (ret) { + pages = ret; + break; + } + + pud = READ_ONCE(*pudp); + if (pud_none(pud)) continue; + if (!range.start) { mmu_notifier_range_init(&range, MMU_NOTIFY_PROTECTION_VMA, 0, vma->vm_mm, addr, end); mmu_notifier_invalidate_range_start(&range); } - pages += change_pmd_range(tlb, vma, pud, addr, next, newprot, + + if (pud_leaf(pud)) { + if ((next - addr != PUD_SIZE) || + pgtable_split_needed(vma, cp_flags)) { + __split_huge_pud(vma, pudp, addr); + goto again; + } else { + ret = change_huge_pud(tlb, vma, pudp, + addr, newprot, cp_flags); + if (ret == 0) + goto again; + /* huge pud was handled */ + if (ret == HPAGE_PUD_NR) + pages += HPAGE_PUD_NR; + continue; + } + } + + pages += change_pmd_range(tlb, vma, pudp, addr, next, newprot, cp_flags); - } while (pud++, addr = next, addr != end); + } while (pudp++, addr = next, addr != end); if (range.start) mmu_notifier_invalidate_range_end(&range);