linux-mm.kvack.org archive mirror
 help / color / mirror / Atom feed
From: Brendan Jackman <jackmanb@google.com>
To: Thomas Gleixner <tglx@linutronix.de>,
	Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	 Dave Hansen <dave.hansen@linux.intel.com>,
	x86@kernel.org,  Andrew Morton <akpm@linux-foundation.org>,
	David Rientjes <rientjes@google.com>,
	 Vlastimil Babka <vbabka@suse.cz>,
	David Hildenbrand <david@redhat.com>
Cc: linux-kernel@vger.kernel.org, linux-mm@kvack.org,
	 Mike Rapoport <rppt@kernel.org>,
	Junaid Shahid <junaids@google.com>,
	Reiji Watanabe <reijiw@google.com>,
	 Patrick Bellasi <derkling@google.com>,
	Brendan Jackman <jackmanb@google.com>,
	 Yosry Ahmed <yosry.ahmed@linux.dev>
Subject: [PATCH RFC HACKS 05/11] Add asi_map() and asi_unmap()
Date: Thu, 13 Mar 2025 18:11:24 +0000	[thread overview]
Message-ID: <20250313-asi-page-alloc-v1-5-04972e046cea@google.com> (raw)
In-Reply-To: <20250313-asi-page-alloc-v1-0-04972e046cea@google.com>

Do not worry too much about the implementation of this. I am trying to
implement this more neatly using the x86 PAT logic but haven't managed to
get it working in time for the RFC. To enable testing & review, I'm very
hastily throwing something together that basically works, based on a
simplified version of what was used for the latest RFC [0].

[0] https://lore.kernel.org/linux-mm/20250110-asi-rfc-v2-v2-0-8419288bc805@google.com/

Signed-off-by: Brendan Jackman <jackmanb@google.com>
---
 arch/x86/include/asm/asi.h |  3 ++
 arch/x86/mm/asi.c          | 77 ++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/asi.h        |  2 ++
 include/linux/vmalloc.h    |  4 +++
 mm/vmalloc.c               | 32 +++++++++++--------
 5 files changed, 105 insertions(+), 13 deletions(-)

diff --git a/arch/x86/include/asm/asi.h b/arch/x86/include/asm/asi.h
index b8f604df6a36508acbc10710f821d5f95e8cdceb..cf8be544de8b108190b765e3eb337089866207a2 100644
--- a/arch/x86/include/asm/asi.h
+++ b/arch/x86/include/asm/asi.h
@@ -23,6 +23,9 @@ static __always_inline pgd_t *asi_pgd(struct asi *asi)
 	return asi ? asi->pgd : NULL;
 }
 
+void asi_map(struct page *page, int numpages);
+void asi_unmap(struct page *page, int numpages);
+
 #endif /* CONFIG_MITIGATION_ADDRESS_SPACE_ISOLATION */
 
 #endif /* _ASM_X86_ASI_H */
diff --git a/arch/x86/mm/asi.c b/arch/x86/mm/asi.c
index e5a981a7b3192655cd981633514fbf945b92c9b6..570233224789631352891f47ac2f0453a7adc06e 100644
--- a/arch/x86/mm/asi.c
+++ b/arch/x86/mm/asi.c
@@ -1,8 +1,85 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <linux/bug.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <linux/mm_types.h>
+#include <linux/pgtable.h>
+#include <linux/set_memory.h>
+#include <linux/vmalloc.h>
+
 #include <asm/asi.h>
+#include <asm/traps.h>
 
 static __aligned(PAGE_SIZE) pgd_t asi_global_nonsensitive_pgd[PTRS_PER_PGD];
 
 struct asi __asi_global_nonsensitive = {
 	.pgd = asi_global_nonsensitive_pgd,
 };
+
+/*
+ * Map the given pages into the ASI nonsensitive physmap. The source of the
+ * mapping is the regular unrestricted page tables. Only supports mapping at
+ * pageblock granularity. Does no synchronization.
+ */
+void asi_map(struct page *page, int numpages)
+{
+	unsigned long virt;
+	unsigned long start = (size_t)(page_to_virt(page));
+	unsigned long end = start + PAGE_SIZE * numpages;
+	unsigned long page_size;
+
+	VM_BUG_ON(!IS_ALIGNED(page_to_pfn(page), pageblock_nr_pages));
+	VM_BUG_ON(!IS_ALIGNED(numpages, pageblock_nr_pages));
+
+	for (virt = start; virt < end; virt = ALIGN(virt + 1, page_size)) {
+		pte_t *pte, *pte_asi;
+		int level, level_asi;
+		pgd_t *pgd = pgd_offset_pgd(asi_global_nonsensitive_pgd, virt);
+
+		pte_asi = lookup_pgtable_in_pgd(pgd, virt, &level_asi);
+		page_size = page_level_size(level_asi);
+
+		pte = lookup_address(virt, &level);
+		if (!pte || pte_none(*pte))
+			continue;
+
+		/*
+		 * Physmap should already be setup by PAT code, with no pages
+		 * smaller than 2M. This function should only be called at
+		 * pageblock granularity. Thus it should never be required to
+		 * break up pages here.
+		 */
+		if (WARN_ON_ONCE(!pte_asi) ||
+		    WARN_ON_ONCE(ALIGN_DOWN(virt, page_size) < virt) ||
+				 ALIGN(virt, page_size) > end)
+			continue;
+
+		/*
+		 * Existing mappings should already match the structure of the
+		 * unrestricted physmap.
+		 */
+		if (WARN_ON_ONCE(level != level_asi))
+			continue;
+
+		set_pte(pte_asi, *pte);
+	}
+}
+
+/*
+ * Unmap pages previously mapped via asi_map().
+ *
+ * Interrupts must be enabled as this does a TLB shootdown.
+ */
+void asi_unmap(struct page *page, int numpages)
+{
+	size_t start = (size_t)page_to_virt(page);
+	size_t end = start + (PAGE_SIZE * numpages);
+	pgtbl_mod_mask mask = 0;
+
+	VM_BUG_ON(!IS_ALIGNED(page_to_pfn(page), pageblock_nr_pages));
+	VM_BUG_ON(!IS_ALIGNED(numpages, pageblock_nr_pages));
+
+	vunmap_pgd_range(asi_pgd(ASI_GLOBAL_NONSENSITIVE), start, end, &mask);
+
+	flush_tlb_kernel_range(start, end - 1);
+}
diff --git a/include/linux/asi.h b/include/linux/asi.h
index 2d3049d5fe423e139dcce8f3d68cdffcc0ec0bfe..ee9811f04a417556cf2e930644eaf05f3c9bfee3 100644
--- a/include/linux/asi.h
+++ b/include/linux/asi.h
@@ -13,6 +13,8 @@
 struct asi {};
 
 static inline pgd_t *asi_pgd(struct asi *asi) { return NULL; }
+static inline void asi_map(struct page *page, int numpages) { }
+static inline void asi_unmap(struct page *page, int numpages) { }
 
 #endif /* CONFIG_MITIGATION_ADDRESS_SPACE_ISOLATION */
 #endif /* _INCLUDE_ASI_H */
diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 31e9ffd936e39334ddaff910222d4751c18da5e7..c498ba127b4a511b5a6f10afa2aae535509fc153 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -11,6 +11,7 @@
 #include <asm/page.h>		/* pgprot_t */
 #include <linux/rbtree.h>
 #include <linux/overflow.h>
+#include <linux/pgtable.h>
 
 #include <asm/vmalloc.h>
 
@@ -324,4 +325,7 @@ bool vmalloc_dump_obj(void *object);
 static inline bool vmalloc_dump_obj(void *object) { return false; }
 #endif
 
+void vunmap_pgd_range(pgd_t *pgd_table, unsigned long addr, unsigned long end,
+			pgtbl_mod_mask *mask);
+
 #endif /* _LINUX_VMALLOC_H */
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 61981ee1c9d2f769d4a06ab542fc84334c1b0cbd..ffeb823398809388c0599f51929a7f3506ed035f 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -427,6 +427,24 @@ static void vunmap_p4d_range(pgd_t *pgd, unsigned long addr, unsigned long end,
 	} while (p4d++, addr = next, addr != end);
 }
 
