[PATCH RFC 00/18] arch, mm: create a generic set_memory/change_page_attr core

Mike Rapoport (Microsoft) posted 18 patches 3 days, 7 hours ago
arch/loongarch/Kconfig                  |   1 +
arch/loongarch/include/asm/pgtable.h    |  42 +++
arch/loongarch/include/asm/set_memory.h |   9 +
arch/loongarch/mm/pageattr.c            | 196 ++++------
arch/riscv/Kconfig                      |   1 +
arch/riscv/include/asm/pgtable.h        |  36 ++
arch/riscv/include/asm/set_memory.h     |   7 +
arch/riscv/mm/pageattr.c                | 489 ++++++++-----------------
arch/x86/Kconfig                        |   1 +
arch/x86/Kconfig.debug                  |   6 -
arch/x86/include/asm/pgtable.h          |  36 ++
arch/x86/include/asm/set_memory.h       |  50 +++
arch/x86/mm/pat/set_memory.c            | 611 ++++----------------------------
include/linux/pgtable.h                 |  72 +++-
include/linux/set_memory.h              |  97 +++++
mm/Kconfig                              |   3 +
mm/Kconfig.debug                        |   7 +
mm/Makefile                             |   1 +
{arch/x86/mm/pat => mm}/cpa-test.c      |  66 ++--
mm/set_memory.c                         | 396 +++++++++++++++++++++
20 files changed, 1092 insertions(+), 1035 deletions(-)
[PATCH RFC 00/18] arch, mm: create a generic set_memory/change_page_attr core
Posted by Mike Rapoport (Microsoft) 3 days, 7 hours ago
Currently there are 6 independent implementations for set_memory and
set_direct_map APIs.

With increasing demand for kernel page table manipulations, for example
"Direct Map Removal Support for guest_memfd" [1] and "mm: ASI direct map
management" [2], it makes sense to have a generic core for kernel page
table manipulation in mm/ with helpers in the architecture specific
code.

Coincidentally, there was a recent fix to a UAF bug [3] that had to
touch set memory functionality in subtly different way in different
architectures rather than to fix the core logic in a single place.

x86's implementation is the most versatile and most battle tested and as
such it is the best base for the generic implementation.

As the first step, pull x86 implementation to core mm code and convert
loongarch and riscv to use the new CPA core. These architectures were
chosen because the conversion is quite straight forward and does not
require tens of preparation patches.

Once this settles, the next step I'm planning is to convert arm64. This
would be much more involved than loongarch and riscv together, so I
didn't even aspire to include arm64 in the first RFC. That said, I have
a very ugly arm64 prototype that rewrites arch/arm64/pageattr.c to use
the generic CPA infrastructure and replaces the existing implementation
of page table splits for systems that support bbml2. But there's a lot
of yak shaving there to get from a PoC to actual patches.

Patch 1 is already applied to the tip tree and I posted patch 2
separately [4], but I included them both here for the completeness. 

Patches 3-10 reorganize x86 CPA implementation to make it friendlier
for generalization.

Patches 11-14 move CPA core and CPA test from x86 to mm/ and slightly
massage the code to allow its use on other architectures.

Patches 15-16 convert riscv to use the common core and adjust riscv
implementation of _noflush APIs to actually be _noflush.

Patches 17-18 convert loongarch to use the common core and adjust
loongarch implementation of _noflush APIs to actually be _noflush.

The patches are lightly tested on x86 and riscv and build tested on
loongarch.

When converting riscv and loongarch my goal was to keep the new
implementation equivalent to the existing (except the _noflush bit), but
I must say that they way loongarch updates permissions for the entire
large leafs rather than splitting them seems a bit suspicious to me.

Regarding AI use, I started with a two-page prompt describing what I
want and how I want it and then it took me about 10 iterations of
additional half-pagers to explain why I don't like what LLM produced.

In the end I despaired to make it write commit messages the way I like
and edited them manually.

With that, the tool was really instrumental with conflicts resolution
during rebases and building and testing with a single "go!" command.

[1] https://lore.kernel.org/all/20260410151746.61150-1-kalyazin@amazon.com
[2] https://lore.kernel.org/all/20250924-b4-asi-page-alloc-v1-0-2d861768041f@google.com/
[3] https://lore.kernel.org/all/20260717-series-vmap-race-fix-v5-0-606a0ac6d3e5@kernel.org
[4] https://lore.kernel.org/all/20260717-verify-rwx-fix-v2-1-fc23141311d6@kernel.org

