From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 27FC22E62B7 for ; Tue, 15 Jul 2025 13:24:13 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=170.10.129.124 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752585855; cv=none; b=BdZ8qraSk4wrTODvKO0scDkxCAOPL26HpxhpyIgSwj72reNQqREYsYL6Yyne7P776McGtR/zXQa/zO2ZmhqV1lfjXglakX7fVzJrJvj8Wp8tcYAimZo4V0WPC3IRDNSX5UC4THRysv7mepjFbFq7HAFlysyBp74Y6YZw0Imr6I4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1752585855; c=relaxed/simple; bh=a9OBY9leQX0eGtrRKrr8AgQOeHXQGP3xXcTwIxxSZ/4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=mSluH8Hn2nMHYuFvAYqgmVxuPZKu6sdU32HfdbXQmH9zJMLv1n16ub7wfvI86ipU8j5nCQcVn7ZFNil3O36rONSE2cDd96z5BsYeyVgRylIThiv3HYZQhzUeE6oe5tr8c2gbuqLFFLRZTSWe2B4SXeQJpvJ3tE9VI2f/HHsede4= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com; spf=pass smtp.mailfrom=redhat.com; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b=Msw2epcR; arc=none smtp.client-ip=170.10.129.124 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=redhat.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=redhat.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=redhat.com header.i=@redhat.com header.b="Msw2epcR" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1752585852; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=cI2lHUCMuK2zQhlnl2y4PjQd6rkotpnK5tiH1r4owRs=; b=Msw2epcRQaluUI+qDzFfEXDcphCGGoAvlLryIXMnyMnnDTN2+hdVpCdhCy8R+9n5lpuEFF /cL8ag4Ehxq4+nELpLmPLkJhWGAEFsP4Ghjhn4Z+4cJutcy0XBpGh1DgbLsIlMR6A7AfYD iP4xcLpFJehgcq49mY94aqojQuVp2Uw= Received: from mail-wm1-f72.google.com (mail-wm1-f72.google.com [209.85.128.72]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-675-UnKTvLgGNPSRXCs79kf5kQ-1; Tue, 15 Jul 2025 09:24:11 -0400 X-MC-Unique: UnKTvLgGNPSRXCs79kf5kQ-1 X-Mimecast-MFC-AGG-ID: UnKTvLgGNPSRXCs79kf5kQ_1752585850 Received: by mail-wm1-f72.google.com with SMTP id 5b1f17b1804b1-4561bc2f477so13652125e9.0 for ; Tue, 15 Jul 2025 06:24:10 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1752585850; x=1753190650; 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=cI2lHUCMuK2zQhlnl2y4PjQd6rkotpnK5tiH1r4owRs=; b=a2Xr7x+3vtQY/MBdBp7k2NC3T9A9Fo2PiiCwmNOaXvn1r+TaAd2rVXAN96i0GRCuuY +zJRRAwMgkGxR6ZpWVq0swuWbA76pDrvvtx5APGOdC6AoysOO93xi4f/IQO069SH5AHV ERgmfO2Re8h6tpMFXHBf1Yg+PGrjrsZPoTbxWcbqS3tAoRqmXPLYtVa5gdA/Vit7LphI VOKnAJnKFnbrjg7DfCHugHjs0GU4ljLhTWuTzRwDgcg3jF8W4BDMAZUBEIXs4+4daVpS QZsvIY3kXNojB/q1y38ATjoyRdCUopXIuT64oHby8pW4VzzfXwS51u89Z9mUcwqw8g1k p86w== X-Forwarded-Encrypted: i=1; AJvYcCUH0b9iJSZgykVanyyiBMjpvSq4R6MxOhm32omlEfZdicxN8CTIh54jOZKi3RtRDW5K7RJRH7v+T9sfF96a@vger.kernel.org X-Gm-Message-State: AOJu0YwAiq3QjJp0BjwuOmrkfSPQQ4++/W/G48SPMXnWWCXVaKfOp/9M 7IslT2higUFfjGXLYPCm/2V5WGel2tbzFa9uLeKzwZnvlmxVEAuH9LjgFSYfkKeOnHSpqZ6XVJ0 ew4S1GDG2X/25fQjAOI/DMhsOPE7zrzTR8ScYMeF9ZGxGILk/4OmziDQS49+CJFC+b+s= X-Gm-Gg: ASbGncsdoRQNkDfsbyIVhTE3mrAnYREDCahDNEqfl1hTnbsKxfsuLP2BLqyN3vcKrJR se9ISX3LrwAHItEIAoIvQtMHJP4O71zMv68h1l0KB8Ob3fTBAINe8xPQiKPoVm8Ewd0fT+pFR0T xFba2+h2kUDGgo0U0Ok5cIm0WnVqOU2F4N5GjCqDqqlXugwtpgxBo7wcnxRVtR/wIgE2JD+SzOk gn1G+YqveZeipyWSW3ozjw9BXlbZs7fLf1xakmNGf6C0ffRFcH7/aC+84Zw287U4mHT+M9cy7oc o2UhFUYaGGnbDKC6FyClypZe0aUAzYvOqngJ4IiBamoYKsadttntszmmvaLn/3enOuFWAGWc8cL 6Ub0ydGn+IKN2JOQ5RIQ2cSDu X-Received: by 2002:a05:600c:3592:b0:456:173c:8a53 with SMTP id 5b1f17b1804b1-456173c8b27mr94728715e9.2.1752585849635; Tue, 15 Jul 2025 06:24:09 -0700 (PDT) X-Google-Smtp-Source: AGHT+IGkPjEhwUD11Kc7R628CsdkyUBojyPzeegGbQKL/YV/Ocaib7+IW0nyg3EFT/AEMoIuz4CMUw== X-Received: by 2002:a05:600c:3592:b0:456:173c:8a53 with SMTP id 5b1f17b1804b1-456173c8b27mr94728115e9.2.1752585848983; Tue, 15 Jul 2025 06:24:08 -0700 (PDT) Received: from localhost (p200300d82f2849002c244e201f219fbd.dip0.t-ipconnect.de. [2003:d8:2f28:4900:2c24:4e20:1f21:9fbd]) by smtp.gmail.com with UTF8SMTPSA id ffacd0b85a97d-3b5e8e2710bsm15102268f8f.99.2025.07.15.06.24.07 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Tue, 15 Jul 2025 06:24:08 -0700 (PDT) From: David Hildenbrand To: linux-kernel@vger.kernel.org Cc: linux-mm@kvack.org, xen-devel@lists.xenproject.org, linux-fsdevel@vger.kernel.org, nvdimm@lists.linux.dev, David Hildenbrand , Andrew Morton , Juergen Gross , Stefano Stabellini , Oleksandr Tyshchenko , Dan Williams , Matthew Wilcox , Jan Kara , Alexander Viro , Christian Brauner , Lorenzo Stoakes , "Liam R. Howlett" , Vlastimil Babka , Mike Rapoport , Suren Baghdasaryan , Michal Hocko , Zi Yan , Baolin Wang , Nico Pache , Ryan Roberts , Dev Jain , Barry Song , Jann Horn , Pedro Falcato , Hugh Dickins , Oscar Salvador , Lance Yang Subject: [PATCH v1 7/9] mm/memory: factor out common code from vm_normal_page_*() Date: Tue, 15 Jul 2025 15:23:48 +0200 Message-ID: <20250715132350.2448901-8-david@redhat.com> X-Mailer: git-send-email 2.50.1 In-Reply-To: <20250715132350.2448901-1-david@redhat.com> References: <20250715132350.2448901-1-david@redhat.com> Precedence: bulk X-Mailing-List: linux-fsdevel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Let's reduce the code duplication and factor out the non-pte/pmd related magic into vm_normal_page_pfn(). To keep it simpler, check the pfn against both zero folios. We could optimize this, but as it's only for the !CONFIG_ARCH_HAS_PTE_SPECIAL case, it's not a compelling micro-optimization. With CONFIG_ARCH_HAS_PTE_SPECIAL we don't have to check anything else, really. It's a good question if we can even hit the !CONFIG_ARCH_HAS_PTE_SPECIAL scenario in the PMD case in practice: but doesn't really matter, as it's now all unified in vm_normal_page_pfn(). Add kerneldoc for all involved functions. No functional change intended. Signed-off-by: David Hildenbrand --- mm/memory.c | 183 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 109 insertions(+), 74 deletions(-) diff --git a/mm/memory.c b/mm/memory.c index 00ee0df020503..d5f80419989b9 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -596,8 +596,13 @@ static void print_bad_page_map(struct vm_area_struct *vma, add_taint(TAINT_BAD_PAGE, LOCKDEP_NOW_UNRELIABLE); } -/* - * vm_normal_page -- This function gets the "struct page" associated with a pte. +/** + * vm_normal_page_pfn() - Get the "struct page" associated with a PFN in a + * non-special page table entry. + * @vma: The VMA mapping the @pfn. + * @addr: The address where the @pfn is mapped. + * @pfn: The PFN. + * @entry: The page table entry value for error reporting purposes. * * "Special" mappings do not wish to be associated with a "struct page" (either * it doesn't exist, or it exists but they don't want to touch it). In this @@ -609,10 +614,10 @@ static void print_bad_page_map(struct vm_area_struct *vma, * (such as GUP) can still identify these mappings and work with the * underlying "struct page". * - * There are 2 broad cases. Firstly, an architecture may define a pte_special() - * pte bit, in which case this function is trivial. Secondly, an architecture - * may not have a spare pte bit, which requires a more complicated scheme, - * described below. + * There are 2 broad cases. Firstly, an architecture may define a "special" + * page table entry bit (e.g., pte_special()), in which case this function is + * trivial. Secondly, an architecture may not have a spare page table + * entry bit, which requires a more complicated scheme, described below. * * A raw VM_PFNMAP mapping (ie. one that is not COWed) is always considered a * special mapping (even if there are underlying and valid "struct pages"). @@ -645,15 +650,72 @@ static void print_bad_page_map(struct vm_area_struct *vma, * don't have to follow the strict linearity rule of PFNMAP mappings in * order to support COWable mappings. * + * This function is not expected to be called for obviously special mappings: + * when the page table entry has the "special" bit set. + * + * Return: Returns the "struct page" if this is a "normal" mapping. Returns + * NULL if this is a "special" mapping. + */ +static inline struct page *vm_normal_page_pfn(struct vm_area_struct *vma, + unsigned long addr, unsigned long pfn, unsigned long long entry) +{ + /* + * With CONFIG_ARCH_HAS_PTE_SPECIAL, any special page table mappings + * (incl. shared zero folios) are marked accordingly and are handled + * by the caller. + */ + if (!IS_ENABLED(CONFIG_ARCH_HAS_PTE_SPECIAL)) { + if (unlikely(vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP))) { + if (vma->vm_flags & VM_MIXEDMAP) { + /* If it has a "struct page", it's "normal". */ + if (!pfn_valid(pfn)) + return NULL; + } else { + unsigned long off = (addr - vma->vm_start) >> PAGE_SHIFT; + + /* Only CoW'ed anon folios are "normal". */ + if (pfn == vma->vm_pgoff + off) + return NULL; + if (!is_cow_mapping(vma->vm_flags)) + return NULL; + } + } + + if (is_zero_pfn(pfn) || is_huge_zero_pfn(pfn)) + return NULL; + } + + /* Cheap check for corrupted page table entries. */ + if (pfn > highest_memmap_pfn) { + print_bad_page_map(vma, addr, entry, NULL); + return NULL; + } + /* + * NOTE! We still have PageReserved() pages in the page tables. + * For example, VDSO mappings can cause them to exist. + */ + VM_WARN_ON_ONCE(is_zero_pfn(pfn) || is_huge_zero_pfn(pfn)); + return pfn_to_page(pfn); +} + +/** + * vm_normal_page() - Get the "struct page" associated with a PTE + * @vma: The VMA mapping the @pte. + * @addr: The address where the @pte is mapped. + * @pte: The PTE. + * + * Get the "struct page" associated with a PTE. See vm_normal_page_pfn() + * for details. + * + * Return: Returns the "struct page" if this is a "normal" mapping. Returns + * NULL if this is a "special" mapping. */ struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, pte_t pte) { unsigned long pfn = pte_pfn(pte); - if (IS_ENABLED(CONFIG_ARCH_HAS_PTE_SPECIAL)) { - if (likely(!pte_special(pte))) - goto check_pfn; + if (unlikely(pte_special(pte))) { if (vma->vm_ops && vma->vm_ops->find_special_page) return vma->vm_ops->find_special_page(vma, addr); if (vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP)) @@ -664,44 +726,21 @@ struct page *vm_normal_page(struct vm_area_struct *vma, unsigned long addr, print_bad_page_map(vma, addr, pte_val(pte), NULL); return NULL; } - - /* !CONFIG_ARCH_HAS_PTE_SPECIAL case follows: */ - - if (unlikely(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP))) { - if (vma->vm_flags & VM_MIXEDMAP) { - if (!pfn_valid(pfn)) - return NULL; - if (is_zero_pfn(pfn)) - return NULL; - goto out; - } else { - unsigned long off; - off = (addr - vma->vm_start) >> PAGE_SHIFT; - if (pfn == vma->vm_pgoff + off) - return NULL; - if (!is_cow_mapping(vma->vm_flags)) - return NULL; - } - } - - if (is_zero_pfn(pfn)) - return NULL; - -check_pfn: - if (unlikely(pfn > highest_memmap_pfn)) { - print_bad_page_map(vma, addr, pte_val(pte), NULL); - return NULL; - } - - /* - * NOTE! We still have PageReserved() pages in the page tables. - * eg. VDSO mappings can cause them to exist. - */ -out: - VM_WARN_ON_ONCE(is_zero_pfn(pfn)); - return pfn_to_page(pfn); + return vm_normal_page_pfn(vma, addr, pfn, pte_val(pte)); } +/** + * vm_normal_folio() - Get the "struct folio" associated with a PTE + * @vma: The VMA mapping the @pte. + * @addr: The address where the @pte is mapped. + * @pte: The PTE. + * + * Get the "struct folio" associated with a PTE. See vm_normal_page_pfn() + * for details. + * + * Return: Returns the "struct folio" if this is a "normal" mapping. Returns + * NULL if this is a "special" mapping. + */ struct folio *vm_normal_folio(struct vm_area_struct *vma, unsigned long addr, pte_t pte) { @@ -713,6 +752,18 @@ struct folio *vm_normal_folio(struct vm_area_struct *vma, unsigned long addr, } #ifdef CONFIG_PGTABLE_HAS_HUGE_LEAVES +/** + * vm_normal_page_pmd() - Get the "struct page" associated with a PMD + * @vma: The VMA mapping the @pmd. + * @addr: The address where the @pmd is mapped. + * @pmd: The PMD. + * + * Get the "struct page" associated with a PMD. See vm_normal_page_pfn() + * for details. + * + * Return: Returns the "struct page" if this is a "normal" mapping. Returns + * NULL if this is a "special" mapping. + */ struct page *vm_normal_page_pmd(struct vm_area_struct *vma, unsigned long addr, pmd_t pmd) { @@ -727,37 +778,21 @@ struct page *vm_normal_page_pmd(struct vm_area_struct *vma, unsigned long addr, print_bad_page_map(vma, addr, pmd_val(pmd), NULL); return NULL; } - - if (unlikely(vma->vm_flags & (VM_PFNMAP|VM_MIXEDMAP))) { - if (vma->vm_flags & VM_MIXEDMAP) { - if (!pfn_valid(pfn)) - return NULL; - goto out; - } else { - unsigned long off; - off = (addr - vma->vm_start) >> PAGE_SHIFT; - if (pfn == vma->vm_pgoff + off) - return NULL; - if (!is_cow_mapping(vma->vm_flags)) - return NULL; - } - } - - if (is_huge_zero_pfn(pfn)) - return NULL; - if (unlikely(pfn > highest_memmap_pfn)) { - print_bad_page_map(vma, addr, pmd_val(pmd), NULL); - return NULL; - } - - /* - * NOTE! We still have PageReserved() pages in the page tables. - * eg. VDSO mappings can cause them to exist. - */ -out: - return pfn_to_page(pfn); + return vm_normal_page_pfn(vma, addr, pfn, pmd_val(pmd)); } +/** + * vm_normal_folio_pmd() - Get the "struct folio" associated with a PMD + * @vma: The VMA mapping the @pmd. + * @addr: The address where the @pmd is mapped. + * @pmd: The PMD. + * + * Get the "struct folio" associated with a PMD. See vm_normal_page_pfn() + * for details. + * + * Return: Returns the "struct folio" if this is a "normal" mapping. Returns + * NULL if this is a "special" mapping. + */ struct folio *vm_normal_folio_pmd(struct vm_area_struct *vma, unsigned long addr, pmd_t pmd) { -- 2.50.1