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
next prev 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