To: linux-mm@kvack.org
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brendan Jackman <jackmanb@google.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: David Hildenbrand <david@kernel.org>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Kevin Brodsky <kevin.brodsky@arm.com>
Cc: "Liam R. Howlett" <liam@infradead.org>
Cc: Lorenzo Stoakes <ljs@kernel.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Paul Walmsley <pjw@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: "H. Peter Anvin" <hpa@zytor.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Thomas Gleixner <tglx@kernel.org>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Will Deacon <will@kernel.org>
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-riscv@lists.infradead.org
Cc: loongarch@lists.linux.dev
Cc: x86@kernel.org

Signed-off-by: Mike Rapoport (Microsoft) <rppt@kernel.org>
---
Mike Rapoport (Microsoft) (18):
      x86/mm/pat: Don't gate cpa_lock on debug_pagealloc_enabled()
      x86/mm/pat: fix effective RW computation in lookup_address_in_pgd_attr()
      x86/mm/pat: replace x86-speficic pg_level with generic pgtable_level
      x86/mm/pat: use page table accessors for effective RW/NX bits
      x86/mm/pat: use a generic helper for the large page size
      x86/mm/pat: introduce an inline helper to check if alias needs update
      x86/mm/pat: introduce cpa_handle_large_page()
      x86/mm/pat: use cpa_split_data structure to pass split parameters
      x86/mm/pat: use a single locked lookup for PTE verification
      x86/mm/pat: move the large page size calculation to should_split_large_page
      x86/mm/pat, mm: set_memory: pull change_page_attr() core to mm/
      x86/pat/mm, mm/set_memory: abstract the CPA page table lock
      mm/set_memory: read page table entries with pXdp_get()
      x86/mm/pat, mm: move cpa-test to mm
      riscv: convert set_memory to the generic CPA implementation
      riscv: make set_direct_map_*_noflush actually noflush
      loongarch: convert set_memory to the generic CPA implementation
      loongarch: make set_direct_map_*_noflush actually noflush

 arch/loongarch/Kconfig                  |   1 +
 arch/loongarch/include/asm/pgtable.h    |  42 +++
 arch/loongarch/include/asm/set_memory.h |   9 +
 arch/loongarch/mm/pageattr.c            | 196 ++++------
 arch/riscv/Kconfig                      |   1 +
 arch/riscv/include/asm/pgtable.h        |  36 ++
 arch/riscv/include/asm/set_memory.h     |   7 +
 arch/riscv/mm/pageattr.c                | 489 ++++++++-----------------
 arch/x86/Kconfig                        |   1 +
 arch/x86/Kconfig.debug                  |   6 -
 arch/x86/include/asm/pgtable.h          |  36 ++
 arch/x86/include/asm/set_memory.h       |  50 +++
 arch/x86/mm/pat/set_memory.c            | 611 ++++----------------------------
 include/linux/pgtable.h                 |  72 +++-
 include/linux/set_memory.h              |  97 +++++
 mm/Kconfig                              |   3 +
 mm/Kconfig.debug                        |   7 +
 mm/Makefile                             |   1 +
 {arch/x86/mm/pat => mm}/cpa-test.c      |  66 ++--
 mm/set_memory.c                         | 396 +++++++++++++++++++++
 20 files changed, 1092 insertions(+), 1035 deletions(-)
---
base-commit: dc59e4fea9d83f03bad6bddf3fa2e52491777482
change-id: 20260721-generic-set-memory-v0-1-06547a00b2ae

--
Sincerely yours,
Mike.
Re: [PATCH RFC 00/18] arch, mm: create a generic set_memory/change_page_attr core
Posted by Adrian Barnaś 2 days, 8 hours ago
On Tue, Jul 21, 2026 at 07:23:23PM +0300, Mike Rapoport (Microsoft) wrote:

Hi Mike,

>Once this settles, the next step I'm planning is to convert arm64. This
>would be much more involved than loongarch and riscv together, so I
>didn't even aspire to include arm64 in the first RFC. That said, I have
>a very ugly arm64 prototype that rewrites arch/arm64/pageattr.c to use
>the generic CPA infrastructure and replaces the existing implementation
>of page table splits for systems that support bbml2. But there's a lot
>of yak shaving there to get from a PoC to actual patches.

Could you share your PoC for ARM64. I can help you with that and align my 
execmem rox cache for ARM64  changes to the desired shape of this API.    

Best regards,
Adrian
Re: [PATCH RFC 00/18] arch, mm: create a generic set_memory/change_page_attr core
Posted by Borislav Petkov 3 days, 6 hours ago
On Tue, Jul 21, 2026 at 07:23:23PM +0300, Mike Rapoport (Microsoft) wrote:
> Currently there are 6 independent implementations for set_memory and
> set_direct_map APIs.

So with all mm/x86/CPA patches flying around, can we first agree on which tree
is going to collect everything?

And if I want to review patches in that area, what am I applying it ontop?
linux-next perhaps...

Let's sort out the workflow first so that we don't get lost on fruitless bug
chases and fingerpointing.

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette
Re: [PATCH RFC 00/18] arch, mm: create a generic set_memory/change_page_attr core
Posted by Dave Hansen 2 days, 6 hours ago
On 7/21/26 10:19, Borislav Petkov wrote:
> On Tue, Jul 21, 2026 at 07:23:23PM +0300, Mike Rapoport (Microsoft) wrote:
>> Currently there are 6 independent implementations for set_memory and
>> set_direct_map APIs.
> So with all mm/x86/CPA patches flying around, can we first agree on which tree
> is going to collect everything?
> 
> And if I want to review patches in that area, what am I applying it ontop?
> linux-next perhaps...
> 
> Let's sort out the workflow first so that we don't get lost on fruitless bug
> chases and fingerpointing.

Just practically, I think this series needs to be ignored for a bit. Bug
fixes first, features and cleanups second.

When the time is right, it probably needs to get get acks from all the
affected architectures and go through mm. Folks can ack it now, but I
don't think anyone should even consider merging it until ~7.3-rc1.
Re: [PATCH RFC 00/18] arch, mm: create a generic set_memory/change_page_attr core
Posted by Mike Rapoport 3 days, 5 hours ago
On Tue, Jul 21, 2026 at 10:19:43AM -0700, Borislav Petkov wrote:
> On Tue, Jul 21, 2026 at 07:23:23PM +0300, Mike Rapoport (Microsoft) wrote:
> > Currently there are 6 independent implementations for set_memory and
> > set_direct_map APIs.
> 
> So with all mm/x86/CPA patches flying around, can we first agree on which tree
> is going to collect everything?

I hope all the fixes flying around will be merged before I even get to v1 :)

In any case, I'm going to wait for the fixes to settle before posting this
not as RFC. Obviously, the code movement will include all the merged fixes
then.
 
> And if I want to review patches in that area, what am I applying it ontop?
> linux-next perhaps...

This set is on top of v7.2-rc1. It includes a patch Dave took to tip and one
fix from those flying around.
 
> Let's sort out the workflow first so that we don't get lost on fruitless bug
> chases and fingerpointing.

I'll take it via the memblock tree? ;-)

> Thx.
> 
> -- 
> Regards/Gruss,
>     Boris.
> 
> https://people.kernel.org/tglx/notes-about-netiquette

-- 
Sincerely yours,
Mike.
Re: [PATCH RFC 00/18] arch, mm: create a generic set_memory/change_page_attr core
Posted by Borislav Petkov 3 days, 3 hours ago
On Tue, Jul 21, 2026 at 09:28:56PM +0300, Mike Rapoport wrote:
> I'll take it via the memblock tree? ;-)

Definitely not.

Unless you folks want to carve out the bits of set_memory.c which interact
with core mm and mark it as maintained by someone else. I personally don't
mind too much.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette
Re: [PATCH RFC 00/18] arch, mm: create a generic set_memory/change_page_attr core
Posted by Mike Rapoport 2 days, 16 hours ago
On Tue, Jul 21, 2026 at 12:54:46PM -0700, Borislav Petkov wrote:
> On Tue, Jul 21, 2026 at 09:28:56PM +0300, Mike Rapoport wrote:
> > I'll take it via the memblock tree? ;-)
> 
> Definitely not.
> 
> Unless you folks want to carve out the bits of set_memory.c which interact
> with core mm and mark it as maintained by someone else. I personally don't
> mind too much.

Well, in essence that's what this set is doing:

 arch/x86/mm/pat/set_memory.c            | 611 ++++----------------------------
 {arch/x86/mm/pat => mm}/cpa-test.c      |  66 ++--
 mm/set_memory.c                         | 396 +++++++++++++++++++++

I just decided to postpone MAINTAINERS update that would add
mm/set_memory.c mm/cpa-test.c to MM CORE section until non-rfc version.
 
> -- 
> Regards/Gruss,
>     Boris.
> 
> https://people.kernel.org/tglx/notes-about-netiquette

-- 
Sincerely yours,
Mike.
[syzbot ci] Re: arch, mm: create a generic set_memory/change_page_attr core
Posted by syzbot ci 2 days, 10 hours ago
syzbot ci has tested the following series

[v1] arch, mm: create a generic set_memory/change_page_attr core
https://lore.kernel.org/all/20260721-generic-set-memory-v0-1-v1-0-2c1fc62306b3@kernel.org
* [PATCH RFC 01/18] x86/mm/pat: Don't gate cpa_lock on debug_pagealloc_enabled()
* [PATCH RFC 02/18] x86/mm/pat: fix effective RW computation in lookup_address_in_pgd_attr()
* [PATCH RFC 03/18] x86/mm/pat: replace x86-speficic pg_level with generic pgtable_level
* [PATCH RFC 04/18] x86/mm/pat: use page table accessors for effective RW/NX bits
* [PATCH RFC 05/18] x86/mm/pat: use a generic helper for the large page size
* [PATCH RFC 06/18] x86/mm/pat: introduce an inline helper to check if alias needs update
* [PATCH RFC 07/18] x86/mm/pat: introduce cpa_handle_large_page()
* [PATCH RFC 08/18] x86/mm/pat: use cpa_split_data structure to pass split parameters
* [PATCH RFC 09/18] x86/mm/pat: use a single locked lookup for PTE verification
* [PATCH RFC 10/18] x86/mm/pat: move the large page size calculation to should_split_large_page
* [PATCH RFC 11/18] x86/mm/pat, mm: set_memory: pull change_page_attr() core to mm/
* [PATCH RFC 12/18] x86/pat/mm, mm/set_memory: abstract the CPA page table lock
* [PATCH RFC 13/18] mm/set_memory: read page table entries with pXdp_get()
* [PATCH RFC 14/18] x86/mm/pat, mm: move cpa-test to mm
* [PATCH RFC 15/18] riscv: convert set_memory to the generic CPA implementation
* [PATCH RFC 16/18] riscv: make set_direct_map_*_noflush actually noflush
* [PATCH RFC 17/18] loongarch: convert set_memory to the generic CPA implementation
* [PATCH RFC 18/18] loongarch: make set_direct_map_*_noflush actually noflush

and found the following issue:
WARNING in arch_should_split_large_page

Full report is available here:
https://ci.syzbot.org/series/08799ddb-4fca-4e5c-a2a7-a16eb2845851

***

WARNING in arch_should_split_large_page

tree:      bpf-next
URL:       https://kernel.googlesource.com/pub/scm/linux/kernel/git/bpf/bpf-next.git
base:      dc59e4fea9d83f03bad6bddf3fa2e52491777482
arch:      amd64
compiler:  Debian clang version 22.1.8 (++20260613092233+e80beda6e255-1~exp1~20260613092250.77), Debian LLD 22.1.8
config:    https://ci.syzbot.org/builds/9a435490-f68f-4ca0-96ae-457a5caa17e6/config

