* [PATCH 20/22] arm64: mm: drop ctor/dtor calls for kernel page tables
From: Kevin Brodsky @ 2026-07-14 14:04 UTC (permalink / raw)
To: linux-mm
Cc: Kevin Brodsky, Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Pasha Tatashin, Russell King,
Catalin Marinas, Will Deacon, Ryan Roberts, linux-arm-kernel,
Huacai Chen, loongarch, James E.J. Bottomley, Helge Deller,
linux-parisc, Madhavan Srinivasan, Michael Ellerman, linuxppc-dev,
Paul Walmsley, Palmer Dabbelt, Albert Ou, linux-riscv,
Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Gerald Schaefer,
linux-s390, David S. Miller, Andreas Larsson, sparclinux,
Richard Weinberger, Anton Ivanov, Johannes Berg, linux-um,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Peter Zijlstra, Ning Sun, x86,
tboot-devel, Ard Biesheuvel, Ilias Apalodimas, linux-efi,
Vishal Moola, Alistair Popple, Matthew Wilcox (Oracle),
linux-kernel, linux-arch
In-Reply-To: <20260714-remove_pgtable_cdtor-v1-0-44be8a7685d7@arm.com>
Thanks to recent changes:
* pagetable_*_ctor() and pagetable_dtor() do nothing for kernel page
tables.
* efi_mm is also treated like a kernel mm by the page table logic,
including ctors.
We can therefore drop the calls to ctors when allocating special
kernel page tables in mmu.c, as well as the dtor call when freeing
hotplug page tables.
Since we no longer need the owning mm or page table level when
allocating them, we can also remove both the init_mm/special_mm
wrappers and the pgtable_level callback argument.
Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>
---
arch/arm64/mm/mmu.c | 82 +++++++++++++++--------------------------------------
1 file changed, 23 insertions(+), 59 deletions(-)
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index f723bcf68174..f1400c6f68ba 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -103,7 +103,7 @@ pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
}
EXPORT_SYMBOL(phys_mem_access_prot);
-static phys_addr_t __init early_pgtable_alloc(enum pgtable_level pgtable_level)
+static phys_addr_t __init early_pgtable_alloc(void)
{
phys_addr_t phys;
@@ -195,7 +195,7 @@ static bool pte_range_has_valid_noncont(pte_t *ptep)
static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
unsigned long end, phys_addr_t phys,
pgprot_t prot,
- phys_addr_t (*pgtable_alloc)(enum pgtable_level),
+ phys_addr_t (*pgtable_alloc)(void),
int flags)
{
unsigned long next;
@@ -210,7 +210,7 @@ static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
if (flags & NO_EXEC_MAPPINGS)
pmdval |= PMD_TABLE_PXN;
BUG_ON(!pgtable_alloc);
- pte_phys = pgtable_alloc(PGTABLE_LEVEL_PTE);
+ pte_phys = pgtable_alloc();
if (pte_phys == INVALID_PHYS_ADDR)
return -ENOMEM;
ptep = pte_set_fixmap(pte_phys);
@@ -251,7 +251,7 @@ static int alloc_init_cont_pte(pmd_t *pmdp, unsigned long addr,
static int init_pmd(pmd_t *pmdp, unsigned long addr, unsigned long end,
phys_addr_t phys, pgprot_t prot,
- phys_addr_t (*pgtable_alloc)(enum pgtable_level), int flags)
+ phys_addr_t (*pgtable_alloc)(void), int flags)
{
unsigned long next;
@@ -303,7 +303,7 @@ static bool pmd_range_has_valid_noncont(pmd_t *pmdp)
static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
unsigned long end, phys_addr_t phys,
pgprot_t prot,
- phys_addr_t (*pgtable_alloc)(enum pgtable_level),
+ phys_addr_t (*pgtable_alloc)(void),
int flags)
{
int ret;
@@ -322,7 +322,7 @@ static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
if (flags & NO_EXEC_MAPPINGS)
pudval |= PUD_TABLE_PXN;
BUG_ON(!pgtable_alloc);
- pmd_phys = pgtable_alloc(PGTABLE_LEVEL_PMD);
+ pmd_phys = pgtable_alloc();
if (pmd_phys == INVALID_PHYS_ADDR)
return -ENOMEM;
pmdp = pmd_set_fixmap(pmd_phys);
@@ -361,7 +361,7 @@ static int alloc_init_cont_pmd(pud_t *pudp, unsigned long addr,
static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
phys_addr_t phys, pgprot_t prot,
- phys_addr_t (*pgtable_alloc)(enum pgtable_level),
+ phys_addr_t (*pgtable_alloc)(void),
int flags)
{
int ret = 0;
@@ -376,7 +376,7 @@ static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
if (flags & NO_EXEC_MAPPINGS)
p4dval |= P4D_TABLE_PXN;
BUG_ON(!pgtable_alloc);
- pud_phys = pgtable_alloc(PGTABLE_LEVEL_PUD);
+ pud_phys = pgtable_alloc();
if (pud_phys == INVALID_PHYS_ADDR)
return -ENOMEM;
pudp = pud_set_fixmap(pud_phys);
@@ -428,7 +428,7 @@ static int alloc_init_pud(p4d_t *p4dp, unsigned long addr, unsigned long end,
static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
phys_addr_t phys, pgprot_t prot,
- phys_addr_t (*pgtable_alloc)(enum pgtable_level),
+ phys_addr_t (*pgtable_alloc)(void),
int flags)
{
int ret;
@@ -443,7 +443,7 @@ static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
if (flags & NO_EXEC_MAPPINGS)
pgdval |= PGD_TABLE_PXN;
BUG_ON(!pgtable_alloc);
- p4d_phys = pgtable_alloc(PGTABLE_LEVEL_P4D);
+ p4d_phys = pgtable_alloc();
if (p4d_phys == INVALID_PHYS_ADDR)
return -ENOMEM;
p4dp = p4d_set_fixmap(p4d_phys);
@@ -480,7 +480,7 @@ static int alloc_init_p4d(pgd_t *pgdp, unsigned long addr, unsigned long end,
static int __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys,
unsigned long virt, phys_addr_t size,
pgprot_t prot,
- phys_addr_t (*pgtable_alloc)(enum pgtable_level),
+ phys_addr_t (*pgtable_alloc)(void),
int flags)
{
int ret;
@@ -513,7 +513,7 @@ static int __create_pgd_mapping_locked(pgd_t *pgdir, phys_addr_t phys,
static int __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
unsigned long virt, phys_addr_t size,
pgprot_t prot,
- phys_addr_t (*pgtable_alloc)(enum pgtable_level),
+ phys_addr_t (*pgtable_alloc)(void),
int flags)
{
int ret;
@@ -529,7 +529,7 @@ static int __create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
static void early_create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
unsigned long virt, phys_addr_t size,
pgprot_t prot,
- phys_addr_t (*pgtable_alloc)(enum pgtable_level),
+ phys_addr_t (*pgtable_alloc)(void),
int flags)
{
int ret;
@@ -540,55 +540,20 @@ static void early_create_pgd_mapping(pgd_t *pgdir, phys_addr_t phys,
panic("Failed to create page tables\n");
}
-static phys_addr_t __pgd_pgtable_alloc(struct mm_struct *mm, gfp_t gfp,
- enum pgtable_level pgtable_level)
+static phys_addr_t pgd_pgtable_alloc_gfp(gfp_t gfp)
{
/* Page is zeroed by init_clear_pgtable() so don't duplicate effort. */
struct ptdesc *ptdesc = pagetable_alloc(gfp & ~__GFP_ZERO, 0);
- phys_addr_t pa;
if (!ptdesc)
return INVALID_PHYS_ADDR;
- pa = page_to_phys(ptdesc_page(ptdesc));
-
- switch (pgtable_level) {
- case PGTABLE_LEVEL_PTE:
- BUG_ON(!pagetable_pte_ctor(mm, ptdesc));
- break;
- case PGTABLE_LEVEL_PMD:
- BUG_ON(!pagetable_pmd_ctor(mm, ptdesc));
- break;
- case PGTABLE_LEVEL_PUD:
- pagetable_pud_ctor(ptdesc);
- break;
- case PGTABLE_LEVEL_P4D:
- pagetable_p4d_ctor(ptdesc);
- break;
- case PGTABLE_LEVEL_PGD:
- VM_WARN_ON(1);
- break;
- }
-
- return pa;
-}
-
-static phys_addr_t
-pgd_pgtable_alloc_init_mm_gfp(enum pgtable_level pgtable_level, gfp_t gfp)
-{
- return __pgd_pgtable_alloc(&init_mm, gfp, pgtable_level);
-}
-
-static phys_addr_t __maybe_unused
-pgd_pgtable_alloc_init_mm(enum pgtable_level pgtable_level)
-{
- return pgd_pgtable_alloc_init_mm_gfp(pgtable_level, GFP_PGTABLE_KERNEL);
+ return page_to_phys(ptdesc_page(ptdesc));
}
-static phys_addr_t
-pgd_pgtable_alloc_special_mm(enum pgtable_level pgtable_level)
+static phys_addr_t pgd_pgtable_alloc(void)
{
- return __pgd_pgtable_alloc(NULL, GFP_PGTABLE_KERNEL, pgtable_level);
+ return pgd_pgtable_alloc_gfp(GFP_PGTABLE_KERNEL);
}
static void split_contpte(pte_t *ptep)
@@ -609,7 +574,7 @@ static int split_pmd(pmd_t *pmdp, pmd_t pmd, gfp_t gfp, bool to_cont)
pte_t *ptep;
int i;
- pte_phys = pgd_pgtable_alloc_init_mm_gfp(PGTABLE_LEVEL_PTE, gfp);
+ pte_phys = pgd_pgtable_alloc_gfp(gfp);
if (pte_phys == INVALID_PHYS_ADDR)
return -ENOMEM;
ptep = (pte_t *)phys_to_virt(pte_phys);
@@ -656,7 +621,7 @@ static int split_pud(pud_t *pudp, pud_t pud, gfp_t gfp, bool to_cont)
pmd_t *pmdp;
int i;
- pmd_phys = pgd_pgtable_alloc_init_mm_gfp(PGTABLE_LEVEL_PMD, gfp);
+ pmd_phys = pgd_pgtable_alloc_gfp(gfp);
if (pmd_phys == INVALID_PHYS_ADDR)
return -ENOMEM;
pmdp = (pmd_t *)phys_to_virt(pmd_phys);
@@ -1035,7 +1000,7 @@ void __init create_pgd_mapping(struct mm_struct *mm, phys_addr_t phys,
flags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
early_create_pgd_mapping(mm->pgd, phys, virt, size, prot,
- pgd_pgtable_alloc_special_mm, flags);
+ pgd_pgtable_alloc, flags);
}
static void update_mapping_prot(phys_addr_t phys, unsigned long virt,
@@ -1249,7 +1214,7 @@ static void __init declare_vma(struct vm_struct *vma,
static phys_addr_t kpti_ng_temp_alloc __initdata;
-static phys_addr_t __init kpti_ng_pgd_alloc(enum pgtable_level pgtable_level)
+static phys_addr_t __init kpti_ng_pgd_alloc(void)
{
kpti_ng_temp_alloc -= PAGE_SIZE;
return kpti_ng_temp_alloc;
@@ -1357,7 +1322,7 @@ static int __init map_entry_trampoline(void)
memset(tramp_pg_dir, 0, PGD_SIZE);
early_create_pgd_mapping(tramp_pg_dir, pa_start, TRAMP_VALIAS,
entry_tramp_text_size(), prot,
- pgd_pgtable_alloc_init_mm, NO_BLOCK_MAPPINGS);
+ pgd_pgtable_alloc, NO_BLOCK_MAPPINGS);
/* Map both the text and data into the kernel page table */
for (i = 0; i < DIV_ROUND_UP(entry_tramp_text_size(), PAGE_SIZE); i++)
@@ -1445,7 +1410,6 @@ static void free_hotplug_page_range(struct page *page, size_t size,
static void free_hotplug_pgtable_page(struct page *page)
{
- pagetable_dtor(page_ptdesc(page));
free_hotplug_page_range(page, PAGE_SIZE, NULL);
}
@@ -1958,7 +1922,7 @@ int arch_add_memory(int nid, u64 start, u64 size,
flags |= NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS;
ret = __create_pgd_mapping(swapper_pg_dir, start, __phys_to_virt(start),
- size, params->pgprot, pgd_pgtable_alloc_init_mm,
+ size, params->pgprot, pgd_pgtable_alloc,
flags);
if (ret)
goto err;
--
2.51.2
^ permalink raw reply related
* [PATCH 21/22] arm: mm: drop ctor call for kernel page tables
From: Kevin Brodsky @ 2026-07-14 14:04 UTC (permalink / raw)
To: linux-mm
Cc: Kevin Brodsky, Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Pasha Tatashin, Russell King,
Catalin Marinas, Will Deacon, Ryan Roberts, linux-arm-kernel,
Huacai Chen, loongarch, James E.J. Bottomley, Helge Deller,
linux-parisc, Madhavan Srinivasan, Michael Ellerman, linuxppc-dev,
Paul Walmsley, Palmer Dabbelt, Albert Ou, linux-riscv,
Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Gerald Schaefer,
linux-s390, David S. Miller, Andreas Larsson, sparclinux,
Richard Weinberger, Anton Ivanov, Johannes Berg, linux-um,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Peter Zijlstra, Ning Sun, x86,
tboot-devel, Ard Biesheuvel, Ilias Apalodimas, linux-efi,
Vishal Moola, Alistair Popple, Matthew Wilcox (Oracle),
linux-kernel, linux-arch
In-Reply-To: <20260714-remove_pgtable_cdtor-v1-0-44be8a7685d7@arm.com>
Thanks to recent changes:
* pagetable_pte_ctor() does nothing for kernel page tables.
* efi_mm is also treated like a kernel mm by the page table logic,
including ctors.
We can therefore drop the ctor call when allocating special kernel
page tables in mmu.c.
Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>
---
arch/arm/mm/mmu.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 23b87b5ef7f1..c8de77a6f01e 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -728,8 +728,7 @@ static void *__init late_alloc(unsigned long sz)
void *ptdesc = pagetable_alloc(GFP_PGTABLE_KERNEL & ~__GFP_HIGHMEM,
get_order(sz));
- if (!ptdesc || !pagetable_pte_ctor(NULL, ptdesc))
- BUG();
+ BUG_ON(!ptdesc);
return ptdesc_address(ptdesc);
}
--
2.51.2
^ permalink raw reply related
* [PATCH 22/22] riscv: mm: drop ctor/dtor calls for kernel page tables
From: Kevin Brodsky @ 2026-07-14 14:04 UTC (permalink / raw)
To: linux-mm
Cc: Kevin Brodsky, Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Pasha Tatashin, Russell King,
Catalin Marinas, Will Deacon, Ryan Roberts, linux-arm-kernel,
Huacai Chen, loongarch, James E.J. Bottomley, Helge Deller,
linux-parisc, Madhavan Srinivasan, Michael Ellerman, linuxppc-dev,
Paul Walmsley, Palmer Dabbelt, Albert Ou, linux-riscv,
Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Gerald Schaefer,
linux-s390, David S. Miller, Andreas Larsson, sparclinux,
Richard Weinberger, Anton Ivanov, Johannes Berg, linux-um,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Peter Zijlstra, Ning Sun, x86,
tboot-devel, Ard Biesheuvel, Ilias Apalodimas, linux-efi,
Vishal Moola, Alistair Popple, Matthew Wilcox (Oracle),
linux-kernel, linux-arch
In-Reply-To: <20260714-remove_pgtable_cdtor-v1-0-44be8a7685d7@arm.com>
Thanks to recent changes:
* pagetable_*_ctor() and pagetable_dtor() do nothing for kernel page
tables.
* efi_mm is also treated like a kernel mm by the page table logic,
including ctors.
We can therefore drop the calls to ctors when allocating special
kernel page tables in mmu.c, as well as the dtor call when freeing
hotplug page tables.
The alloc_*_late() helpers are all identical after removing the ctor
calls, so replace them with alloc_pgtable_late().
Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>
---
arch/riscv/mm/init.c | 63 ++++++++++++----------------------------------------
1 file changed, 14 insertions(+), 49 deletions(-)
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 5b1b3c88b4d1..e823662be256 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -382,6 +382,14 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot)
local_flush_tlb_page(addr);
}
+static phys_addr_t __meminit alloc_pgtable_late(uintptr_t va)
+{
+ struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL, 0);
+
+ BUG_ON(!ptdesc);
+ return __pa(ptdesc_address(ptdesc));
+}
+
static inline pte_t *__init get_pte_virt_early(phys_addr_t pa)
{
return (pte_t *)((uintptr_t)pa);
@@ -412,19 +420,6 @@ static inline phys_addr_t __init alloc_pte_fixmap(uintptr_t va)
return memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
}
-static phys_addr_t __meminit alloc_pte_late(uintptr_t va)
-{
- struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL, 0);
-
- /*
- * We do not know which mm the PTE page is associated to at this point.
- * Passing NULL to the ctor is the safe option, though it may result
- * in unnecessary work (e.g. initialising the ptlock for init_mm).
- */
- BUG_ON(!ptdesc || !pagetable_pte_ctor(NULL, ptdesc));
- return __pa((pte_t *)ptdesc_address(ptdesc));
-}
-
static void __meminit create_pte_mapping(pte_t *ptep, uintptr_t va, phys_addr_t pa, phys_addr_t sz,
pgprot_t prot)
{
@@ -479,15 +474,6 @@ static phys_addr_t __init alloc_pmd_fixmap(uintptr_t va)
return memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
}
-static phys_addr_t __meminit alloc_pmd_late(uintptr_t va)
-{
- struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL, 0);
-
- /* See comment in alloc_pte_late() regarding NULL passed the ctor */
- BUG_ON(!ptdesc || !pagetable_pmd_ctor(NULL, ptdesc));
- return __pa((pmd_t *)ptdesc_address(ptdesc));
-}
-
static void __meminit create_pmd_mapping(pmd_t *pmdp,
uintptr_t va, phys_addr_t pa,
phys_addr_t sz, pgprot_t prot)
@@ -544,15 +530,6 @@ static phys_addr_t __init alloc_pud_fixmap(uintptr_t va)
return memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
}
-static phys_addr_t __meminit alloc_pud_late(uintptr_t va)
-{
- struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL, 0);
-
- BUG_ON(!ptdesc);
- pagetable_pud_ctor(ptdesc);
- return __pa((pud_t *)ptdesc_address(ptdesc));
-}
-
static p4d_t *__init get_p4d_virt_early(phys_addr_t pa)
{
return (p4d_t *)((uintptr_t)pa);
@@ -582,15 +559,6 @@ static phys_addr_t __init alloc_p4d_fixmap(uintptr_t va)
return memblock_phys_alloc(PAGE_SIZE, PAGE_SIZE);
}
-static phys_addr_t __meminit alloc_p4d_late(uintptr_t va)
-{
- struct ptdesc *ptdesc = pagetable_alloc(GFP_KERNEL, 0);
-
- BUG_ON(!ptdesc);
- pagetable_p4d_ctor(ptdesc);
- return __pa((p4d_t *)ptdesc_address(ptdesc));
-}
-
static void __meminit create_pud_mapping(pud_t *pudp, uintptr_t va, phys_addr_t pa, phys_addr_t sz,
pgprot_t prot)
{
@@ -1003,14 +971,14 @@ static void __init pt_ops_set_fixmap(void)
*/
static void __init pt_ops_set_late(void)
{
- pt_ops.alloc_pte = alloc_pte_late;
+ pt_ops.alloc_pte = alloc_pgtable_late;
pt_ops.get_pte_virt = get_pte_virt_late;
#ifndef __PAGETABLE_PMD_FOLDED
- pt_ops.alloc_pmd = alloc_pmd_late;
+ pt_ops.alloc_pmd = alloc_pgtable_late;
pt_ops.get_pmd_virt = get_pmd_virt_late;
- pt_ops.alloc_pud = alloc_pud_late;
+ pt_ops.alloc_pud = alloc_pgtable_late;
pt_ops.get_pud_virt = get_pud_virt_late;
- pt_ops.alloc_p4d = alloc_p4d_late;
+ pt_ops.alloc_p4d = alloc_pgtable_late;
pt_ops.get_p4d_virt = get_p4d_virt_late;
#endif
}
@@ -1488,7 +1456,6 @@ static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd)
return;
}
- pagetable_dtor(ptdesc);
if (PageReserved(page))
free_reserved_page(page);
else
@@ -1496,7 +1463,7 @@ static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd)
pmd_clear(pmd);
}
-static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud, bool is_vmemmap)
+static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud)
{
struct page *page = pud_page(*pud);
struct ptdesc *ptdesc = page_ptdesc(page);
@@ -1509,8 +1476,6 @@ static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud, bool is_vmemm
return;
}
- if (!is_vmemmap)
- pagetable_dtor(ptdesc);
if (PageReserved(page))
free_reserved_page(page);
else
@@ -1634,7 +1599,7 @@ static void __meminit remove_pud_mapping(pud_t *pud_base, unsigned long addr, un
remove_pmd_mapping(pmd_base, addr, next, is_vmemmap, altmap);
if (pgtable_l4_enabled)
- free_pmd_table(pmd_base, pudp, is_vmemmap);
+ free_pmd_table(pmd_base, pudp);
}
}
--
2.51.2
^ permalink raw reply related
* Re: [PATCH 03/22] mm: introduce MMF_KERNEL flag and set it for init_mm
From: Dave Hansen @ 2026-07-14 14:47 UTC (permalink / raw)
To: Kevin Brodsky, linux-mm
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Pasha Tatashin, Russell King,
Catalin Marinas, Will Deacon, Ryan Roberts, linux-arm-kernel,
Huacai Chen, loongarch, James E.J. Bottomley, Helge Deller,
linux-parisc, Madhavan Srinivasan, Michael Ellerman, linuxppc-dev,
Paul Walmsley, Palmer Dabbelt, Albert Ou, linux-riscv,
Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Gerald Schaefer,
linux-s390, David S. Miller, Andreas Larsson, sparclinux,
Richard Weinberger, Anton Ivanov, Johannes Berg, linux-um,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Peter Zijlstra, Ning Sun, x86,
tboot-devel, Ard Biesheuvel, Ilias Apalodimas, linux-efi,
Vishal Moola, Alistair Popple, Matthew Wilcox (Oracle),
linux-kernel, linux-arch
In-Reply-To: <20260714-remove_pgtable_cdtor-v1-3-44be8a7685d7@arm.com>
On 7/14/26 07:03, Kevin Brodsky wrote:
> +static inline bool mm_is_kernel(const struct mm_struct *mm)
> +{
> + return mm && mm_flags_test(MMF_KERNEL, mm);
> +}
Could we give this some nice comments explaining what a kernel mm is,
please? Part of the problem with the init_mm checks is that they're
magic and it's not always clear what's special about init_mm.
Maybe start with this list?
1. There's only one of them.
2. All kernel threads share it. tsk->mm is the same for all kernel
threads.
3. It holds the reference copy of the kernel page tables
4. Userspace can't be entered when it is the current mm
5. It has different TLB flushing rules than userspace mms
I _think_ those are universal across all architectures.
^ permalink raw reply
* Re: [PATCH 03/22] mm: introduce MMF_KERNEL flag and set it for init_mm
From: Lorenzo Stoakes (ARM) @ 2026-07-14 15:04 UTC (permalink / raw)
To: Dave Hansen
Cc: Kevin Brodsky, linux-mm, Andrew Morton, David Hildenbrand,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Pasha Tatashin, Russell King,
Catalin Marinas, Will Deacon, Ryan Roberts, linux-arm-kernel,
Huacai Chen, loongarch, James E.J. Bottomley, Helge Deller,
linux-parisc, Madhavan Srinivasan, Michael Ellerman, linuxppc-dev,
Paul Walmsley, Palmer Dabbelt, Albert Ou, linux-riscv,
Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Gerald Schaefer,
linux-s390, David S. Miller, Andreas Larsson, sparclinux,
Richard Weinberger, Anton Ivanov, Johannes Berg, linux-um,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Peter Zijlstra, Ning Sun, x86,
tboot-devel, Ard Biesheuvel, Ilias Apalodimas, linux-efi,
Vishal Moola, Alistair Popple, Matthew Wilcox (Oracle),
linux-kernel, linux-arch
In-Reply-To: <71045fa8-89fe-4a0b-a05b-67e19ce89834@intel.com>
On Tue, Jul 14, 2026 at 07:47:43AM -0700, Dave Hansen wrote:
> On 7/14/26 07:03, Kevin Brodsky wrote:
> > +static inline bool mm_is_kernel(const struct mm_struct *mm)
> > +{
> > + return mm && mm_flags_test(MMF_KERNEL, mm);
> > +}
>
> Could we give this some nice comments explaining what a kernel mm is,
> please? Part of the problem with the init_mm checks is that they're
> magic and it's not always clear what's special about init_mm.
>
> Maybe start with this list?
>
> 1. There's only one of them.
> 2. All kernel threads share it. tsk->mm is the same for all kernel
> threads.
> 3. It holds the reference copy of the kernel page tables
> 4. Userspace can't be entered when it is the current mm
> 5. It has different TLB flushing rules than userspace mms
>
> I _think_ those are universal across all architectures.
Well point 1 isn't true of efimm or tboot_mm so we possibly need a better
name :)
"Special" is overloaded too much already. I quite like "eternal" so:
static inline bool mm_is_eternal(const struct mm_struct *mm)
{
return mm && mm_flags_test(MMF_ETERNAL, mm);
}
:)
Cheers, Lorenzo
^ permalink raw reply
* Re: [PATCH 12/22] x86/mm: use mm_is_kernel() for kernel mm checks
From: Dave Hansen @ 2026-07-14 15:09 UTC (permalink / raw)
To: Kevin Brodsky, linux-mm
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Pasha Tatashin, Russell King,
Catalin Marinas, Will Deacon, Ryan Roberts, linux-arm-kernel,
Huacai Chen, loongarch, James E.J. Bottomley, Helge Deller,
linux-parisc, Madhavan Srinivasan, Michael Ellerman, linuxppc-dev,
Paul Walmsley, Palmer Dabbelt, Albert Ou, linux-riscv,
Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Gerald Schaefer,
linux-s390, David S. Miller, Andreas Larsson, sparclinux,
Richard Weinberger, Anton Ivanov, Johannes Berg, linux-um,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Peter Zijlstra, Ning Sun, x86,
tboot-devel, Ard Biesheuvel, Ilias Apalodimas, linux-efi,
Vishal Moola, Alistair Popple, Matthew Wilcox (Oracle),
linux-kernel, linux-arch
In-Reply-To: <20260714-remove_pgtable_cdtor-v1-12-44be8a7685d7@arm.com>
On 7/14/26 07:04, Kevin Brodsky wrote:
...
> @@ -188,7 +188,7 @@ DECLARE_PER_CPU_SHARED_ALIGNED(struct tlb_state_shared, cpu_tlbstate_shared);
> #define enter_lazy_tlb enter_lazy_tlb
> static __always_inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
> {
> - if (this_cpu_read(cpu_tlbstate.loaded_mm) == &init_mm)
> + if (mm_is_kernel(this_cpu_read(cpu_tlbstate.loaded_mm)))
> return;
>
> this_cpu_write(cpu_tlbstate_shared.is_lazy, true);
This one makes me nervous, especially combined with the efi_mm changes
later in the series. init_mm really is special. Before this patch,
running on init_mm qualifies as being in lazy tlb mode. After this
patch, efi_mm qualifies too.
Is that OK?
> diff --git a/arch/x86/mm/pgtable.c b/arch/x86/mm/pgtable.c
> index f32facdb3035..91d2a6f2ac5a 100644
> --- a/arch/x86/mm/pgtable.c
> +++ b/arch/x86/mm/pgtable.c
> @@ -168,7 +168,7 @@ static int preallocate_pmds(struct mm_struct *mm, pmd_t *pmds[], int count)
> bool failed = false;
> gfp_t gfp = GFP_PGTABLE_USER;
>
> - if (mm == &init_mm)
> + if (mm_is_kernel(mm))
> gfp &= ~__GFP_ACCOUNT;
> gfp &= ~__GFP_HIGHMEM;
This hunk is probably fine.
> diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
> index 1023acadd8f8..5517cab8ad00 100644
> --- a/arch/x86/mm/tlb.c
> +++ b/arch/x86/mm/tlb.c
> @@ -594,7 +594,7 @@ void leave_mm(void)
> * This needs to happen before any other sanity checks due to
> * intel_idle's shenanigans.
> */
> - if (loaded_mm == &init_mm)
> + if (mm_is_kernel(loaded_mm))
> return;
This one is almost *certainly* buggy.
The efi_mm stuff uses leave_mm(). In fact, I think it's what's
responsible for switching the hardware back over to use the init_mm page
tables. If this check trips for init_mm, then the kernel will stay
running on efi_mm when it's not intended to.
Remember when I asked about whether there was going to be *a* kernel mm
or lots? This is where it starts to matter. It's outside the diff
context but the code here is basically:
if (loaded_mm == &init_mm)
return;
switch_mm(NULL, &init_mm, NULL);
So either all kernel mm's are equivalent or this code doesn't quite work.
> /* Warn if we're not lazy. */
> @@ -855,7 +855,7 @@ void switch_mm_irqs_off(struct mm_struct *unused, struct mm_struct *next,
> * cpu_tlbstate_shared.is_lazy whether or not to send an IPI.
> */
> if (IS_ENABLED(CONFIG_DEBUG_VM) &&
> - WARN_ON_ONCE(prev != &init_mm && !is_notrack_mm(prev) &&
> + WARN_ON_ONCE(!mm_is_kernel(prev) && !is_notrack_mm(prev) &&
> !cpumask_test_cpu(cpu, mm_cpumask(next))))
> cpumask_set_cpu(cpu, mm_cpumask(next));
>
> @@ -932,7 +932,8 @@ void switch_mm_irqs_off(struct mm_struct *unused, struct mm_struct *next,
> * This way switch_mm() must see the new tlb_gen or
> * flush_tlb_mm_range() must see the new loaded_mm, or both.
> */
> - if (next != &init_mm && !cpumask_test_cpu(cpu, mm_cpumask(next)))
> + if (!mm_is_kernel(next) &&
> + !cpumask_test_cpu(cpu, mm_cpumask(next)))
> cpumask_set_cpu(cpu, mm_cpumask(next));
> else
> smp_mb();
This one is interesting. It's basically saying that init_mm doesn't get
mm_cpumask() updates. That makes sense since it has special TLB flushing
rules. But what does this mean for efi_mm? Does it needs mm_cpumask()
updates?
^ permalink raw reply
* Re: [PATCH 14/22] mm: set page table page type when allocated
From: Vishal Moola @ 2026-07-14 15:16 UTC (permalink / raw)
To: Kevin Brodsky
Cc: linux-mm, Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Pasha Tatashin, Russell King,
Catalin Marinas, Will Deacon, Ryan Roberts, linux-arm-kernel,
Huacai Chen, loongarch, James E.J. Bottomley, Helge Deller,
linux-parisc, Madhavan Srinivasan, Michael Ellerman, linuxppc-dev,
Paul Walmsley, Palmer Dabbelt, Albert Ou, linux-riscv,
Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Gerald Schaefer,
linux-s390, David S. Miller, Andreas Larsson, sparclinux,
Richard Weinberger, Anton Ivanov, Johannes Berg, linux-um,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Peter Zijlstra, Ning Sun, x86,
tboot-devel, Ard Biesheuvel, Ilias Apalodimas, linux-efi,
Alistair Popple, Matthew Wilcox (Oracle), linux-kernel,
linux-arch
In-Reply-To: <20260714-remove_pgtable_cdtor-v1-14-44be8a7685d7@arm.com>
On Tue, Jul 14, 2026 at 03:04:03PM +0100, Kevin Brodsky wrote:
> As a step towards removing pagetable ctor/dtor calls for kernel
> mm's, move the page type updates from the ctor/dtor to
> pagetable_{alloc,free}.
Thanks for doing this patchset.
We should switch over from __folio_set_pgtable() to __SetPagePgtable()
in this patch. Ptdescs and folios should be treated as distinctly
independent of each other.
Eventually, we want to replace the memcg accounting as well, but
there's no existing API for that right now. Lets leave that as is for
now; this patchset is big enough already ;)
> __pagetable_ctor() is now empty so remove it;
> pagetable_{pud,p4d,pgd}_ctor() will be removed at a later stage.
>
> The ctor is normally called after pagetable_alloc() (and dtor before
> pagetable_free()) so this patch should have no functional effect in
> most cases. Where calls to ctor/dtor are currently missing (e.g.
> x86's split_large_page()), this patch will ensure the page type is
> set correctly.
>
> This patch is based on Matthew's earlier implementation linked
> below, with the difference that when freeing the page type is
> cleared in __pagetable_free(), meaning that the update is delayed
> until the pages are actually freed in the
> CONFIG_ASYNC_KERNEL_PGTABLE_FREE case. This shouldn't matter in
> practice.
>
> Suggested-by: "Matthew Wilcox (Oracle)" <willy@infradead.org>
> Link: https://lore.kernel.org/r/20251113140448.1814860-4-willy@infradead.org
> Signed-off-by: Kevin Brodsky <kevin.brodsky@arm.com>
> ---
> include/linux/mm.h | 17 ++---------------
> 1 file changed, 2 insertions(+), 15 deletions(-)
>
> diff --git a/include/linux/mm.h b/include/linux/mm.h
> index 361a0d7b74c5..94f0fb1c662a 100644
> --- a/include/linux/mm.h
> +++ b/include/linux/mm.h
> @@ -3684,6 +3684,7 @@ static inline struct ptdesc *pagetable_alloc_noprof(gfp_t gfp, unsigned int orde
> if (!page)
> return NULL;
>
> + __folio_set_pgtable(page_folio(page));
> lruvec_stat_add_folio(page_folio(page), NR_PAGETABLE);
>
> return page_ptdesc(page);
> @@ -3694,6 +3695,7 @@ static inline void __pagetable_free(struct ptdesc *pt)
> {
> struct page *page = ptdesc_page(pt);
>
> + __folio_clear_pgtable(page_folio(page));
> lruvec_stat_sub_folio(page_folio(page), NR_PAGETABLE);
>
> __free_pages(page, compound_order(page));
> @@ -3799,19 +3801,9 @@ static inline bool ptlock_init(struct ptdesc *ptdesc) { return true; }
> static inline void ptlock_free(struct ptdesc *ptdesc) {}
> #endif /* defined(CONFIG_SPLIT_PTE_PTLOCKS) */
>
> -static inline void __pagetable_ctor(struct ptdesc *ptdesc)
> -{
> - struct folio *folio = ptdesc_folio(ptdesc);
> -
> - __folio_set_pgtable(folio);
> -}
> -
> static inline void pagetable_dtor(struct ptdesc *ptdesc)
> {
> - struct folio *folio = ptdesc_folio(ptdesc);
> -
> ptlock_free(ptdesc);
> - __folio_clear_pgtable(folio);
> }
>
> static inline void pagetable_dtor_free(struct ptdesc *ptdesc)
> @@ -3825,7 +3817,6 @@ static inline bool pagetable_pte_ctor(struct mm_struct *mm,
> {
> if (!mm_is_kernel(mm) && !ptlock_init(ptdesc))
> return false;
> - __pagetable_ctor(ptdesc);
> return true;
> }
>
> @@ -3917,7 +3908,6 @@ static inline bool pagetable_pmd_ctor(struct mm_struct *mm,
> if (!mm_is_kernel(mm) && !pmd_ptlock_init(ptdesc))
> return false;
> ptdesc_pmd_pts_init(ptdesc);
> - __pagetable_ctor(ptdesc);
> return true;
> }
>
> @@ -3942,17 +3932,14 @@ static inline spinlock_t *pud_lock(struct mm_struct *mm, pud_t *pud)
>
> static inline void pagetable_pud_ctor(struct ptdesc *ptdesc)
> {
> - __pagetable_ctor(ptdesc);
> }
>
> static inline void pagetable_p4d_ctor(struct ptdesc *ptdesc)
> {
> - __pagetable_ctor(ptdesc);
> }
>
> static inline void pagetable_pgd_ctor(struct ptdesc *ptdesc)
> {
> - __pagetable_ctor(ptdesc);
> }
>
> extern void __init pagecache_init(void);
>
> --
> 2.51.2
>
^ permalink raw reply
* Re: [PATCH 19/22] x86/tboot: mark tboot_mm as a kernel mm
From: Dave Hansen @ 2026-07-14 15:19 UTC (permalink / raw)
To: Kevin Brodsky, linux-mm
Cc: Andrew Morton, David Hildenbrand, Lorenzo Stoakes,
Liam R. Howlett, Vlastimil Babka, Mike Rapoport,
Suren Baghdasaryan, Michal Hocko, Pasha Tatashin, Russell King,
Catalin Marinas, Will Deacon, Ryan Roberts, linux-arm-kernel,
Huacai Chen, loongarch, James E.J. Bottomley, Helge Deller,
linux-parisc, Madhavan Srinivasan, Michael Ellerman, linuxppc-dev,
Paul Walmsley, Palmer Dabbelt, Albert Ou, linux-riscv,
Heiko Carstens, Vasily Gorbik, Alexander Gordeev, Gerald Schaefer,
linux-s390, David S. Miller, Andreas Larsson, sparclinux,
Richard Weinberger, Anton Ivanov, Johannes Berg, linux-um,
Thomas Gleixner, Ingo Molnar, Borislav Petkov, Dave Hansen,
H. Peter Anvin, Andy Lutomirski, Peter Zijlstra, Ning Sun, x86,
tboot-devel, Ard Biesheuvel, Ilias Apalodimas, linux-efi,
Vishal Moola, Alistair Popple, Matthew Wilcox (Oracle),
linux-kernel, linux-arch
In-Reply-To: <20260714-remove_pgtable_cdtor-v1-19-44be8a7685d7@arm.com>
On 7/14/26 07:04, Kevin Brodsky wrote:
> tboot_mm is a kernel-owned address space used to build the
> identity map for tboot shutdown. Mark it with MMF_KERNEL so
> page table allocation and initialisation code treats its page tables
> as kernel page tables.
>
> Having marked tboot_mm as a kernel mm, we also need to convert
> pte_alloc_map() (user PTE) to pte_alloc_kernel() (kernel PTE), and
> drop the matching pte_unmap().
This makes me wonder whether MMF_KERNEL is the right way to mark these mms.
I think this series tries to cram too much into that one bit.
Using MMF_KERNEL to drive the page table accounting seems like a good
idea. It also seems like a good thing to make sure that those mm's don't
ever exit to userspace, for instance.
But I think it goes a step too far to say that all the special 'init_mm'
TLB flushing should also be common among all MMF_KERNEL mms.
My suggestion for now would be to just go after the page table
accounting alone. Don't mechanically replace mm==&mm_init checks.
^ permalink raw reply
* Re: [patch 1/4] entry: Rework syscall_audit_enter()
From: Radu Rendec @ 2026-07-14 15:23 UTC (permalink / raw)
To: Thomas Gleixner, LKML
Cc: Michal Suchánek, Michael Ellerman, Shrikanth Hegde,
linuxppc-dev, Huacai Chen, loongarch, Paul Walmsley,
Palmer Dabbelt, linux-riscv, Sven Schnelle, linux-s390, x86,
Mark Rutland, Jinjie Ruan, Magnus Lindholm,
Mukesh Kumar Chaurasiya (IBM), Jonathan Corbet
In-Reply-To: <20260712141346.576865340@kernel.org>
On Sun, 2026-07-12 at 23:25 +0200, Thomas Gleixner wrote:
> Move it out of line and let it reread the syscall number on it's own. That
> makes the low level entry code denser and allows to move the reread to the
> call site of syscall_trace_enter() once the tracer is fixed up.
>
> Signed-off-by: Thomas Gleixner <tglx@kernel.org>
> ---
> include/linux/entry-common.h | 14 +++-----------
> kernel/entry/syscall-common.c | 10 ++++++++++
> 2 files changed, 13 insertions(+), 11 deletions(-)
>
> --- a/include/linux/entry-common.h
> +++ b/include/linux/entry-common.h
> @@ -60,16 +60,7 @@ static __always_inline bool arch_ptrace_
>
> long trace_syscall_enter(struct pt_regs *regs, long syscall);
> void trace_syscall_exit(struct pt_regs *regs, long ret);
> -
> -static inline void syscall_enter_audit(struct pt_regs *regs, long syscall)
> -{
> - if (unlikely(audit_context())) {
> - unsigned long args[6];
> -
> - syscall_get_arguments(current, regs, args);
> - audit_syscall_entry(syscall, args[0], args[1], args[2], args[3]);
> - }
> -}
> +void syscall_enter_audit(struct pt_regs *regs);
>
> static __always_inline long syscall_trace_enter(struct pt_regs *regs, unsigned long work,
> long syscall)
> @@ -111,7 +102,8 @@ static __always_inline long syscall_trac
> if (unlikely(work & SYSCALL_WORK_SYSCALL_TRACEPOINT))
> syscall = trace_syscall_enter(regs, syscall);
>
> - syscall_enter_audit(regs, syscall);
> + if (unlikely(audit_context()))
> + syscall_enter_audit(regs);
>
> return syscall;
> }
> --- a/kernel/entry/syscall-common.c
> +++ b/kernel/entry/syscall-common.c
> @@ -1,5 +1,6 @@
> // SPDX-License-Identifier: GPL-2.0
>
> +#include <linux/audit.h>
> #include <linux/entry-common.h>
>
> #define CREATE_TRACE_POINTS
> @@ -21,3 +22,12 @@ void trace_syscall_exit(struct pt_regs *
> {
> trace_sys_exit(regs, ret);
> }
> +
> +void syscall_enter_audit(struct pt_regs *regs)
> +{
> + long syscall = syscall_get_nr(current, regs);
> + unsigned long args[6];
> +
> + syscall_get_arguments(current, regs, args);
> + __audit_syscall_entry(syscall, args[0], args[1], args[2], args[3]);
> +}
Reviewed-by: Radu Rendec <radu@rendec.net>
^ permalink raw reply
* Re: [patch 2/4] entry: Rework trace_syscall_enter()
From: Radu Rendec @ 2026-07-14 15:28 UTC (permalink / raw)
To: Thomas Gleixner, LKML
Cc: Michal Suchánek, Michael Ellerman, Shrikanth Hegde,
linuxppc-dev, Huacai Chen, loongarch, Paul Walmsley,
Palmer Dabbelt, linux-riscv, Sven Schnelle, linux-s390, x86,
Mark Rutland, Jinjie Ruan, Magnus Lindholm,
Mukesh Kumar Chaurasiya (IBM), Jonathan Corbet
In-Reply-To: <20260712141346.639115923@kernel.org>
On Sun, 2026-07-12 at 23:25 +0200, Thomas Gleixner wrote:
> Reread the syscall number from pt_regs and stop returning the eventually
> modified syscall number.
>
> That moves the reread to the end of the syscall_trace_enter() and prepares
> for moving it to the call site.
>
> No functional change.
>
> Signed-off-by: Thomas Gleixner <tglx@kernel.org>
> ---
> include/linux/entry-common.h | 10 ++++------
> kernel/entry/syscall-common.c | 9 ++-------
> 2 files changed, 6 insertions(+), 13 deletions(-)
>
> --- a/include/linux/entry-common.h
> +++ b/include/linux/entry-common.h
> @@ -58,7 +58,7 @@ static __always_inline bool arch_ptrace_
> }
> #endif
>
> -long trace_syscall_enter(struct pt_regs *regs, long syscall);
> +void trace_syscall_enter(struct pt_regs *regs);
> void trace_syscall_exit(struct pt_regs *regs, long ret);
> void syscall_enter_audit(struct pt_regs *regs);
>
> @@ -96,16 +96,14 @@ static __always_inline long syscall_trac
> return -1L;
> }
>
> - /* Either of the above might have changed the syscall number */
> - syscall = syscall_get_nr(current, regs);
> -
> if (unlikely(work & SYSCALL_WORK_SYSCALL_TRACEPOINT))
> - syscall = trace_syscall_enter(regs, syscall);
> + trace_syscall_enter(regs);
>
> if (unlikely(audit_context()))
> syscall_enter_audit(regs);
>
> - return syscall;
> + /* Either of the above might have changed the syscall number */
nit: "Either" implies two items. I would rephrase it to "Any" to make
things clearer.
> + return syscall_get_nr(current, regs);
> }
>
> /**
> --- a/kernel/entry/syscall-common.c
> +++ b/kernel/entry/syscall-common.c
> @@ -8,14 +8,9 @@
>
> /* Out of line to prevent tracepoint code duplication */
>
> -long trace_syscall_enter(struct pt_regs *regs, long syscall)
> +void trace_syscall_enter(struct pt_regs *regs)
> {
> - trace_sys_enter(regs, syscall);
> - /*
> - * Probes or BPF hooks in the tracepoint may have changed the
> - * system call number. Reread it.
> - */
> - return syscall_get_nr(current, regs);
> + trace_sys_enter(regs, syscall_get_nr(current, regs));
> }
>
> void trace_syscall_exit(struct pt_regs *regs, long ret)
With the above,
Reviewed-by: Radu Rendec <radu@rendec.net>
^ permalink raw reply
* Re: [patch 3/4] entry: Make return type of syscall_trace_enter() bool
From: Radu Rendec @ 2026-07-14 15:41 UTC (permalink / raw)
To: Thomas Gleixner, LKML
Cc: Michal Suchánek, Michael Ellerman, Shrikanth Hegde,
linuxppc-dev, Huacai Chen, loongarch, Paul Walmsley,
Palmer Dabbelt, linux-riscv, Sven Schnelle, linux-s390, x86,
Mark Rutland, Jinjie Ruan, Magnus Lindholm,
Mukesh Kumar Chaurasiya (IBM), Jonathan Corbet
In-Reply-To: <20260712141346.699072205@kernel.org>
On Sun, 2026-07-12 at 23:25 +0200, Thomas Gleixner wrote:
> From: Thomas Gleixner <tglx@kernel.org>
>
> This prepares for changing the return types of
> syscall_enter_from_user_mode[_work]() to bool, which in turn separates the
> decision of invoking the syscall from the syscall number, which might have
> been changed in the call by ptrace, seccomp, tracing.
>
> Signed-off-by: Thomas Gleixner <tglx@kernel.org>
> ---
> include/linux/entry-common.h | 18 +++++++++++-------
> 1 file changed, 11 insertions(+), 7 deletions(-)
> --- a/include/linux/entry-common.h
> +++ b/include/linux/entry-common.h
> @@ -72,7 +72,7 @@ static __always_inline long syscall_trac
> */
> if (work & SYSCALL_WORK_SYSCALL_USER_DISPATCH) {
> if (syscall_user_dispatch(regs))
> - return -1L;
> + return false;
> }
>
> /*
> @@ -87,13 +87,13 @@ static __always_inline long syscall_trac
> if (work & (SYSCALL_WORK_SYSCALL_TRACE | SYSCALL_WORK_SYSCALL_EMU)) {
> if (!arch_ptrace_report_syscall_permit_entry(regs) ||
> (work & SYSCALL_WORK_SYSCALL_EMU))
> - return -1L;
> + return false;
> }
>
> /* Do seccomp after ptrace, to catch any tracer changes. */
> if (work & SYSCALL_WORK_SECCOMP) {
> if (!__seccomp_permit_syscall())
> - return -1L;
> + return false;
> }
>
> if (unlikely(work & SYSCALL_WORK_SYSCALL_TRACEPOINT))
> @@ -102,8 +102,7 @@ static __always_inline long syscall_trac
> if (unlikely(audit_context()))
> syscall_enter_audit(regs);
>
> - /* Either of the above might have changed the syscall number */
> - return syscall_get_nr(current, regs);
> + return true;
> }
>
> /**
> @@ -133,8 +132,13 @@ static __always_inline long syscall_ente
> {
> unsigned long work = READ_ONCE(current_thread_info()->syscall_work);
>
> - if (work & SYSCALL_WORK_ENTER)
> - syscall = syscall_trace_enter(regs, work, syscall);
> + if (work & SYSCALL_WORK_ENTER) {
> + if (!syscall_trace_enter(regs, work, syscall))
> + return -1L;
> +
> + /* Reread the syscall number as it might have been modified */
nit: I would add "in the call above by ptrace, seccomp, tracing" - which
is actually in your commit message, but would make it immediately obvious
when reading the code.
> + syscall = syscall_get_nr(current, regs);
> + }
>
> return syscall;
> }
Reviewed-by: Radu Rendec <radu@rendec.net>
^ permalink raw reply
* RE: [PATCH v7 11/22] dma-pool: track decrypted atomic pools and select them via attrs
From: Michael Kelley @ 2026-07-14 15:46 UTC (permalink / raw)
To: Jason Gunthorpe, Aneesh Kumar K.V
Cc: iommu@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
linux-kernel@vger.kernel.org, linux-coco@lists.linux.dev,
Robin Murphy, Marek Szyprowski, Will Deacon, Marc Zyngier,
Steven Price, Suzuki K Poulose, Catalin Marinas, Jiri Pirko,
Mostafa Saleh, Petr Tesarik, Alexey Kardashevskiy, Dan Williams,
Xu Yilun, linuxppc-dev@lists.ozlabs.org,
linux-s390@vger.kernel.org, Madhavan Srinivasan, Michael Ellerman,
Nicholas Piggin, Christophe Leroy (CS GROUP), Alexander Gordeev,
Gerald Schaefer, Heiko Carstens, Vasily Gorbik,
Christian Borntraeger, Sven Schnelle, x86@kernel.org, Jiri Pirko,
Michael Kelley
In-Reply-To: <20260714122504.GG3133966@ziepe.ca>
From: Jason Gunthorpe <jgg@ziepe.ca> Sent: Tuesday, July 14, 2026 5:25 AM
>
> On Tue, Jul 14, 2026 at 09:32:27AM +0530, Aneesh Kumar K.V wrote:
>
> > If we want to warn about such failures, we should add the warning
> > consistently across the code. We may also want to handle decrypt
> > failures by encrypting the page again to avoid leaking it.
> >
> > I will work on that as a tree-wide change in a separate patch.
>
> IMHO the WARN should be inside set_memory_encrypted(), and maybe it
> should be a BUG_ON...
There was a discussion about this a while back. The decision was
to embed the WARNs, and that callers should not output any error
messages upon failure.
The x86 implementation of set_memory_decrypted() and
set_memory_encrypted() has an embedded WARN_ON_ONCE()
that triggers on a failure. The arm64 realm encrypt/decrypt ops also
have an embedded WARN().
The pkvm encrypt/decrypt ops do not, so that's maybe where it should
be added.
Michael
^ permalink raw reply
* Re: [PATCH 01/14] ASoC: codecs: NeoFidelity: repair the kernel-doc format
From: Randy Dunlap @ 2026-07-14 15:57 UTC (permalink / raw)
To: Mark Brown
Cc: linux-sound, Jaroslav Kysela, Takashi Iwai, Shengjiu Wang,
Xiubo Li, Fabio Estevam, Nicolin Chen, linuxppc-dev,
Charles Keepax, Maciej Strozek, Bard Liao, Pierre-Louis Bossart,
patches, Srinivas Kandagatla, linux-arm-msm, Liam Girdwood
In-Reply-To: <4eddcb03-3c2a-4ef4-8825-e750e8109476@sirena.org.uk>
On 7/14/26 3:20 AM, Mark Brown wrote:
> On Mon, Jul 13, 2026 at 06:44:32PM -0700, Randy Dunlap wrote:
>> Don't use "/**" for a non-kernel-doc comment.
>> Use kernel-doc notation to document the parameters and return value of
>> ntpfw_load().
>
> As mentioned in submitting-patches.rst when submitting a patch series
> you should supply a cover letter for that patch series which describes
> the overall content of the series. This helps people understand what
> they are looking at and how things fit together.
Are you saying that my cover letter was insufficient?
https://lore.kernel.org/all/20260714014445.569992-1-rdunlap@infradead.org/
--
~Randy
^ permalink raw reply
* Re: [PATCH 01/14] ASoC: codecs: NeoFidelity: repair the kernel-doc format
From: Randy Dunlap @ 2026-07-14 16:02 UTC (permalink / raw)
To: Mark Brown
Cc: linux-sound, Jaroslav Kysela, Takashi Iwai, Shengjiu Wang,
Xiubo Li, Fabio Estevam, Nicolin Chen, linuxppc-dev,
Charles Keepax, Maciej Strozek, Bard Liao, Pierre-Louis Bossart,
patches, Srinivas Kandagatla, linux-arm-msm, Liam Girdwood
In-Reply-To: <1a885ccd-77bb-4537-89c9-6b031c2f3812@infradead.org>
On 7/14/26 8:57 AM, Randy Dunlap wrote:
>
>
> On 7/14/26 3:20 AM, Mark Brown wrote:
>> On Mon, Jul 13, 2026 at 06:44:32PM -0700, Randy Dunlap wrote:
>>> Don't use "/**" for a non-kernel-doc comment.
>>> Use kernel-doc notation to document the parameters and return value of
>>> ntpfw_load().
>>
>> As mentioned in submitting-patches.rst when submitting a patch series
>> you should supply a cover letter for that patch series which describes
>> the overall content of the series. This helps people understand what
>> they are looking at and how things fit together.
>
> Are you saying that my cover letter was insufficient?
>
> https://lore.kernel.org/all/20260714014445.569992-1-rdunlap@infradead.org/
>
Ah, somehow I missing sending that one directly to you. My bad.
Should I resend the series?
thanks.
--
~Randy
^ permalink raw reply
* [PATCH 1/3] x86/mce: Use __DEVICE_ATTR() macro to initialize dev_ext_attribute
From: Thomas Weißschuh @ 2026-07-14 16:51 UTC (permalink / raw)
To: Tony Luck, Borislav Petkov, Thomas Gleixner, Ingo Molnar,
Dave Hansen, x86, H. Peter Anvin, Will Deacon, Mark Rutland,
Jonathan Cameron, Yushan Wang, Jijie Shao, Khuong Dinh,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Greg Kroah-Hartman,
Rafael J. Wysocki, Danilo Krummrich
Cc: linux-edac, linux-kernel, linux-arm-kernel, linux-perf-users,
linux-cxl, linux-arm-msm, linuxppc-dev, driver-core,
Thomas Weißschuh
In-Reply-To: <20260714-sysfs-const-attr-dev_ext_attr-v1-0-6b2c0435d621@weissschuh.net>
The upcoming constification of the device_show_int() and
device_show_bool() signatures requires the users to handle the
transition automatically.
Switch to the __DEVICE_ATTR() macro which can do this.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
arch/x86/kernel/cpu/mce/core.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/arch/x86/kernel/cpu/mce/core.c b/arch/x86/kernel/cpu/mce/core.c
index 9bba1e2f03af..7fc9aa9e2ec9 100644
--- a/arch/x86/kernel/cpu/mce/core.c
+++ b/arch/x86/kernel/cpu/mce/core.c
@@ -2621,17 +2621,17 @@ static DEVICE_BOOL_ATTR(dont_log_ce, 0644, mca_cfg.dont_log_ce);
static DEVICE_BOOL_ATTR(print_all, 0644, mca_cfg.print_all);
static struct dev_ext_attribute dev_attr_check_interval = {
- __ATTR(check_interval, 0644, device_show_int, store_int_with_restart),
+ __DEVICE_ATTR(check_interval, 0644, device_show_int, store_int_with_restart),
&check_interval
};
static struct dev_ext_attribute dev_attr_ignore_ce = {
- __ATTR(ignore_ce, 0644, device_show_bool, set_ignore_ce),
+ __DEVICE_ATTR(ignore_ce, 0644, device_show_bool, set_ignore_ce),
&mca_cfg.ignore_ce
};
static struct dev_ext_attribute dev_attr_cmci_disabled = {
- __ATTR(cmci_disabled, 0644, device_show_bool, set_cmci_disabled),
+ __DEVICE_ATTR(cmci_disabled, 0644, device_show_bool, set_cmci_disabled),
&mca_cfg.cmci_disabled
};
--
2.55.0
^ permalink raw reply related
* [PATCH 2/3] drivers: perf: Use __DEVICE_ATTR() macro to initialize dev_ext_attribute
From: Thomas Weißschuh @ 2026-07-14 16:51 UTC (permalink / raw)
To: Tony Luck, Borislav Petkov, Thomas Gleixner, Ingo Molnar,
Dave Hansen, x86, H. Peter Anvin, Will Deacon, Mark Rutland,
Jonathan Cameron, Yushan Wang, Jijie Shao, Khuong Dinh,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Greg Kroah-Hartman,
Rafael J. Wysocki, Danilo Krummrich
Cc: linux-edac, linux-kernel, linux-arm-kernel, linux-perf-users,
linux-cxl, linux-arm-msm, linuxppc-dev, driver-core,
Thomas Weißschuh
In-Reply-To: <20260714-sysfs-const-attr-dev_ext_attr-v1-0-6b2c0435d621@weissschuh.net>
The upcoming constification of the device_show_*() callback
signatures requires the users to handle the transition automatically.
Switch to the __DEVICE_ATTR() macro which can do this.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
drivers/perf/arm-cci.c | 2 +-
drivers/perf/arm-ccn.c | 2 +-
drivers/perf/arm_cspmu/arm_cspmu.h | 2 +-
drivers/perf/arm_dsu_pmu.c | 2 +-
drivers/perf/cxl_pmu.c | 10 +++++-----
drivers/perf/fujitsu_uncore_pmu.c | 2 +-
drivers/perf/hisilicon/hisi_pcie_pmu.c | 2 +-
drivers/perf/hisilicon/hisi_uncore_pmu.h | 6 +++---
drivers/perf/hisilicon/hns3_pmu.c | 6 +++---
drivers/perf/nvidia_t410_c2c_pmu.c | 2 +-
drivers/perf/nvidia_t410_cmem_latency_pmu.c | 12 ++++++------
drivers/perf/qcom_l3_pmu.c | 8 ++++----
drivers/perf/xgene_pmu.c | 2 +-
13 files changed, 29 insertions(+), 29 deletions(-)
diff --git a/drivers/perf/arm-cci.c b/drivers/perf/arm-cci.c
index 1cc3214d6b6d..374a00ae4e48 100644
--- a/drivers/perf/arm-cci.c
+++ b/drivers/perf/arm-cci.c
@@ -132,7 +132,7 @@ static ssize_t __maybe_unused cci_pmu_event_show(struct device *dev,
#define CCI_EXT_ATTR_ENTRY(_name, _func, _config) \
&((struct dev_ext_attribute[]) { \
- { __ATTR(_name, S_IRUGO, _func, NULL), (void *)_config } \
+ { __DEVICE_ATTR(_name, S_IRUGO, _func, NULL), (void *)_config } \
})[0].attr.attr
#define CCI_FORMAT_EXT_ATTR_ENTRY(_name, _config) \
diff --git a/drivers/perf/arm-ccn.c b/drivers/perf/arm-ccn.c
index 8af3563fdf60..955cb5c2b77b 100644
--- a/drivers/perf/arm-ccn.c
+++ b/drivers/perf/arm-ccn.c
@@ -217,7 +217,7 @@ static void arm_ccn_pmu_config_set(u64 *config, u32 node_xp, u32 type, u32 port)
#define CCN_FORMAT_ATTR(_name, _config) \
struct dev_ext_attribute arm_ccn_pmu_format_attr_##_name = \
- { __ATTR(_name, S_IRUGO, device_show_string, \
+ { __DEVICE_ATTR(_name, S_IRUGO, device_show_string, \
NULL), _config }
static CCN_FORMAT_ATTR(node, "config:0-7");
diff --git a/drivers/perf/arm_cspmu/arm_cspmu.h b/drivers/perf/arm_cspmu/arm_cspmu.h
index 3fc5c8d77266..841b04ea02a4 100644
--- a/drivers/perf/arm_cspmu/arm_cspmu.h
+++ b/drivers/perf/arm_cspmu/arm_cspmu.h
@@ -23,7 +23,7 @@
#define ARM_CSPMU_EXT_ATTR(_name, _func, _config) \
(&((struct dev_ext_attribute[]){ \
{ \
- .attr = __ATTR(_name, 0444, _func, NULL), \
+ .attr = __DEVICE_ATTR(_name, 0444, _func, NULL),\
.var = (void *)_config \
} \
})[0].attr.attr)
diff --git a/drivers/perf/arm_dsu_pmu.c b/drivers/perf/arm_dsu_pmu.c
index 32b0dd7c693b..1d7def95645f 100644
--- a/drivers/perf/arm_dsu_pmu.c
+++ b/drivers/perf/arm_dsu_pmu.c
@@ -69,7 +69,7 @@
#define DSU_EXT_ATTR(_name, _func, _config) \
(&((struct dev_ext_attribute[]) { \
{ \
- .attr = __ATTR(_name, 0444, _func, NULL), \
+ .attr = __DEVICE_ATTR(_name, 0444, _func, NULL),\
.var = (void *)_config \
} \
})[0].attr.attr)
diff --git a/drivers/perf/cxl_pmu.c b/drivers/perf/cxl_pmu.c
index 68a54d97d2a8..4ab3360a9004 100644
--- a/drivers/perf/cxl_pmu.c
+++ b/drivers/perf/cxl_pmu.c
@@ -209,11 +209,11 @@ static int cxl_pmu_parse_caps(struct device *dev, struct cxl_pmu_info *info)
}
#define CXL_PMU_FORMAT_ATTR(_name, _format)\
- (&((struct dev_ext_attribute[]) { \
- { \
- .attr = __ATTR(_name, 0444, device_show_string, NULL), \
- .var = (void *)_format \
- } \
+ (&((struct dev_ext_attribute[]) { \
+ { \
+ .attr = __DEVICE_ATTR(_name, 0444, device_show_string, NULL), \
+ .var = (void *)_format \
+ } \
})[0].attr.attr)
enum {
diff --git a/drivers/perf/fujitsu_uncore_pmu.c b/drivers/perf/fujitsu_uncore_pmu.c
index c3c6f56474ad..b83fdaf59324 100644
--- a/drivers/perf/fujitsu_uncore_pmu.c
+++ b/drivers/perf/fujitsu_uncore_pmu.c
@@ -292,7 +292,7 @@ static void fujitsu_uncore_event_read(struct perf_event *event)
#define UNCORE_PMU_FORMAT_ATTR(_name, _config) \
(&((struct dev_ext_attribute[]) { \
- { .attr = __ATTR(_name, 0444, device_show_string, NULL), \
+ { .attr = __DEVICE_ATTR(_name, 0444, device_show_string, NULL), \
.var = (void *)_config, } \
})[0].attr.attr)
diff --git a/drivers/perf/hisilicon/hisi_pcie_pmu.c b/drivers/perf/hisilicon/hisi_pcie_pmu.c
index c5394d007b61..2dc19b7c8cbf 100644
--- a/drivers/perf/hisilicon/hisi_pcie_pmu.c
+++ b/drivers/perf/hisilicon/hisi_pcie_pmu.c
@@ -110,7 +110,7 @@ static ssize_t hisi_pcie_event_sysfs_show(struct device *dev, struct device_attr
#define HISI_PCIE_PMU_FORMAT_ATTR(_name, _format) \
(&((struct dev_ext_attribute[]){ \
- { .attr = __ATTR(_name, 0444, device_show_string, NULL), \
+ { .attr = __DEVICE_ATTR(_name, 0444, device_show_string, NULL),\
.var = (void *)_format } \
})[0].attr.attr)
diff --git a/drivers/perf/hisilicon/hisi_uncore_pmu.h b/drivers/perf/hisilicon/hisi_uncore_pmu.h
index 3ffe6acda653..a4cb9ed7ea20 100644
--- a/drivers/perf/hisilicon/hisi_uncore_pmu.h
+++ b/drivers/perf/hisilicon/hisi_uncore_pmu.h
@@ -27,9 +27,9 @@
#define HISI_MAX_COUNTERS 0x18
#define to_hisi_pmu(p) (container_of(p, struct hisi_pmu, pmu))
-#define HISI_PMU_ATTR(_name, _func, _config) \
- (&((struct dev_ext_attribute[]) { \
- { __ATTR(_name, 0444, _func, NULL), (void *)_config } \
+#define HISI_PMU_ATTR(_name, _func, _config) \
+ (&((struct dev_ext_attribute[]) { \
+ { __DEVICE_ATTR(_name, 0444, _func, NULL), (void *)_config } \
})[0].attr.attr)
#define HISI_PMU_FORMAT_ATTR(_name, _config) \
diff --git a/drivers/perf/hisilicon/hns3_pmu.c b/drivers/perf/hisilicon/hns3_pmu.c
index c157f3572cae..88a1129e9b90 100644
--- a/drivers/perf/hisilicon/hns3_pmu.c
+++ b/drivers/perf/hisilicon/hns3_pmu.c
@@ -405,9 +405,9 @@ static ssize_t hns3_pmu_filter_mode_show(struct device *dev,
return len;
}
-#define HNS3_PMU_ATTR(_name, _func, _config) \
- (&((struct dev_ext_attribute[]) { \
- { __ATTR(_name, 0444, _func, NULL), (void *)_config } \
+#define HNS3_PMU_ATTR(_name, _func, _config) \
+ (&((struct dev_ext_attribute[]) { \
+ { __DEVICE_ATTR(_name, 0444, _func, NULL), (void *)_config } \
})[0].attr.attr)
#define HNS3_PMU_FORMAT_ATTR(_name, _format) \
diff --git a/drivers/perf/nvidia_t410_c2c_pmu.c b/drivers/perf/nvidia_t410_c2c_pmu.c
index 411987153ff3..930cb3e8aad2 100644
--- a/drivers/perf/nvidia_t410_c2c_pmu.c
+++ b/drivers/perf/nvidia_t410_c2c_pmu.c
@@ -545,7 +545,7 @@ static struct attribute_group nv_c2c_pmu_peer_attr_group = {
#define NV_C2C_PMU_EXT_ATTR(_name, _func, _config) \
(&((struct dev_ext_attribute[]){ \
{ \
- .attr = __ATTR(_name, 0444, _func, NULL), \
+ .attr = __DEVICE_ATTR(_name, 0444, _func, NULL),\
.var = (void *)_config \
} \
})[0].attr.attr)
diff --git a/drivers/perf/nvidia_t410_cmem_latency_pmu.c b/drivers/perf/nvidia_t410_cmem_latency_pmu.c
index acb8f5571522..d6e02b70a7cf 100644
--- a/drivers/perf/nvidia_t410_cmem_latency_pmu.c
+++ b/drivers/perf/nvidia_t410_cmem_latency_pmu.c
@@ -435,12 +435,12 @@ static struct attribute_group cmem_lat_pmu_identifier_attr_group = {
/* Format attributes. */
-#define NV_PMU_EXT_ATTR(_name, _func, _config) \
- (&((struct dev_ext_attribute[]){ \
- { \
- .attr = __ATTR(_name, 0444, _func, NULL), \
- .var = (void *)_config \
- } \
+#define NV_PMU_EXT_ATTR(_name, _func, _config) \
+ (&((struct dev_ext_attribute[]){ \
+ { \
+ .attr = __DEVICE_ATTR(_name, 0444, _func, NULL), \
+ .var = (void *)_config \
+ } \
})[0].attr.attr)
static struct attribute *cmem_lat_pmu_formats[] = {
diff --git a/drivers/perf/qcom_l3_pmu.c b/drivers/perf/qcom_l3_pmu.c
index 66e6cabd6fff..d5aa6ace847a 100644
--- a/drivers/perf/qcom_l3_pmu.c
+++ b/drivers/perf/qcom_l3_pmu.c
@@ -609,10 +609,10 @@ static void qcom_l3_cache__event_read(struct perf_event *event)
/* formats */
-#define L3CACHE_PMU_FORMAT_ATTR(_name, _config) \
- (&((struct dev_ext_attribute[]) { \
- { .attr = __ATTR(_name, 0444, device_show_string, NULL), \
- .var = (void *) _config, } \
+#define L3CACHE_PMU_FORMAT_ATTR(_name, _config) \
+ (&((struct dev_ext_attribute[]) { \
+ { .attr = __DEVICE_ATTR(_name, 0444, device_show_string, NULL), \
+ .var = (void *) _config, } \
})[0].attr.attr)
static struct attribute *qcom_l3_cache_pmu_formats[] = {
diff --git a/drivers/perf/xgene_pmu.c b/drivers/perf/xgene_pmu.c
index 33b5497bdc06..3f23611fd4c7 100644
--- a/drivers/perf/xgene_pmu.c
+++ b/drivers/perf/xgene_pmu.c
@@ -164,7 +164,7 @@ enum xgene_pmu_dev_type {
*/
#define XGENE_PMU_FORMAT_ATTR(_name, _config) \
(&((struct dev_ext_attribute[]) { \
- { .attr = __ATTR(_name, S_IRUGO, device_show_string, NULL), \
+ { .attr = __DEVICE_ATTR(_name, S_IRUGO, device_show_string, NULL), \
.var = (void *) _config, } \
})[0].attr.attr)
--
2.55.0
^ permalink raw reply related
* [PATCH 0/3] driver core: Constify the signature of device_show/store_*()
From: Thomas Weißschuh @ 2026-07-14 16:51 UTC (permalink / raw)
To: Tony Luck, Borislav Petkov, Thomas Gleixner, Ingo Molnar,
Dave Hansen, x86, H. Peter Anvin, Will Deacon, Mark Rutland,
Jonathan Cameron, Yushan Wang, Jijie Shao, Khuong Dinh,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Greg Kroah-Hartman,
Rafael J. Wysocki, Danilo Krummrich
Cc: linux-edac, linux-kernel, linux-arm-kernel, linux-perf-users,
linux-cxl, linux-arm-msm, linuxppc-dev, driver-core,
Thomas Weißschuh
Prepare for the constification of 'struct dev_ext_attribute' by changing
the signature of the standard callback functions.
Intended for the driver-core tree.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
Thomas Weißschuh (3):
x86/mce: Use __DEVICE_ATTR() macro to initialize dev_ext_attribute
drivers: perf: Use __DEVICE_ATTR() macro to initialize dev_ext_attribute
driver core: Constify the signature of device_show/store_*()
arch/powerpc/perf/hv-24x7.c | 2 +-
arch/x86/kernel/cpu/mce/core.c | 6 +++---
drivers/base/core.c | 30 ++++++++++++++---------------
drivers/perf/arm-cci.c | 2 +-
drivers/perf/arm-ccn.c | 2 +-
drivers/perf/arm_cspmu/arm_cspmu.h | 2 +-
drivers/perf/arm_dsu_pmu.c | 2 +-
drivers/perf/cxl_pmu.c | 10 +++++-----
drivers/perf/fujitsu_uncore_pmu.c | 2 +-
drivers/perf/hisilicon/hisi_pcie_pmu.c | 2 +-
drivers/perf/hisilicon/hisi_uncore_pmu.h | 6 +++---
drivers/perf/hisilicon/hns3_pmu.c | 6 +++---
drivers/perf/nvidia_t410_c2c_pmu.c | 2 +-
drivers/perf/nvidia_t410_cmem_latency_pmu.c | 12 ++++++------
drivers/perf/qcom_l3_pmu.c | 8 ++++----
drivers/perf/xgene_pmu.c | 2 +-
include/linux/device.h | 14 +++++++-------
17 files changed, 55 insertions(+), 55 deletions(-)
---
base-commit: 1160c2208fab4eaf4a32d738f83474c32c3a6944
change-id: 20260712-sysfs-const-attr-dev_ext_attr-dbf669fdfd4e
Best regards,
--
Thomas Weißschuh <linux@weissschuh.net>
^ permalink raw reply
* [PATCH 3/3] driver core: Constify the signature of device_show/store_*()
From: Thomas Weißschuh @ 2026-07-14 16:51 UTC (permalink / raw)
To: Tony Luck, Borislav Petkov, Thomas Gleixner, Ingo Molnar,
Dave Hansen, x86, H. Peter Anvin, Will Deacon, Mark Rutland,
Jonathan Cameron, Yushan Wang, Jijie Shao, Khuong Dinh,
Madhavan Srinivasan, Michael Ellerman, Nicholas Piggin,
Christophe Leroy (CS GROUP), Greg Kroah-Hartman,
Rafael J. Wysocki, Danilo Krummrich
Cc: linux-edac, linux-kernel, linux-arm-kernel, linux-perf-users,
linux-cxl, linux-arm-msm, linuxppc-dev, driver-core,
Thomas Weißschuh
In-Reply-To: <20260714-sysfs-const-attr-dev_ext_attr-v1-0-6b2c0435d621@weissschuh.net>
Prepare for the constification of 'struct dev_ext_attribute' by changing
the signature of the standard callback functions.
Signed-off-by: Thomas Weißschuh <linux@weissschuh.net>
---
arch/powerpc/perf/hv-24x7.c | 2 +-
drivers/base/core.c | 30 +++++++++++++++---------------
include/linux/device.h | 14 +++++++-------
3 files changed, 23 insertions(+), 23 deletions(-)
diff --git a/arch/powerpc/perf/hv-24x7.c b/arch/powerpc/perf/hv-24x7.c
index abb4cfb11fcc..c0abac00e026 100644
--- a/arch/powerpc/perf/hv-24x7.c
+++ b/arch/powerpc/perf/hv-24x7.c
@@ -462,7 +462,7 @@ static struct attribute *device_str_attr_create_(char *name, char *str)
attr->var = str;
attr->attr.attr.name = name;
attr->attr.attr.mode = 0444;
- attr->attr.show = device_show_string;
+ attr->attr.show_const = device_show_string;
return &attr->attr.attr;
}
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 4d026682944f..649b8a126920 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -2513,13 +2513,13 @@ static const struct sysfs_ops dev_sysfs_ops = {
.store = dev_attr_store,
};
-#define to_ext_attr(x) container_of(x, struct dev_ext_attribute, attr)
+#define to_ext_attr(x) container_of_const(x, struct dev_ext_attribute, attr)
ssize_t device_store_ulong(struct device *dev,
- struct device_attribute *attr,
+ const struct device_attribute *attr,
const char *buf, size_t size)
{
- struct dev_ext_attribute *ea = to_ext_attr(attr);
+ const struct dev_ext_attribute *ea = to_ext_attr(attr);
int ret;
unsigned long new;
@@ -2533,19 +2533,19 @@ ssize_t device_store_ulong(struct device *dev,
EXPORT_SYMBOL_GPL(device_store_ulong);
ssize_t device_show_ulong(struct device *dev,
- struct device_attribute *attr,
+ const struct device_attribute *attr,
char *buf)
{
- struct dev_ext_attribute *ea = to_ext_attr(attr);
+ const struct dev_ext_attribute *ea = to_ext_attr(attr);
return sysfs_emit(buf, "%lx\n", *(unsigned long *)(ea->var));
}
EXPORT_SYMBOL_GPL(device_show_ulong);
ssize_t device_store_int(struct device *dev,
- struct device_attribute *attr,
+ const struct device_attribute *attr,
const char *buf, size_t size)
{
- struct dev_ext_attribute *ea = to_ext_attr(attr);
+ const struct dev_ext_attribute *ea = to_ext_attr(attr);
int ret;
long new;
@@ -2562,19 +2562,19 @@ ssize_t device_store_int(struct device *dev,
EXPORT_SYMBOL_GPL(device_store_int);
ssize_t device_show_int(struct device *dev,
- struct device_attribute *attr,
+ const struct device_attribute *attr,
char *buf)
{
- struct dev_ext_attribute *ea = to_ext_attr(attr);
+ const struct dev_ext_attribute *ea = to_ext_attr(attr);
return sysfs_emit(buf, "%d\n", *(int *)(ea->var));
}
EXPORT_SYMBOL_GPL(device_show_int);
-ssize_t device_store_bool(struct device *dev, struct device_attribute *attr,
+ssize_t device_store_bool(struct device *dev, const struct device_attribute *attr,
const char *buf, size_t size)
{
- struct dev_ext_attribute *ea = to_ext_attr(attr);
+ const struct dev_ext_attribute *ea = to_ext_attr(attr);
if (kstrtobool(buf, ea->var) < 0)
return -EINVAL;
@@ -2583,19 +2583,19 @@ ssize_t device_store_bool(struct device *dev, struct device_attribute *attr,
}
EXPORT_SYMBOL_GPL(device_store_bool);
-ssize_t device_show_bool(struct device *dev, struct device_attribute *attr,
+ssize_t device_show_bool(struct device *dev, const struct device_attribute *attr,
char *buf)
{
- struct dev_ext_attribute *ea = to_ext_attr(attr);
+ const struct dev_ext_attribute *ea = to_ext_attr(attr);
return sysfs_emit(buf, "%d\n", *(bool *)(ea->var));
}
EXPORT_SYMBOL_GPL(device_show_bool);
ssize_t device_show_string(struct device *dev,
- struct device_attribute *attr, char *buf)
+ const struct device_attribute *attr, char *buf)
{
- struct dev_ext_attribute *ea = to_ext_attr(attr);
+ const struct dev_ext_attribute *ea = to_ext_attr(attr);
return sysfs_emit(buf, "%s\n", (char *)ea->var);
}
diff --git a/include/linux/device.h b/include/linux/device.h
index 7b2baffdd2f5..61e2b98b38a4 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -127,19 +127,19 @@ struct dev_ext_attribute {
void *var;
};
-ssize_t device_show_ulong(struct device *dev, struct device_attribute *attr,
+ssize_t device_show_ulong(struct device *dev, const struct device_attribute *attr,
char *buf);
-ssize_t device_store_ulong(struct device *dev, struct device_attribute *attr,
+ssize_t device_store_ulong(struct device *dev, const struct device_attribute *attr,
const char *buf, size_t count);
-ssize_t device_show_int(struct device *dev, struct device_attribute *attr,
+ssize_t device_show_int(struct device *dev, const struct device_attribute *attr,
char *buf);
-ssize_t device_store_int(struct device *dev, struct device_attribute *attr,
+ssize_t device_store_int(struct device *dev, const struct device_attribute *attr,
const char *buf, size_t count);
-ssize_t device_show_bool(struct device *dev, struct device_attribute *attr,
+ssize_t device_show_bool(struct device *dev, const struct device_attribute *attr,
char *buf);
-ssize_t device_store_bool(struct device *dev, struct device_attribute *attr,
+ssize_t device_store_bool(struct device *dev, const struct device_attribute *attr,
const char *buf, size_t count);
-ssize_t device_show_string(struct device *dev, struct device_attribute *attr,
+ssize_t device_show_string(struct device *dev, const struct device_attribute *attr,
char *buf);
typedef ssize_t __device_show_handler_const(struct device *dev, const struct device_attribute *attr,
--
2.55.0
^ permalink raw reply related
* Re: [PATCH 01/14] ASoC: codecs: NeoFidelity: repair the kernel-doc format
From: Mark Brown @ 2026-07-14 17:09 UTC (permalink / raw)
To: Randy Dunlap
Cc: linux-sound, Jaroslav Kysela, Takashi Iwai, Shengjiu Wang,
Xiubo Li, Fabio Estevam, Nicolin Chen, linuxppc-dev,
Charles Keepax, Maciej Strozek, Bard Liao, Pierre-Louis Bossart,
patches, Srinivas Kandagatla, linux-arm-msm, Liam Girdwood
In-Reply-To: <1a885ccd-77bb-4537-89c9-6b031c2f3812@infradead.org>
[-- Attachment #1: Type: text/plain, Size: 630 bytes --]
On Tue, Jul 14, 2026 at 08:57:06AM -0700, Randy Dunlap wrote:
> On 7/14/26 3:20 AM, Mark Brown wrote:
> > As mentioned in submitting-patches.rst when submitting a patch series
> > you should supply a cover letter for that patch series which describes
> > the overall content of the series. This helps people understand what
> > they are looking at and how things fit together.
> Are you saying that my cover letter was insufficient?
> https://lore.kernel.org/all/20260714014445.569992-1-rdunlap@infradead.org/
Well, quite apart from anything else you didn't send to to me so as far
as my inbox is concerned it doesn't exist.
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]
^ permalink raw reply
* Re: [PATCH] powerpc/eeh: Fix recursive locking on devices without EEH sensitive driver
From: Shivaprasad G Bhat @ 2026-07-14 17:15 UTC (permalink / raw)
To: Ritesh Harjani (IBM), maddy, linuxppc-dev
Cc: mpe, npiggin, chleroy, linux-kernel
In-Reply-To: <h5m9wmeo.ritesh.list@gmail.com>
Hi Ritesh,
Thanks for the review.
On 7/8/26 8:36 PM, Ritesh Harjani (IBM) wrote:
> Shivaprasad G Bhat <sbhat@linux.ibm.com> writes:
>
> hey, sorry looks like this fall through the cracks.
>
>> The commit 1010b4c012b0 ("powerpc/eeh: Make EEH driver device hotplug
>> safe") refactored the EEH code such that the pci_rescan_remove_lock is
>> held at the beginning of eeh_handle_normal_event() and the
>> eeh_reset_device() is called with that lock being held. Looks like the
>> commit missed to remove the existing lock/unlock inside eeh_rmv_device()
>> which is no longer necessary. This is causing the eehd to hang on the
>> lock which it actually holds when that code path is taken.
>>
>> [<0>] 0xc00000011c78f870
>> [<0>] __switch_to+0xfc/0x1a0
>> [<0>] pci_lock_rescan_remove+0x30/0x44
>> [<0>] eeh_rmv_device+0x290/0x2e0
>> [<0>] eeh_pe_dev_traverse+0x80/0x130
>> [<0>] eeh_reset_device+0xcc/0x23c
>> [<0>] eeh_handle_normal_event+0x830/0xa80
>> [<0>] eeh_event_handler+0xf8/0x190
>> [<0>] kthread+0x194/0x1b0
>> [<0>] start_kernel_thread+0x14/0x18
>>
> yup. I see eeh_handle_normal_event(), already holds this lock,
> pci_lock_rescan_remove().
>
> And eeh_rmv_device() only ever gets called from
>
> eeh_handle_normal_event()
> eeh_reset_device()
> eeh_pe_dev_traverse(pe, eeh_rmv_device,...)
>
> OR
>
> eeh_handle_normal_event()),
> eeh_pe_dev_traverse(pe, eeh_rmv_device,...)
>
> In both the paths, eeh_handle_normal_event() holds this lock. Although I
> am not an expert in eeh area - but looking at the relevant code paths,
> the race looks real and this patch fixes that. So feel free to add:
>
> Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
>
>
> I wonder whether clang context analyzer [1] could catch this. This is a
> good candidate to try that out.
>
> [1]: https://lore.kernel.org/lkml/20251219154418.3592607-1-elver@google.com/
I did give it a try.
https://gist.github.com/shivaprasadbhat/473ea8bcb63afda669bcb5de24ac22f8
It couldnt catch it. May need some more work.
>> The issue is seen for cases where the errors are detected on the PHB
>> directly AND|OR for devices where the driver error_detected() returns
>> PCI_ERS_RESULT_NEED_RESET, and driver being not EEH sensitive(i.e no
>> error handlers like slot_reset(), resume() etc defined).
>>
> I am just wondering how did we catch this issue and whether we have some
> ways to test eeh scenarios. Although the patch looks good to me.
Two ways to recreate, Mostly with drivers not having eeh_handlers like
slot_reset(), resume defined.
- On Baremetal, eeh on multi-function device bound to vfio.
- On PowerVM, eeh on a device behind a switch or IO drawer.
>> Fixes: 1010b4c012b0 ("powerpc/eeh: Make EEH driver device hotplug safe")
> Cc: stable@vger.kernel.org
>
> Let's add the above tag so that this also goes to stable trees. Since
> it's been sometime since this was last posted - maybe we should rebase
> and resend this with the above tag.
Sure.
Thanks,
Shivaprasad
> -ritesh
>
>> Signed-off-by: Shivaprasad G Bhat <sbhat@linux.ibm.com>
>> ---
>> arch/powerpc/kernel/eeh_driver.c | 2 --
>> 1 file changed, 2 deletions(-)
>>
>> diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
>> index 028f69158532..d64cce17a4e0 100644
>> --- a/arch/powerpc/kernel/eeh_driver.c
>> +++ b/arch/powerpc/kernel/eeh_driver.c
>> @@ -533,9 +533,7 @@ static void eeh_rmv_device(struct eeh_dev *edev, void *userdata)
>> if (rmv_data)
>> list_add(&edev->rmv_entry, &rmv_data->removed_vf_list);
>> } else {
>> - pci_lock_rescan_remove();
>> pci_stop_and_remove_bus_device(dev);
>> - pci_unlock_rescan_remove();
>> }
>> }
>>
^ permalink raw reply
* [PATCH v2] powerpc/eeh: Fix recursive locking on devices without EEH sensitive driver
From: Shivaprasad G Bhat @ 2026-07-14 17:16 UTC (permalink / raw)
To: maddy, linuxppc-dev
Cc: harshpb, mpe, npiggin, chleroy, sbhat, ritesh.list, linux-kernel
The commit 1010b4c012b0 ("powerpc/eeh: Make EEH driver device hotplug
safe") refactored the EEH code such that the pci_rescan_remove_lock is
held at the beginning of eeh_handle_normal_event() and the
eeh_reset_device() is called with that lock being held. Looks like the
commit missed to remove the existing lock/unlock inside eeh_rmv_device()
which is no longer necessary. This is causing the eehd to hang on the
lock which it actually holds when that code path is taken.
[<0>] 0xc00000011c78f870
[<0>] __switch_to+0xfc/0x1a0
[<0>] pci_lock_rescan_remove+0x30/0x44
[<0>] eeh_rmv_device+0x290/0x2e0
[<0>] eeh_pe_dev_traverse+0x80/0x130
[<0>] eeh_reset_device+0xcc/0x23c
[<0>] eeh_handle_normal_event+0x830/0xa80
[<0>] eeh_event_handler+0xf8/0x190
[<0>] kthread+0x194/0x1b0
[<0>] start_kernel_thread+0x14/0x18
The issue is seen for cases where the errors are detected on the PHB
directly AND|OR for devices where the driver error_detected() returns
PCI_ERS_RESULT_NEED_RESET, and driver being not EEH sensitive(i.e no
error handlers like slot_reset(), resume() etc defined).
Fixes: 1010b4c012b0 ("powerpc/eeh: Make EEH driver device hotplug safe")
Cc: stable <stable@kernel.org>
Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
Signed-off-by: Shivaprasad G Bhat <sbhat@linux.ibm.com>
---
arch/powerpc/kernel/eeh_driver.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 028f69158532..d64cce17a4e0 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -533,9 +533,7 @@ static void eeh_rmv_device(struct eeh_dev *edev, void *userdata)
if (rmv_data)
list_add(&edev->rmv_entry, &rmv_data->removed_vf_list);
} else {
- pci_lock_rescan_remove();
pci_stop_and_remove_bus_device(dev);
- pci_unlock_rescan_remove();
}
}
^ permalink raw reply related
* [PATCH] ppc/fadump: collect dump if the collected size is lesser than reserved
From: Shivang Upadhyay @ 2026-07-14 17:30 UTC (permalink / raw)
To: linuxppc-dev, linux-kernel
Cc: maddy, mpe, npiggin, chleroy, sourabhjain, adri.vero.dev, adityag,
anushree.mathur, Shivang Upadhyay
When a machine is subjected to CPUs add/remove, using dlpar
operations, the number of collected CPU_NOTES can change.
As per PAPR, collected dump size should not be more than
allocated size. Reflecting the same in source.
Signed-off-by: Shivang Upadhyay <shivangu@linux.ibm.com>
---
arch/powerpc/platforms/pseries/rtas-fadump.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/platforms/pseries/rtas-fadump.c b/arch/powerpc/platforms/pseries/rtas-fadump.c
index 3bb4ac2ab6cc..19a5adaf326b 100644
--- a/arch/powerpc/platforms/pseries/rtas-fadump.c
+++ b/arch/powerpc/platforms/pseries/rtas-fadump.c
@@ -469,7 +469,8 @@ static int __init rtas_fadump_process(struct fw_dump *fadump_conf)
pr_err("Dump taken by platform is not valid (%d)\n", i);
rc = -EINVAL;
}
- if (fdm_active->rgn[i].bytes_dumped != fdm_active->rgn[i].source_len) {
+ if (be64_to_cpu(fdm_active->rgn[i].bytes_dumped)
+ > be64_to_cpu(fdm_active->rgn[i].source_len)) {
pr_err("Dump taken by platform is incomplete (%d)\n", i);
rc = -EINVAL;
}
--
2.54.0
^ permalink raw reply related
* Re: [PATCH v7 06/10] ACPI: APEI: GHES: move CXL CPER helpers
From: Alison Schofield @ 2026-07-14 17:33 UTC (permalink / raw)
To: Ahmed Tiba
Cc: Rafael J. Wysocki, Tony Luck, Borislav Petkov, Hanjun Guo,
Mauro Carvalho Chehab, Shuai Xue, Len Brown, Saket Dumbre,
Davidlohr Bueso, Jonathan Cameron, Dave Jiang, Vishal Verma,
Dan Williams, Ira Weiny, Li Ming, Mahesh J Salgaonkar,
Oliver O'Halloran, Bjorn Helgaas, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, Jonathan Corbet, Shuah Khan,
linux-kernel, linux-acpi, acpica-devel, linux-cxl, linuxppc-dev,
linux-pci, devicetree, linux-edac, linux-doc, Dmitry.Lamerov
In-Reply-To: <e77d0367-ab24-4b6d-beaa-034dd793cef6@arm.com>
On Tue, Jul 14, 2026 at 10:27:01AM +0100, Ahmed Tiba wrote:
> On 14/07/2026 03:45, Alison Schofield wrote:
> > On Wed, Jul 08, 2026 at 02:59:05PM +0100, Ahmed Tiba wrote:
> > > Move the CXL CPER handling paths out of ghes.c and into ghes_cper.c so the
> > > helpers can be reused. The code is moved as-is, with the public
> > > prototypes updated so GHES keeps calling into the new translation unit.
> > >
> > > While moving this code, also add CXL CPER section length checks and use
> > > spinlock_irqsave() in CXL register/unregister paths for locking
> > > consistency.
> >
> > NAK on moving and changing in the same patch, and esp in a patch
> > whose subject only says MOVE.
> Hi Alison,
>
> I understand the concern.
>
> I kept those changes in 06/10 because they address pre-existing issues
> reported specifically against this patch by Sashiko, and I wanted to avoid
> carrying known defects forward in the series. I did this following Boris'
> feedback to address review-reported issues in-series rather than carry them
> forward unchanged.
>
> I can also add a dedicated "Sashiko findings addressed" section and update
> the commit description to state clearly that this patch is not pure move.
>
> Please advise your preferred way to address Sashiko findings per patch in
> this series.
I think you can address the Sashiko pre-exists in series without
them being hidden in a move patch.
To be strictly like Boris seems to be asking (fixes first), do:
add CXL CPER section length checks
use spinlock_irqsave() in CXL (un-)register paths
move CXL CPER helpers
-- Alison
>
> Thanks,
> Ahmed
^ permalink raw reply
* [PATCH v5] KVM: PPC: Book3S HV: Validate arch_compat against host compatibility mode
From: Amit Machhiwal @ 2026-07-14 17:54 UTC (permalink / raw)
To: linuxppc-dev, Madhavan Srinivasan
Cc: Amit Machhiwal, Vaibhav Jain, Harsh Prateek Bora, Ritesh Harjani,
Anushree Mathur, Gautam Menghani, Mukesh Kumar Chaurasiya,
Nicholas Piggin, Michael Ellerman, Christophe Leroy (CS GROUP),
Thomas Huth, kvm, stable, linux-kernel
On IBM POWER systems, newer processor generations can operate in
compatibility modes corresponding to earlier generations. This becomes
relevant for nested virtualization, where nested KVM guests may need to
run with a specific processor compatibility level.
Currently, when running a nested KVM guest (L2) inside a Power11 pSeries
logical partition (L1) booted in Power10 compatibility mode, the guest
fails to boot while setting 'arch_compat'. This happens because the CPU
class is derived from the hardware PVR (via mfspr()), which reflects the
physical processor generation (Power11), rather than the effective
compatibility mode (Power10).
As a result, userspace may request a Power11 arch_compat for the L2
guest. However, the L1 partition, running in Power10 compatibility, has
only negotiated support up to Power10 with the Power Hypervisor (L0).
When H_GUEST_SET_STATE is invoked with a Power11 Logical PVR, the
hypervisor rejects the request, leading to a late guest boot failure:
KVM-NESTEDv2: couldn't set guest wide elements
[..KVM reg dump..]
This situation should be detected earlier and rejected by KVM. Without
proper validation, if userspace ignores the error, the guest may continue
to boot in Power11 raw mode on a Power10 compatibility host, which should
not be allowed.
Introduce a validation mechanism that detects unsupported arch_compat
values early in the guest initialization path. When an unsupported
arch_compat is requested (e.g., Power11 on a Power10 compatibility mode
host), kvmppc_set_arch_compat() uses cpu_has_feature(CPU_FTR_P11_PVR) to
detect the mismatch and sets arch_compat to PVR_ARCH_INVALID (0xffffffff).
This sentinel value is architecturally safe: PAPR specifies that valid
logical PVR values must have 0x0f as the first byte, ensuring 0xffffffff
lies permanently outside the specification-defined range. Setting this
value triggers kvmppc_sanity_check() to mark the vCPU as invalid by
setting vcpu->arch.sane to false. On the next vCPU run, kvmppc_vcpu_run_hv()
checks this flag and returns -EINVAL, preventing the guest from running
with an invalid processor compatibility configuration.
With this, when a Power11 arch_compat is requested on a Power10
compatibility mode host, the guest fails early during boot with:
error: kvm run failed Invalid argument
This provides a much clearer failure mode compared to the previous
behavior where the guest could boot in Power11 raw mode (if userspace
ignored the error) or fail late during H_GUEST_SET_STATE.
Suggested-by: Vaibhav Jain <vaibhav@linux.ibm.com>
Reviewed-by: Vaibhav Jain <vaibhav@linux.ibm.com>
Tested-by: Anushree Mathur <anushree.mathur@linux.ibm.com>
Acked-by: Gautam Menghani <gautam@linux.ibm.com>
Cc: stable@vger.kernel.org # v6.13+
Reviewed-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
Reviewed-by: Mukesh Kumar Chaurasiya (IBM) <mkchauras@gmail.com>
Signed-off-by: Amit Machhiwal <amachhiw@linux.ibm.com>
---
Testing: Both Anushree and I have tested the below scenarios:
1. P11 guest on P11 host - Works
2. P10 compat guest on P11 host - Works
3. P11 guest on compat-P10 host - Correctly fails with "Invalid argument"
4. P10 guest on compat-P10 host - Works
Changes in v5:
* Guarded the new vcpu->arch.vcore->arch_compat check in
kvmppc_sanity_check() with #if defined(CONFIG_KVM_BOOK3S_HV_POSSIBLE)
to fix a build failure in randconfig builds where CONFIG_PPC_BOOK3S is
not set and struct kvmppc_vcore is not fully defined [Reported by
kernel test robot]
* Report: https://lore.kernel.org/all/202607142107.CrgQhmsx-lkp@intel.com/
* v4: https://lore.kernel.org/all/20260616163405.96962-1-amachhiw@linux.ibm.com/
Changes in v4:
* Added documentation for PVR_ARCH_INVALID explaining why 0xffffffff is
architecturally safe to use as a sentinel value (PAPR constraint on
first byte being 0x0f) [Ritesh]
* Updated commit message
* v3: https://lore.kernel.org/all/20260609053327.61563-1-amachhiw@linux.ibm.com/
Changes in v3:
* Fixed null pointer dereference in kvmppc_sanity_check(): added check for
vcpu->arch.vcore before accessing arch_compat, as vcore is NULL for Book3S
PR and BookE guests (only Book3S HV uses vcore) [Reported by Sashiko AI]
* Added Reviewed-by tag from Vaibhav
* v2: https://lore.kernel.org/all/20260608201001.65760-1-amachhiw@linux.ibm.com/
Changes in v2:
* Fixed issue where v1 allowed guest to boot in Power11 raw mode when
userspace ignored the error, by adding validation in kvmppc_sanity_check()
to ensure early failure during vCPU run [Found the issue after posting v1,
also reported by Gautam.]
* Introduced PVR_ARCH_INVALID constant for marking invalid arch_compat
* Dropped all Reviewed-by and Tested-by tags due to code changes; requesting
fresh reviews
* v1: https://lore.kernel.org/all/20260603141539.47620-1-amachhiw@linux.ibm.com/
Changes in v1:
* Moved this patch out of the v3 series [1] as discussed here [2]
* Addressed below review comments from Ritesh:
- Based the PVR validation on cpu features
- Fixed hcall name typo
- Stable backport
[1] https://lore.kernel.org/all/20260522152744.55251-1-amachhiw@linux.ibm.com/
[2] https://lore.kernel.org/all/20260522152744.55251-2-amachhiw@linux.ibm.com/
---
arch/powerpc/include/asm/reg.h | 12 ++++++++++++
arch/powerpc/kvm/book3s_hv.c | 15 ++++++++++++++-
arch/powerpc/kvm/powerpc.c | 6 ++++++
3 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/arch/powerpc/include/asm/reg.h b/arch/powerpc/include/asm/reg.h
index 3449dd2b577d..b9ab9df1e2bc 100644
--- a/arch/powerpc/include/asm/reg.h
+++ b/arch/powerpc/include/asm/reg.h
@@ -1357,6 +1357,18 @@
#define PVR_ARCH_31 0x0f000006
#define PVR_ARCH_31_P11 0x0f000007
+/*
+ * Kernel-internal sentinel for invalid processor compatibility modes.
+ * PAPR specifies that the first byte of a valid logical PVR value is
+ * 0x0f. So 0xffffffff lies permanently outside the PAPR-defined range
+ * and is safe to repurpose. KVM stores it in vcpu->arch.arch_compat
+ * when userspace requests an unsupported compatibility mode (e.g.,
+ * Power11 PVR on a Power11 host booted in Power10 compat).
+ * kvmppc_sanity_check() detects this and prevents the vCPU from
+ * running with an unsupported arch_compat.
+ */
+#define PVR_ARCH_INVALID 0xffffffff
+
/* Macros for setting and retrieving special purpose registers */
#ifndef __ASSEMBLER__
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index 61dbeea317f3..f9380ef65750 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -446,7 +446,19 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
guest_pcr_bit = PCR_ARCH_300;
break;
case PVR_ARCH_31:
+ guest_pcr_bit = PCR_ARCH_31;
+ break;
case PVR_ARCH_31_P11:
+ /*
+ * Need to check this for ISA 3.1, as Power10 and
+ * Power11 share the same PCR. For any subsequent ISA
+ * versions, this will be taken care of by the guest vs
+ * host PCR comparison below.
+ */
+ if (!cpu_has_feature(CPU_FTR_P11_PVR)) {
+ arch_compat = PVR_ARCH_INVALID;
+ goto out;
+ }
guest_pcr_bit = PCR_ARCH_31;
break;
default:
@@ -469,6 +481,7 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
return -EINVAL;
}
+out:
spin_lock(&vc->lock);
vc->arch_compat = arch_compat;
kvmhv_nestedv2_mark_dirty(vcpu, KVMPPC_GSID_LOGICAL_PVR);
@@ -479,7 +492,7 @@ static int kvmppc_set_arch_compat(struct kvm_vcpu *vcpu, u32 arch_compat)
vc->pcr = (host_pcr_bit - guest_pcr_bit) | PCR_MASK;
spin_unlock(&vc->lock);
- return 0;
+ return kvmppc_sanity_check(vcpu);
}
static void kvmppc_dump_regs(struct kvm_vcpu *vcpu)
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index 00302399fc37..b6b83fe3233f 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -258,6 +258,12 @@ int kvmppc_sanity_check(struct kvm_vcpu *vcpu)
if (!vcpu->arch.pvr)
goto out;
+#if defined(CONFIG_KVM_BOOK3S_HV_POSSIBLE)
+ if (vcpu->arch.vcore &&
+ vcpu->arch.vcore->arch_compat == PVR_ARCH_INVALID)
+ goto out;
+#endif
+
/* PAPR only works with book3s_64 */
if ((vcpu->arch.cpu_type != KVM_CPU_3S_64) && vcpu->arch.papr_enabled)
goto out;
base-commit: 3b029c035b34bbc693405ddf759f0e9b920c27f1
--
2.50.1 (Apple Git-155)
^ permalink raw reply related
* Re: [PATCH] KVM: Nullify irqfd->producer when add_producer() fails
From: Sean Christopherson @ 2026-07-14 18:41 UTC (permalink / raw)
To: Sean Christopherson, leixiang
Cc: stable, Madhavan Srinivasan, Nicholas Piggin, Michael Ellerman,
Christophe Leroy (CS GROUP), Paolo Bonzini, Thomas Gleixner,
Ingo Molnar, Borislav Petkov, Dave Hansen, x86, H. Peter Anvin,
Paul Mackerras, Suresh Warrier, linuxppc-dev, kvm, linux-kernel
In-Reply-To: <1782119051448443.14545.seg@mailgw.kylinos.cn>
On Mon, 22 Jun 2026 15:51:01 +0800, leixiang wrote:
> The x86 and powerpc add_producer() callbacks set irqfd->producer before the
> fallible setup and never clear it on error. The bypass manager doesn't
> register a producer whose add_producer() failed -- producer->eventfd is
> left NULL, so the later unregister early-returns and del_producer() is
> never called -- so nothing ever drops the pointer.
>
> For VFIO PCI the producer is embedded in struct vfio_pci_irq_ctx and freed
> when the vector is disabled, after which a routing update dereferences the
> dangling pointer via kvm_arch_update_irqfd_routing().
>
> [...]
Applied to kvm-x86 fixes, thanks!
[1/1] KVM: Nullify irqfd->producer when add_producer() fails
https://github.com/kvm-x86/linux/commit/ed446e8aa894
--
https://github.com/kvm-x86/linux/tree/next
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox