From: Greg Kroah-Hartman Date: Sun, 13 Jul 2025 14:37:12 +0000 (+0200) Subject: 6.6-stable patches X-Git-Tag: v5.15.188~31 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ae226932fb6fd9ae058ba9bc42f2d256ad0416c9;p=thirdparty%2Fkernel%2Fstable-queue.git 6.6-stable patches added patches: kallsyms-fix-build-without-execinfo.patch maple_tree-fix-mt_destroy_walk-on-root-leaf-node.patch mm-fix-the-inaccurate-memory-statistics-issue-for-users.patch mm-vmalloc-leave-lazy-mmu-mode-on-pte-mapping-error.patch scripts-gdb-de-reference-per-cpu-mce-interrupts.patch scripts-gdb-fix-interrupts-display-after-mcp-on-x86.patch scripts-gdb-fix-interrupts.py-after-maple-tree-conversion.patch --- diff --git a/queue-6.6/kallsyms-fix-build-without-execinfo.patch b/queue-6.6/kallsyms-fix-build-without-execinfo.patch new file mode 100644 index 0000000000..d297135334 --- /dev/null +++ b/queue-6.6/kallsyms-fix-build-without-execinfo.patch @@ -0,0 +1,48 @@ +From a95743b53031b015e8949e845a9f6fdfb2656347 Mon Sep 17 00:00:00 2001 +From: Achill Gilgenast +Date: Sun, 22 Jun 2025 03:45:49 +0200 +Subject: kallsyms: fix build without execinfo + +From: Achill Gilgenast + +commit a95743b53031b015e8949e845a9f6fdfb2656347 upstream. + +Some libc's like musl libc don't provide execinfo.h since it's not part of +POSIX. In order to fix compilation on musl, only include execinfo.h if +available (HAVE_BACKTRACE_SUPPORT) + +This was discovered with c104c16073b7 ("Kunit to check the longest symbol +length") which starts to include linux/kallsyms.h with Alpine Linux' +configs. + +Link: https://lkml.kernel.org/r/20250622014608.448718-1-fossdd@pwned.life +Fixes: c104c16073b7 ("Kunit to check the longest symbol length") +Signed-off-by: Achill Gilgenast +Cc: Luis Henriques +Cc: Greg Kroah-Hartman +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + tools/include/linux/kallsyms.h | 4 ++++ + 1 file changed, 4 insertions(+) + +--- a/tools/include/linux/kallsyms.h ++++ b/tools/include/linux/kallsyms.h +@@ -18,6 +18,7 @@ static inline const char *kallsyms_looku + return NULL; + } + ++#ifdef HAVE_BACKTRACE_SUPPORT + #include + #include + static inline void print_ip_sym(const char *loglvl, unsigned long ip) +@@ -30,5 +31,8 @@ static inline void print_ip_sym(const ch + + free(name); + } ++#else ++static inline void print_ip_sym(const char *loglvl, unsigned long ip) {} ++#endif + + #endif diff --git a/queue-6.6/maple_tree-fix-mt_destroy_walk-on-root-leaf-node.patch b/queue-6.6/maple_tree-fix-mt_destroy_walk-on-root-leaf-node.patch new file mode 100644 index 0000000000..c352d2c754 --- /dev/null +++ b/queue-6.6/maple_tree-fix-mt_destroy_walk-on-root-leaf-node.patch @@ -0,0 +1,40 @@ +From ea9b77f98d94c4d5c1bd1ac1db078f78b40e8bf5 Mon Sep 17 00:00:00 2001 +From: Wei Yang +Date: Tue, 24 Jun 2025 15:18:40 -0400 +Subject: maple_tree: fix mt_destroy_walk() on root leaf node + +From: Wei Yang + +commit ea9b77f98d94c4d5c1bd1ac1db078f78b40e8bf5 upstream. + +On destroy, we should set each node dead. But current code miss this when +the maple tree has only the root node. + +The reason is mt_destroy_walk() leverage mte_destroy_descend() to set node +dead, but this is skipped since the only root node is a leaf. + +Fixes this by setting the node dead if it is a leaf. + +Link: https://lore.kernel.org/all/20250407231354.11771-1-richard.weiyang@gmail.com/ +Link: https://lkml.kernel.org/r/20250624191841.64682-1-Liam.Howlett@oracle.com +Fixes: 54a611b60590 ("Maple Tree: add new data structure") +Signed-off-by: Wei Yang +Signed-off-by: Liam R. Howlett +Reviewed-by: Dev Jain +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + lib/maple_tree.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/lib/maple_tree.c ++++ b/lib/maple_tree.c +@@ -5270,6 +5270,7 @@ static void mt_destroy_walk(struct maple + struct maple_enode *start; + + if (mte_is_leaf(enode)) { ++ mte_set_node_dead(enode); + node->type = mte_node_type(enode); + goto free_leaf; + } diff --git a/queue-6.6/mm-fix-the-inaccurate-memory-statistics-issue-for-users.patch b/queue-6.6/mm-fix-the-inaccurate-memory-statistics-issue-for-users.patch new file mode 100644 index 0000000000..ec15af801f --- /dev/null +++ b/queue-6.6/mm-fix-the-inaccurate-memory-statistics-issue-for-users.patch @@ -0,0 +1,138 @@ +From 82241a83cd15aaaf28200a40ad1a8b480012edaf Mon Sep 17 00:00:00 2001 +From: Baolin Wang +Date: Thu, 5 Jun 2025 20:58:29 +0800 +Subject: mm: fix the inaccurate memory statistics issue for users + +From: Baolin Wang + +commit 82241a83cd15aaaf28200a40ad1a8b480012edaf upstream. + +On some large machines with a high number of CPUs running a 64K pagesize +kernel, we found that the 'RES' field is always 0 displayed by the top +command for some processes, which will cause a lot of confusion for users. + + PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND + 875525 root 20 0 12480 0 0 R 0.3 0.0 0:00.08 top + 1 root 20 0 172800 0 0 S 0.0 0.0 0:04.52 systemd + +The main reason is that the batch size of the percpu counter is quite +large on these machines, caching a significant percpu value, since +converting mm's rss stats into percpu_counter by commit f1a7941243c1 ("mm: +convert mm's rss stats into percpu_counter"). Intuitively, the batch +number should be optimized, but on some paths, performance may take +precedence over statistical accuracy. Therefore, introducing a new +interface to add the percpu statistical count and display it to users, +which can remove the confusion. In addition, this change is not expected +to be on a performance-critical path, so the modification should be +acceptable. + +In addition, the 'mm->rss_stat' is updated by using add_mm_counter() and +dec/inc_mm_counter(), which are all wrappers around +percpu_counter_add_batch(). In percpu_counter_add_batch(), there is +percpu batch caching to avoid 'fbc->lock' contention. This patch changes +task_mem() and task_statm() to get the accurate mm counters under the +'fbc->lock', but this should not exacerbate kernel 'mm->rss_stat' lock +contention due to the percpu batch caching of the mm counters. The +following test also confirm the theoretical analysis. + +I run the stress-ng that stresses anon page faults in 32 threads on my 32 +cores machine, while simultaneously running a script that starts 32 +threads to busy-loop pread each stress-ng thread's /proc/pid/status +interface. From the following data, I did not observe any obvious impact +of this patch on the stress-ng tests. + +w/o patch: +stress-ng: info: [6848] 4,399,219,085,152 CPU Cycles 67.327 B/sec +stress-ng: info: [6848] 1,616,524,844,832 Instructions 24.740 B/sec (0.367 instr. per cycle) +stress-ng: info: [6848] 39,529,792 Page Faults Total 0.605 M/sec +stress-ng: info: [6848] 39,529,792 Page Faults Minor 0.605 M/sec + +w/patch: +stress-ng: info: [2485] 4,462,440,381,856 CPU Cycles 68.382 B/sec +stress-ng: info: [2485] 1,615,101,503,296 Instructions 24.750 B/sec (0.362 instr. per cycle) +stress-ng: info: [2485] 39,439,232 Page Faults Total 0.604 M/sec +stress-ng: info: [2485] 39,439,232 Page Faults Minor 0.604 M/sec + +On comparing a very simple app which just allocates & touches some +memory against v6.1 (which doesn't have f1a7941243c1) and latest Linus +tree (4c06e63b9203) I can see that on latest Linus tree the values for +VmRSS, RssAnon and RssFile from /proc/self/status are all zeroes while +they do report values on v6.1 and a Linus tree with this patch. + +Link: https://lkml.kernel.org/r/f4586b17f66f97c174f7fd1f8647374fdb53de1c.1749119050.git.baolin.wang@linux.alibaba.com +Fixes: f1a7941243c1 ("mm: convert mm's rss stats into percpu_counter") +Signed-off-by: Baolin Wang +Reviewed-by: Aboorva Devarajan +Tested-by: Aboorva Devarajan +Tested-by Donet Tom +Acked-by: Shakeel Butt +Acked-by: SeongJae Park +Acked-by: Michal Hocko +Reviewed-by: Vlastimil Babka +Cc: David Hildenbrand +Cc: Liam Howlett +Cc: Lorenzo Stoakes +Cc: Mike Rapoport +Cc: Suren Baghdasaryan +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + fs/proc/task_mmu.c | 14 +++++++------- + include/linux/mm.h | 5 +++++ + 2 files changed, 12 insertions(+), 7 deletions(-) + +--- a/fs/proc/task_mmu.c ++++ b/fs/proc/task_mmu.c +@@ -33,9 +33,9 @@ void task_mem(struct seq_file *m, struct + unsigned long text, lib, swap, anon, file, shmem; + unsigned long hiwater_vm, total_vm, hiwater_rss, total_rss; + +- anon = get_mm_counter(mm, MM_ANONPAGES); +- file = get_mm_counter(mm, MM_FILEPAGES); +- shmem = get_mm_counter(mm, MM_SHMEMPAGES); ++ anon = get_mm_counter_sum(mm, MM_ANONPAGES); ++ file = get_mm_counter_sum(mm, MM_FILEPAGES); ++ shmem = get_mm_counter_sum(mm, MM_SHMEMPAGES); + + /* + * Note: to minimize their overhead, mm maintains hiwater_vm and +@@ -56,7 +56,7 @@ void task_mem(struct seq_file *m, struct + text = min(text, mm->exec_vm << PAGE_SHIFT); + lib = (mm->exec_vm << PAGE_SHIFT) - text; + +- swap = get_mm_counter(mm, MM_SWAPENTS); ++ swap = get_mm_counter_sum(mm, MM_SWAPENTS); + SEQ_PUT_DEC("VmPeak:\t", hiwater_vm); + SEQ_PUT_DEC(" kB\nVmSize:\t", total_vm); + SEQ_PUT_DEC(" kB\nVmLck:\t", mm->locked_vm); +@@ -89,12 +89,12 @@ unsigned long task_statm(struct mm_struc + unsigned long *shared, unsigned long *text, + unsigned long *data, unsigned long *resident) + { +- *shared = get_mm_counter(mm, MM_FILEPAGES) + +- get_mm_counter(mm, MM_SHMEMPAGES); ++ *shared = get_mm_counter_sum(mm, MM_FILEPAGES) + ++ get_mm_counter_sum(mm, MM_SHMEMPAGES); + *text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) + >> PAGE_SHIFT; + *data = mm->data_vm + mm->stack_vm; +- *resident = *shared + get_mm_counter(mm, MM_ANONPAGES); ++ *resident = *shared + get_mm_counter_sum(mm, MM_ANONPAGES); + return mm->total_vm; + } + +--- a/include/linux/mm.h ++++ b/include/linux/mm.h +@@ -2551,6 +2551,11 @@ static inline unsigned long get_mm_count + return percpu_counter_read_positive(&mm->rss_stat[member]); + } + ++static inline unsigned long get_mm_counter_sum(struct mm_struct *mm, int member) ++{ ++ return percpu_counter_sum_positive(&mm->rss_stat[member]); ++} ++ + void mm_trace_rss_stat(struct mm_struct *mm, int member); + + static inline void add_mm_counter(struct mm_struct *mm, int member, long value) diff --git a/queue-6.6/mm-vmalloc-leave-lazy-mmu-mode-on-pte-mapping-error.patch b/queue-6.6/mm-vmalloc-leave-lazy-mmu-mode-on-pte-mapping-error.patch new file mode 100644 index 0000000000..c9c162c391 --- /dev/null +++ b/queue-6.6/mm-vmalloc-leave-lazy-mmu-mode-on-pte-mapping-error.patch @@ -0,0 +1,69 @@ +From fea18c686320a53fce7ad62a87a3e1d10ad02f31 Mon Sep 17 00:00:00 2001 +From: Alexander Gordeev +Date: Mon, 23 Jun 2025 09:57:21 +0200 +Subject: mm/vmalloc: leave lazy MMU mode on PTE mapping error + +From: Alexander Gordeev + +commit fea18c686320a53fce7ad62a87a3e1d10ad02f31 upstream. + +vmap_pages_pte_range() enters the lazy MMU mode, but fails to leave it in +case an error is encountered. + +Link: https://lkml.kernel.org/r/20250623075721.2817094-1-agordeev@linux.ibm.com +Fixes: 2ba3e6947aed ("mm/vmalloc: track which page-table levels were modified") +Signed-off-by: Alexander Gordeev +Reported-by: kernel test robot +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/r/202506132017.T1l1l6ME-lkp@intel.com/ +Reviewed-by: Ryan Roberts +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + mm/vmalloc.c | 22 +++++++++++++++------- + 1 file changed, 15 insertions(+), 7 deletions(-) + +--- a/mm/vmalloc.c ++++ b/mm/vmalloc.c +@@ -459,6 +459,7 @@ static int vmap_pages_pte_range(pmd_t *p + unsigned long end, pgprot_t prot, struct page **pages, int *nr, + pgtbl_mod_mask *mask) + { ++ int err = 0; + pte_t *pte; + + /* +@@ -472,18 +473,25 @@ static int vmap_pages_pte_range(pmd_t *p + do { + struct page *page = pages[*nr]; + +- if (WARN_ON(!pte_none(ptep_get(pte)))) +- return -EBUSY; +- if (WARN_ON(!page)) +- return -ENOMEM; +- if (WARN_ON(!pfn_valid(page_to_pfn(page)))) +- return -EINVAL; ++ if (WARN_ON(!pte_none(ptep_get(pte)))) { ++ err = -EBUSY; ++ break; ++ } ++ if (WARN_ON(!page)) { ++ err = -ENOMEM; ++ break; ++ } ++ if (WARN_ON(!pfn_valid(page_to_pfn(page)))) { ++ err = -EINVAL; ++ break; ++ } + + set_pte_at(&init_mm, addr, pte, mk_pte(page, prot)); + (*nr)++; + } while (pte++, addr += PAGE_SIZE, addr != end); + *mask |= PGTBL_PTE_MODIFIED; +- return 0; ++ ++ return err; + } + + static int vmap_pages_pmd_range(pud_t *pud, unsigned long addr, diff --git a/queue-6.6/scripts-gdb-de-reference-per-cpu-mce-interrupts.patch b/queue-6.6/scripts-gdb-de-reference-per-cpu-mce-interrupts.patch new file mode 100644 index 0000000000..a6a0dd4cf1 --- /dev/null +++ b/queue-6.6/scripts-gdb-de-reference-per-cpu-mce-interrupts.patch @@ -0,0 +1,45 @@ +From 50f4d2ba26d5c3a4687ae0569be3bbf1c8f0cbed Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Mon, 23 Jun 2025 20:00:19 -0700 +Subject: scripts/gdb: de-reference per-CPU MCE interrupts + +From: Florian Fainelli + +commit 50f4d2ba26d5c3a4687ae0569be3bbf1c8f0cbed upstream. + +The per-CPU MCE interrupts are looked up by reference and need to be +de-referenced before printing, otherwise we print the addresses of the +variables instead of their contents: + +MCE: 18379471554386948492 Machine check exceptions +MCP: 18379471554386948488 Machine check polls + +The corrected output looks like this instead now: + +MCE: 0 Machine check exceptions +MCP: 1 Machine check polls + +Link: https://lkml.kernel.org/r/20250625021109.1057046-1-florian.fainelli@broadcom.com +Link: https://lkml.kernel.org/r/20250624030020.882472-1-florian.fainelli@broadcom.com +Fixes: b0969d7687a7 ("scripts/gdb: print interrupts") +Signed-off-by: Florian Fainelli +Cc: Jan Kiszka +Cc: Kieran Bingham +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + scripts/gdb/linux/interrupts.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/scripts/gdb/linux/interrupts.py ++++ b/scripts/gdb/linux/interrupts.py +@@ -110,7 +110,7 @@ def x86_show_mce(prec, var, pfx, desc): + pvar = gdb.parse_and_eval(var) + text = "%*s: " % (prec, pfx) + for cpu in cpus.each_online_cpu(): +- text += "%10u " % (cpus.per_cpu(pvar, cpu)) ++ text += "%10u " % (cpus.per_cpu(pvar, cpu).dereference()) + text += " %s\n" % (desc) + return text + diff --git a/queue-6.6/scripts-gdb-fix-interrupts-display-after-mcp-on-x86.patch b/queue-6.6/scripts-gdb-fix-interrupts-display-after-mcp-on-x86.patch new file mode 100644 index 0000000000..89e1cabec1 --- /dev/null +++ b/queue-6.6/scripts-gdb-fix-interrupts-display-after-mcp-on-x86.patch @@ -0,0 +1,40 @@ +From 7627b459aa0737bdd62a8591a1481cda467f20e3 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Mon, 23 Jun 2025 09:41:52 -0700 +Subject: scripts/gdb: fix interrupts display after MCP on x86 + +From: Florian Fainelli + +commit 7627b459aa0737bdd62a8591a1481cda467f20e3 upstream. + +The text line would not be appended to as it should have, it should have +been a '+=' but ended up being a '==', fix that. + +Link: https://lkml.kernel.org/r/20250623164153.746359-1-florian.fainelli@broadcom.com +Fixes: b0969d7687a7 ("scripts/gdb: print interrupts") +Signed-off-by: Florian Fainelli +Cc: Jan Kiszka +Cc: Kieran Bingham +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + scripts/gdb/linux/interrupts.py | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/scripts/gdb/linux/interrupts.py b/scripts/gdb/linux/interrupts.py +index 616a5f26377a..199d9e8193f4 100644 +--- a/scripts/gdb/linux/interrupts.py ++++ b/scripts/gdb/linux/interrupts.py +@@ -142,7 +142,7 @@ def x86_show_interupts(prec): + + if constants.LX_CONFIG_X86_MCE: + text += x86_show_mce(prec, "&mce_exception_count", "MCE", "Machine check exceptions") +- text == x86_show_mce(prec, "&mce_poll_count", "MCP", "Machine check polls") ++ text += x86_show_mce(prec, "&mce_poll_count", "MCP", "Machine check polls") + + text += show_irq_err_count(prec) + +-- +2.50.1 + diff --git a/queue-6.6/scripts-gdb-fix-interrupts.py-after-maple-tree-conversion.patch b/queue-6.6/scripts-gdb-fix-interrupts.py-after-maple-tree-conversion.patch new file mode 100644 index 0000000000..7854beee07 --- /dev/null +++ b/queue-6.6/scripts-gdb-fix-interrupts.py-after-maple-tree-conversion.patch @@ -0,0 +1,389 @@ +From a02b0cde8ee515ee0c8efd33e7fbe6830c282e69 Mon Sep 17 00:00:00 2001 +From: Florian Fainelli +Date: Tue, 24 Jun 2025 19:10:20 -0700 +Subject: scripts/gdb: fix interrupts.py after maple tree conversion + +From: Florian Fainelli + +commit a02b0cde8ee515ee0c8efd33e7fbe6830c282e69 upstream. + +In commit 721255b9826b ("genirq: Use a maple tree for interrupt descriptor +management"), the irq_desc_tree was replaced with a sparse_irqs tree using +a maple tree structure. Since the script looked for the irq_desc_tree +symbol which is no longer available, no interrupts would be printed and +the script output would not be useful anymore. + +In addition to looking up the correct symbol (sparse_irqs), a new module +(mapletree.py) is added whose mtree_load() implementation is largely +copied after the C version and uses the same variable and intermediate +function names wherever possible to ensure that both the C and Python +version be updated in the future. + +This restores the scripts' output to match that of /proc/interrupts. + +Link: https://lkml.kernel.org/r/20250625021020.1056930-1-florian.fainelli@broadcom.com +Fixes: 721255b9826b ("genirq: Use a maple tree for interrupt descriptor management") +Signed-off-by: Florian Fainelli +Cc: Jan Kiszka +Cc: Kieran Bingham +Cc: Shanker Donthineni +Cc: Thomas Gleinxer +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + scripts/gdb/linux/constants.py.in | 7 + + scripts/gdb/linux/interrupts.py | 12 - + scripts/gdb/linux/mapletree.py | 252 ++++++++++++++++++++++++++++++++++++++ + scripts/gdb/linux/xarray.py | 28 ++++ + 4 files changed, 293 insertions(+), 6 deletions(-) + create mode 100644 scripts/gdb/linux/mapletree.py + create mode 100644 scripts/gdb/linux/xarray.py + +--- a/scripts/gdb/linux/constants.py.in ++++ b/scripts/gdb/linux/constants.py.in +@@ -20,6 +20,7 @@ + #include + #include + #include ++#include + #include + #include + #include +@@ -93,6 +94,12 @@ LX_GDBPARSED(RADIX_TREE_MAP_SIZE) + LX_GDBPARSED(RADIX_TREE_MAP_SHIFT) + LX_GDBPARSED(RADIX_TREE_MAP_MASK) + ++/* linux/maple_tree.h */ ++LX_VALUE(MAPLE_NODE_SLOTS) ++LX_VALUE(MAPLE_RANGE64_SLOTS) ++LX_VALUE(MAPLE_ARANGE64_SLOTS) ++LX_GDBPARSED(MAPLE_NODE_MASK) ++ + /* linux/vmalloc.h */ + LX_VALUE(VM_IOREMAP) + LX_VALUE(VM_ALLOC) +--- a/scripts/gdb/linux/interrupts.py ++++ b/scripts/gdb/linux/interrupts.py +@@ -7,7 +7,7 @@ import gdb + from linux import constants + from linux import cpus + from linux import utils +-from linux import radixtree ++from linux import mapletree + + irq_desc_type = utils.CachedType("struct irq_desc") + +@@ -23,12 +23,12 @@ def irqd_is_level(desc): + def show_irq_desc(prec, irq): + text = "" + +- desc = radixtree.lookup(gdb.parse_and_eval("&irq_desc_tree"), irq) ++ desc = mapletree.mtree_load(gdb.parse_and_eval("&sparse_irqs"), irq) + if desc is None: + return text + +- desc = desc.cast(irq_desc_type.get_type()) +- if desc is None: ++ desc = desc.cast(irq_desc_type.get_type().pointer()) ++ if desc == 0: + return text + + if irq_settings_is_hidden(desc): +@@ -221,8 +221,8 @@ class LxInterruptList(gdb.Command): + gdb.write("CPU%-8d" % cpu) + gdb.write("\n") + +- if utils.gdb_eval_or_none("&irq_desc_tree") is None: +- return ++ if utils.gdb_eval_or_none("&sparse_irqs") is None: ++ raise gdb.GdbError("Unable to find the sparse IRQ tree, is CONFIG_SPARSE_IRQ enabled?") + + for irq in range(nr_irqs): + gdb.write(show_irq_desc(prec, irq)) +--- /dev/null ++++ b/scripts/gdb/linux/mapletree.py +@@ -0,0 +1,252 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Maple tree helpers ++# ++# Copyright (c) 2025 Broadcom ++# ++# Authors: ++# Florian Fainelli ++ ++import gdb ++ ++from linux import utils ++from linux import constants ++from linux import xarray ++ ++maple_tree_root_type = utils.CachedType("struct maple_tree") ++maple_node_type = utils.CachedType("struct maple_node") ++maple_enode_type = utils.CachedType("void") ++ ++maple_dense = 0 ++maple_leaf_64 = 1 ++maple_range_64 = 2 ++maple_arange_64 = 3 ++ ++class Mas(object): ++ ma_active = 0 ++ ma_start = 1 ++ ma_root = 2 ++ ma_none = 3 ++ ma_pause = 4 ++ ma_overflow = 5 ++ ma_underflow = 6 ++ ma_error = 7 ++ ++ def __init__(self, mt, first, end): ++ if mt.type == maple_tree_root_type.get_type().pointer(): ++ self.tree = mt.dereference() ++ elif mt.type != maple_tree_root_type.get_type(): ++ raise gdb.GdbError("must be {} not {}" ++ .format(maple_tree_root_type.get_type().pointer(), mt.type)) ++ self.tree = mt ++ self.index = first ++ self.last = end ++ self.node = None ++ self.status = self.ma_start ++ self.min = 0 ++ self.max = -1 ++ ++ def is_start(self): ++ # mas_is_start() ++ return self.status == self.ma_start ++ ++ def is_ptr(self): ++ # mas_is_ptr() ++ return self.status == self.ma_root ++ ++ def is_none(self): ++ # mas_is_none() ++ return self.status == self.ma_none ++ ++ def root(self): ++ # mas_root() ++ return self.tree['ma_root'].cast(maple_enode_type.get_type().pointer()) ++ ++ def start(self): ++ # mas_start() ++ if self.is_start() is False: ++ return None ++ ++ self.min = 0 ++ self.max = ~0 ++ ++ while True: ++ self.depth = 0 ++ root = self.root() ++ if xarray.xa_is_node(root): ++ self.depth = 0 ++ self.status = self.ma_active ++ self.node = mte_safe_root(root) ++ self.offset = 0 ++ if mte_dead_node(self.node) is True: ++ continue ++ ++ return None ++ ++ self.node = None ++ # Empty tree ++ if root is None: ++ self.status = self.ma_none ++ self.offset = constants.LX_MAPLE_NODE_SLOTS ++ return None ++ ++ # Single entry tree ++ self.status = self.ma_root ++ self.offset = constants.LX_MAPLE_NODE_SLOTS ++ ++ if self.index != 0: ++ return None ++ ++ return root ++ ++ return None ++ ++ def reset(self): ++ # mas_reset() ++ self.status = self.ma_start ++ self.node = None ++ ++def mte_safe_root(node): ++ if node.type != maple_enode_type.get_type().pointer(): ++ raise gdb.GdbError("{} must be {} not {}" ++ .format(mte_safe_root.__name__, maple_enode_type.get_type().pointer(), node.type)) ++ ulong_type = utils.get_ulong_type() ++ indirect_ptr = node.cast(ulong_type) & ~0x2 ++ val = indirect_ptr.cast(maple_enode_type.get_type().pointer()) ++ return val ++ ++def mte_node_type(entry): ++ ulong_type = utils.get_ulong_type() ++ val = None ++ if entry.type == maple_enode_type.get_type().pointer(): ++ val = entry.cast(ulong_type) ++ elif entry.type == ulong_type: ++ val = entry ++ else: ++ raise gdb.GdbError("{} must be {} not {}" ++ .format(mte_node_type.__name__, maple_enode_type.get_type().pointer(), entry.type)) ++ return (val >> 0x3) & 0xf ++ ++def ma_dead_node(node): ++ if node.type != maple_node_type.get_type().pointer(): ++ raise gdb.GdbError("{} must be {} not {}" ++ .format(ma_dead_node.__name__, maple_node_type.get_type().pointer(), node.type)) ++ ulong_type = utils.get_ulong_type() ++ parent = node['parent'] ++ indirect_ptr = node['parent'].cast(ulong_type) & ~constants.LX_MAPLE_NODE_MASK ++ return indirect_ptr == node ++ ++def mte_to_node(enode): ++ ulong_type = utils.get_ulong_type() ++ if enode.type == maple_enode_type.get_type().pointer(): ++ indirect_ptr = enode.cast(ulong_type) ++ elif enode.type == ulong_type: ++ indirect_ptr = enode ++ else: ++ raise gdb.GdbError("{} must be {} not {}" ++ .format(mte_to_node.__name__, maple_enode_type.get_type().pointer(), enode.type)) ++ indirect_ptr = indirect_ptr & ~constants.LX_MAPLE_NODE_MASK ++ return indirect_ptr.cast(maple_node_type.get_type().pointer()) ++ ++def mte_dead_node(enode): ++ if enode.type != maple_enode_type.get_type().pointer(): ++ raise gdb.GdbError("{} must be {} not {}" ++ .format(mte_dead_node.__name__, maple_enode_type.get_type().pointer(), enode.type)) ++ node = mte_to_node(enode) ++ return ma_dead_node(node) ++ ++def ma_is_leaf(tp): ++ result = tp < maple_range_64 ++ return tp < maple_range_64 ++ ++def mt_pivots(t): ++ if t == maple_dense: ++ return 0 ++ elif t == maple_leaf_64 or t == maple_range_64: ++ return constants.LX_MAPLE_RANGE64_SLOTS - 1 ++ elif t == maple_arange_64: ++ return constants.LX_MAPLE_ARANGE64_SLOTS - 1 ++ ++def ma_pivots(node, t): ++ if node.type != maple_node_type.get_type().pointer(): ++ raise gdb.GdbError("{}: must be {} not {}" ++ .format(ma_pivots.__name__, maple_node_type.get_type().pointer(), node.type)) ++ if t == maple_arange_64: ++ return node['ma64']['pivot'] ++ elif t == maple_leaf_64 or t == maple_range_64: ++ return node['mr64']['pivot'] ++ else: ++ return None ++ ++def ma_slots(node, tp): ++ if node.type != maple_node_type.get_type().pointer(): ++ raise gdb.GdbError("{}: must be {} not {}" ++ .format(ma_slots.__name__, maple_node_type.get_type().pointer(), node.type)) ++ if tp == maple_arange_64: ++ return node['ma64']['slot'] ++ elif tp == maple_range_64 or tp == maple_leaf_64: ++ return node['mr64']['slot'] ++ elif tp == maple_dense: ++ return node['slot'] ++ else: ++ return None ++ ++def mt_slot(mt, slots, offset): ++ ulong_type = utils.get_ulong_type() ++ return slots[offset].cast(ulong_type) ++ ++def mtree_lookup_walk(mas): ++ ulong_type = utils.get_ulong_type() ++ n = mas.node ++ ++ while True: ++ node = mte_to_node(n) ++ tp = mte_node_type(n) ++ pivots = ma_pivots(node, tp) ++ end = mt_pivots(tp) ++ offset = 0 ++ while True: ++ if pivots[offset] >= mas.index: ++ break ++ if offset >= end: ++ break ++ offset += 1 ++ ++ slots = ma_slots(node, tp) ++ n = mt_slot(mas.tree, slots, offset) ++ if ma_dead_node(node) is True: ++ mas.reset() ++ return None ++ break ++ ++ if ma_is_leaf(tp) is True: ++ break ++ ++ return n ++ ++def mtree_load(mt, index): ++ ulong_type = utils.get_ulong_type() ++ # MT_STATE(...) ++ mas = Mas(mt, index, index) ++ entry = None ++ ++ while True: ++ entry = mas.start() ++ if mas.is_none(): ++ return None ++ ++ if mas.is_ptr(): ++ if index != 0: ++ entry = None ++ return entry ++ ++ entry = mtree_lookup_walk(mas) ++ if entry is None and mas.is_start(): ++ continue ++ else: ++ break ++ ++ if xarray.xa_is_zero(entry): ++ return None ++ ++ return entry +--- /dev/null ++++ b/scripts/gdb/linux/xarray.py +@@ -0,0 +1,28 @@ ++# SPDX-License-Identifier: GPL-2.0 ++# ++# Xarray helpers ++# ++# Copyright (c) 2025 Broadcom ++# ++# Authors: ++# Florian Fainelli ++ ++import gdb ++ ++from linux import utils ++from linux import constants ++ ++def xa_is_internal(entry): ++ ulong_type = utils.get_ulong_type() ++ return ((entry.cast(ulong_type) & 3) == 2) ++ ++def xa_mk_internal(v): ++ return ((v << 2) | 2) ++ ++def xa_is_zero(entry): ++ ulong_type = utils.get_ulong_type() ++ return entry.cast(ulong_type) == xa_mk_internal(257) ++ ++def xa_is_node(entry): ++ ulong_type = utils.get_ulong_type() ++ return xa_is_internal(entry) and (entry.cast(ulong_type) > 4096) diff --git a/queue-6.6/series b/queue-6.6/series index 8071f0b5d0..b729295e3a 100644 --- a/queue-6.6/series +++ b/queue-6.6/series @@ -49,3 +49,10 @@ usb-gadget-u_serial-fix-race-condition-in-tty-wakeup.patch revert-usb-gadget-u_serial-add-null-pointer-check-in-gs_start_io.patch drm-framebuffer-acquire-internal-references-on-gem-handles.patch revert-acpi-battery-negate-current-when-discharging.patch +kallsyms-fix-build-without-execinfo.patch +maple_tree-fix-mt_destroy_walk-on-root-leaf-node.patch +mm-fix-the-inaccurate-memory-statistics-issue-for-users.patch +scripts-gdb-fix-interrupts-display-after-mcp-on-x86.patch +scripts-gdb-de-reference-per-cpu-mce-interrupts.patch +scripts-gdb-fix-interrupts.py-after-maple-tree-conversion.patch +mm-vmalloc-leave-lazy-mmu-mode-on-pte-mapping-error.patch