+void vunmap_pgd_range(pgd_t *pgd_table, unsigned long addr, unsigned long end,
+		      pgtbl_mod_mask *mask)
+{
+	unsigned long next;
+	pgd_t *pgd = pgd_offset_pgd(pgd_table, addr);
+
+	BUG_ON(addr >= end);
+
+	do {
+		next = pgd_addr_end(addr, end);
+		if (pgd_bad(*pgd))
+			*mask |= PGTBL_PGD_MODIFIED;
+		if (pgd_none_or_clear_bad(pgd))
+			continue;
+		vunmap_p4d_range(pgd, addr, next, mask);
+	} while (pgd++, addr = next, addr != end);
+}
+
 /*
  * vunmap_range_noflush is similar to vunmap_range, but does not
  * flush caches or TLBs.
@@ -441,21 +459,9 @@ static void vunmap_p4d_range(pgd_t *pgd, unsigned long addr, unsigned long end,
  */
 void __vunmap_range_noflush(unsigned long start, unsigned long end)
 {
-	unsigned long next;
-	pgd_t *pgd;
-	unsigned long addr = start;
 	pgtbl_mod_mask mask = 0;
 
-	BUG_ON(addr >= end);
-	pgd = pgd_offset_k(addr);
-	do {
-		next = pgd_addr_end(addr, end);
-		if (pgd_bad(*pgd))
-			mask |= PGTBL_PGD_MODIFIED;
-		if (pgd_none_or_clear_bad(pgd))
-			continue;
-		vunmap_p4d_range(pgd, addr, next, &mask);
-	} while (pgd++, addr = next, addr != end);
+	vunmap_pgd_range(init_mm.pgd, start, end, &mask);
 
 	if (mask & ARCH_PAGE_TABLE_SYNC_MASK)
 		arch_sync_kernel_mappings(start, end);

-- 
2.49.0.rc1.451.g8f38331e32-goog



  parent reply	other threads:[~2025-03-13 18:12 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-13 18:11 [PATCH RFC 00/11] mm: ASI integration for the page allocator Brendan Jackman
2025-03-13 18:11 ` [PATCH RFC 01/11] x86/mm: Bare minimum ASI API for page_alloc integration Brendan Jackman
2025-03-13 18:11 ` [PATCH RFC 02/11] x86/mm: Factor out phys_pgd_init() Brendan Jackman
2025-03-13 22:14   ` Yosry Ahmed
2025-03-17 16:24     ` Brendan Jackman
2025-03-13 18:11 ` [PATCH RFC 03/11] x86/mm: Add lookup_pgtable_in_pgd() Brendan Jackman
2025-03-13 22:09   ` Yosry Ahmed
2025-03-14  9:12     ` Brendan Jackman
2025-03-14 17:56       ` Yosry Ahmed
2025-03-13 18:11 ` [PATCH RFC 04/11] x86/mm/asi: Sync physmap into ASI_GLOBAL_NONSENSITIVE Brendan Jackman
2025-03-13 18:11 ` Brendan Jackman [this message]
2025-03-13 18:11 ` [PATCH RFC 06/11] mm/page_alloc: Add __GFP_SENSITIVE and always set it Brendan Jackman
2025-03-13 18:11 ` [PATCH RFC HACKS 07/11] mm/slub: Set __GFP_SENSITIVE for reclaimable slabs Brendan Jackman
2025-03-13 18:11 ` [PATCH RFC HACKS 08/11] mm/page_alloc: Simplify gfp_migratetype() Brendan Jackman
2025-03-13 18:11 ` [PATCH RFC 09/11] mm/page_alloc: Split MIGRATE_UNMOVABLE by sensitivity Brendan Jackman
2025-03-13 18:11 ` [PATCH RFC 10/11] mm/page_alloc: Add support for nonsensitive allocations Brendan Jackman
2025-03-13 18:11 ` [PATCH RFC 11/11] mm/page_alloc: Add support for ASI-unmapping pages Brendan Jackman
2025-06-10 17:04 ` [PATCH RFC 00/11] mm: ASI integration for the page allocator Brendan Jackman

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250313-asi-page-alloc-v1-5-04972e046cea@google.com \
    --to=jackmanb@google.com \
    --cc=akpm@linux-foundation.org \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=david@redhat.com \
    --cc=derkling@google.com \
    --cc=junaids@google.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-mm@kvack.org \
    --cc=mingo@redhat.com \
    --cc=reijiw@google.com \
    --cc=rientjes@google.com \
    --cc=rppt@kernel.org \
    --cc=tglx@linutronix.de \
    --cc=vbabka@suse.cz \
    --cc=x86@kernel.org \
    --cc=yosry.ahmed@linux.dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox