From: Lance Yang <lance.yang@linux.dev>
To: akpm@linux-foundation.org
Cc: rppt@kernel.org, david@kernel.org, tglx@kernel.org,
mingo@redhat.com, bp@alien8.de, dave.hansen@linux.intel.com,
x86@kernel.org, hpa@zytor.com, luto@kernel.org,
peterz@infradead.org, linux-mm@kvack.org,
linux-kernel@vger.kernel.org, xueyuan.chen21@gmail.com,
ioworker0@gmail.com, Lance Yang <lance.yang@linux.dev>
Subject: [RFC PATCH 2/2] x86/mm: restore large page mappings for secretmem
Date: Wed, 3 Jun 2026 18:46:24 +0800 [thread overview]
Message-ID: <20260603104624.36390-3-lance.yang@linux.dev> (raw)
In-Reply-To: <20260603104624.36390-1-lance.yang@linux.dev>
From: Lance Yang <lance.yang@linux.dev>
secretmem can ask the architecture to restore large page mappings in the
direct map after a page has been restored.
On x86, set_direct_map_invalid_noflush() clears _PAGE_PRESENT, _PAGE_RW
and _PAGE_DIRTY through CPA. CPA also clears _PAGE_GLOBAL after the PTE
becomes non-present, because that bit is used for PROTNONE.
set_direct_map_default_noflush() only restores _PAGE_PRESENT and _PAGE_RW,
so the restored PTE can still differ from the rest of the direct map. Put
back the missing PAGE_KERNEL bits before trying to collapse the range.
Use PAGE_KERNEL so the restored PTE keeps _PAGE_GLOBAL when PAGE_KERNEL
has it, and does not get it when PTI clears _PAGE_GLOBAL from
__default_kernel_pte_mask.
Tested-by: Xueyuan Chen <xueyuan.chen21@gmail.com>
Signed-off-by: Lance Yang <lance.yang@linux.dev>
---
arch/x86/include/asm/set_memory.h | 2 ++
arch/x86/mm/pat/set_memory.c | 27 +++++++++++++++++++++++++++
2 files changed, 29 insertions(+)
diff --git a/arch/x86/include/asm/set_memory.h b/arch/x86/include/asm/set_memory.h
index 4362c26aa992..f9e94bcd83df 100644
--- a/arch/x86/include/asm/set_memory.h
+++ b/arch/x86/include/asm/set_memory.h
@@ -89,6 +89,8 @@ int set_pages_rw(struct page *page, int numpages);
int set_direct_map_invalid_noflush(struct page *page);
int set_direct_map_default_noflush(struct page *page);
int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid);
+void arch_try_collapse_direct_map(struct page *page);
+#define arch_try_collapse_direct_map arch_try_collapse_direct_map
bool kernel_page_present(struct page *page);
extern int kernel_set_to_readonly;
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index d023a40a1e03..b118619fa83c 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -2654,6 +2654,33 @@ int set_direct_map_default_noflush(struct page *page)
return __set_pages_p(page, 1);
}
+void arch_try_collapse_direct_map(struct page *page)
+{
+ pgprotval_t mask = pgprot_val(PAGE_KERNEL) & (_PAGE_DIRTY | _PAGE_GLOBAL);
+ unsigned long addr;
+ struct cpa_data cpa = { .vaddr = &addr,
+ .pgd = NULL,
+ .numpages = 1,
+ .mask_set = __pgprot(mask),
+ .mask_clr = __pgprot(0),
+ .flags = CPA_NO_CHECK_ALIAS };
+
+ if (PageHighMem(page) || debug_pagealloc_enabled())
+ return;
+
+ addr = (unsigned long)page_address(page);
+
+ /*
+ * set_direct_map_default_noflush() only restores _PAGE_PRESENT and
+ * _PAGE_RW. Put back the other PAGE_KERNEL bits needed for a restored
+ * direct-map PTE to match the rest of the range.
+ */
+ if (__change_page_attr_set_clr(&cpa, 1))
+ return;
+
+ cpa_collapse_large_pages(&cpa);
+}
+
int set_direct_map_valid_noflush(struct page *page, unsigned nr, bool valid)
{
if (valid)
--
2.49.0
prev parent reply other threads:[~2026-06-03 10:47 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-03 10:46 [RFC PATCH 0/2] restore large page mappings in direct map for secretmem Lance Yang
2026-06-03 10:46 ` [RFC PATCH 1/2] mm/secretmem: try to restore large page mappings in direct map Lance Yang
2026-06-03 10:59 ` Mike Rapoport
2026-06-03 11:41 ` Lance Yang
2026-06-03 12:35 ` Mike Rapoport
2026-06-03 13:09 ` Lance Yang
2026-06-03 15:48 ` David Hildenbrand (Arm)
2026-06-04 3:11 ` Lance Yang
2026-06-04 14:57 ` Mike Rapoport
2026-06-03 10:46 ` Lance Yang [this message]
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=20260603104624.36390-3-lance.yang@linux.dev \
--to=lance.yang@linux.dev \
--cc=akpm@linux-foundation.org \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=david@kernel.org \
--cc=hpa@zytor.com \
--cc=ioworker0@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=luto@kernel.org \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=rppt@kernel.org \
--cc=tglx@kernel.org \
--cc=x86@kernel.org \
--cc=xueyuan.chen21@gmail.com \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.