Demotion targets for Node 1: null
debug_vm_pgtable: [debug_vm_pgtable         ]: Validating architecture page table helpers
Key type .fscrypt registered
Key type fscrypt-provisioning registered
kAFS: Red Hat AFS client v0.1 registering.
Btrfs loaded, assert=on, zoned=yes, fsverity=yes
Key type big_key registered
Key type encrypted registered
AppArmor: AppArmor sha256 policy hashing enabled
ima: No TPM chip found, activating TPM-bypass!
Loading compiled-in module X.509 certificates
Loaded X.509 cert 'Build time autogenerated kernel key: dc5bfa299b381f3c121e230b24acaec0874c302b'
ima: Allocated hash algorithm: sha256
ima: No architecture policies found
evm: Initialising EVM extended attributes:
evm: security.selinux (disabled)
evm: security.SMACK64 (disabled)
evm: security.SMACK64EXEC (disabled)
evm: security.SMACK64TRANSMUTE (disabled)
evm: security.SMACK64MMAP (disabled)
evm: security.apparmor
evm: security.ima
evm: security.capability
evm: HMAC attrs: 0x1
PM:   Magic number: 2:551:79
netconsole: network logging started
gtp: GTP module loaded (pdp ctx size 128 bytes)
rdma_rxe: loaded
cfg80211: Loading compiled-in X.509 certificates for regulatory database
Loaded X.509 cert 'sforshee: 00b28ddf47aef9cea7'
Loaded X.509 cert 'wens: 61c038651aabdcf94bd0ac7ff06c7248db18c600'
clk: Disabling unused clocks
ALSA device list:
  #0: Dummy 1
  #1: Loopback 1
  #2: Virtual MIDI Card 1
md: Waiting for all devices to be available before autodetect
md: If you don't use raid, use raid=noautodetect
md: Autodetecting RAID arrays.
md: autorun ...
md: ... autorun DONE.
EXT4-fs (sda1): mounted filesystem b4773fba-1738-4da0-8a90-0fe043d0a496 ro with ordered data mode. Quota mode: none.
VFS: Mounted root (ext4 filesystem) readonly on device 8:1.
devtmpfs: mounted
VFS: Pivoted into new rootfs
Freeing unused kernel image (initmem) memory: 26964K
Write protecting the kernel read-only data: 221184k
Testing CPA: undo ffffffff81000000-ffffffff8e800000
------------[ cut here ]------------
CPA detected W^X violation: 00000000000001a1 -> 00000000000001a3 range: 0xffffffff81000000 - 0xffffffff811fffff PFN 1000
WARNING: arch/x86/mm/pat/set_memory.c:601 at arch_should_split_large_page+0x493/0x710, CPU#0: swapper/0/1
Modules linked in:
CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Not tainted syzkaller #0 PREEMPT(full) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.2-debian-1.16.2-1 04/01/2014
RIP: 0010:arch_should_split_large_page+0x49e/0x710
Code: 00 48 8b 44 24 20 48 25 00 f0 ff ff 48 8b 4c 24 08 4c 8d 04 08 49 ff c8 48 8d 3d 4d 66 e1 0e 4c 89 ee 48 89 ea 4c 8b 4c 24 18 <67> 48 0f b9 3a eb 05 e8 46 37 4d 00 4c 89 f7 48 89 ee e8 9b 39 4d
RSP: 0000:ffffc900000679f0 EFLAGS: 00010296
RAX: 0000000000200000 RBX: 0000000000000123 RCX: ffffffff81000000
RDX: 00000000000001a3 RSI: 00000000000001a1 RDI: ffffffff905a8280
RBP: 00000000000001a3 R08: ffffffff811fffff R09: 0000000000001000
R10: 0000000000000003 R11: 0000000000000000 R12: 0000000000000002
R13: 00000000000001a1 R14: 00000000000001a3 R15: 0000000000000002
FS:  0000000000000000(0000) GS:ffff88818d95a000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: ffff88823ffff000 CR3: 000000000e946000 CR4: 00000000000006f0
Call Trace:
 <TASK>
 __change_page_attr_set_clr+0x936/0x12d0
 change_page_attr_set_clr+0x3ac/0x450
 set_memory_rw+0x8c/0xd0
 mark_rodata_ro+0xf0/0x140
 kernel_init+0x4e/0x1d0
 ret_from_fork+0x514/0xb70
 ret_from_fork_asm+0x1a/0x30
 </TASK>


***

If these findings have caused you to resend the series or submit a
separate fix, please add the following tag to your commit message:
  Tested-by: syzbot@syzkaller.appspotmail.com

---
This report is generated by a bot. It may contain errors.
syzbot ci engineers can be reached at syzkaller@googlegroups.com.

To test a patch for this bug, please reply with `#syz test`
(should be on a separate line).

The patch should be attached to the email.
Note: arguments like custom git repos and branches are not supported.