* [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR @ 2025-04-23 1:48 Ye Liu 2025-04-23 9:45 ` Florian Weimer 2025-04-23 22:00 ` SeongJae Park 0 siblings, 2 replies; 9+ messages in thread From: Ye Liu @ 2025-04-23 1:48 UTC (permalink / raw) To: akpm Cc: linux-debuggers, linux-kernel, linux-mm, linux-toolchains, osandov, paulmck, sweettea-kernel, liuye, ye.liu From: Ye Liu <liuye@kylinos.cn> Introduces a new drgn script, `show_page_info.py`, which allows users to analyze the state of a page given a process ID (PID) and a virtual address (VADDR). This can help kernel developers or debuggers easily inspect page-related information in a live kernel or vmcore. The script extracts information such as the page flags, mapping, and other metadata relevant to diagnosing memory issues. Output example: sudo ./show_page_info.py 1 0x7f43df5acf00 PID: 1 Comm: systemd mm: 0xffff8881273bbc40 Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70 Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000 User Virtual Address: 0x7f43df5acf00 Page Address: 0xffffea00049a0b00 Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active| PG_private|PG_reported Page Size: 16384 Page PFN: 0x12682c Page Physical: 0x12682c000 Page Virtual: 0xffff88812682c000 Page Refcount: 37 Page Mapcount: 7 Page Index: 0x0 Page Memcg Data: 0xffff88812642c000 Memcg Name: init.scope Memcg Path: /sys/fs/cgroup/memory/init.scope Page Mapping: 0xffff88810f086a70 Page Anon/File: File Page VMA: 0xffff88810e4af3b8 VMA Start: 0x7f43df5ac000 VMA End: 0x7f43df5b0000 This page is part of a compound page. This page is the head page of a compound page. Head Page: 0xffffea00049a0b00 Compound Order: 2 Number of Pages: 4 Signed-off-by: Ye Liu <liuye@kylinos.cn> Changes in v3: - Adjust display style. - Link to v2:https://lore.kernel.org/all/20250421080748.114750-1-ye.liu@linux.dev/ Changes in v2: - Move the show_page_info.py file to tools/mm. - Link to v1: https://lore.kernel.org/all/20250415075024.248232-1-ye.liu@linux.dev/ --- MAINTAINERS | 5 ++ tools/mm/show_page_info.py | 120 +++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+) create mode 100755 tools/mm/show_page_info.py diff --git a/MAINTAINERS b/MAINTAINERS index 17ed0b5ffdd2..85686a30dc72 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -18351,6 +18351,11 @@ F: Documentation/mm/page_table_check.rst F: include/linux/page_table_check.h F: mm/page_table_check.c +PAGE STATE DEBUG SCRIPT +M: Ye Liu <liuye@kylinos.cn> +S: Maintained +F: tools/mm/show_page_info.py + PANASONIC LAPTOP ACPI EXTRAS DRIVER M: Kenneth Chan <kenneth.t.chan@gmail.com> L: platform-driver-x86@vger.kernel.org diff --git a/tools/mm/show_page_info.py b/tools/mm/show_page_info.py new file mode 100755 index 000000000000..8622c5499dfe --- /dev/null +++ b/tools/mm/show_page_info.py @@ -0,0 +1,120 @@ +#!/usr/bin/env drgn +# SPDX-License-Identifier: GPL-2.0-only +# Copyright (C) 2025 Ye Liu <liuye@kylinos.cn> + +import argparse +from drgn import Object +from drgn.helpers.linux import find_task, follow_page, page_size +from drgn.helpers.linux.mm import ( + decode_page_flags, page_to_pfn, page_to_phys, page_to_virt, vma_find, + PageSlab, PageCompound, PageHead, PageTail, compound_head, compound_order, compound_nr +) +from drgn.helpers.linux.cgroup import cgroup_name, cgroup_path + +DESC = """ +This is a drgn script to show the page state. +For more info on drgn, visit https://github.com/osandov/drgn. +""" + +MEMCG_DATA_OBJEXTS = 1 << 0 +MEMCG_DATA_KMEM = 1 << 1 +__NR_MEMCG_DATA_FLAGS = 1 << 2 + +def format_page_data(data): + """Format raw page data into a readable hex dump.""" + chunks = [data[i:i+8] for i in range(0, len(data), 8)] + hex_chunks = ["".join(f"{b:02x}" for b in chunk[::-1]) for chunk in chunks] + lines = [" ".join(hex_chunks[i:i+4]) for i in range(0, len(hex_chunks), 4)] + return "\n".join(f"Raw: {line}" for line in lines) + +def get_memcg_info(page): + """Retrieve memory cgroup information for a page.""" + memcg_data = page.memcg_data.value_() + if memcg_data & MEMCG_DATA_OBJEXTS: + memcg_value = 0 + elif memcg_data & MEMCG_DATA_KMEM: + objcg = Object(prog, "struct obj_cgroup *", address=memcg_data & ~__NR_MEMCG_DATA_FLAGS) + memcg_value = objcg.memcg.value_() + else: + memcg_value = memcg_data & ~__NR_MEMCG_DATA_FLAGS + + memcg = Object(prog, "struct mem_cgroup *", address=memcg_value) + cgrp = memcg.css.cgroup + return cgroup_name(cgrp).decode(), f"/sys/fs/cgroup/memory{cgroup_path(cgrp).decode()}" + +def show_page_state(page, addr, mm, pid, task): + """Display detailed information about a page.""" + print(f'PID: {pid} Comm: {task.comm.string_().decode()} mm: {hex(mm)}') + print(format_page_data(prog.read(page.value_(), 64))) + fields = { + "User Virtual Address": hex(addr), + "Page Address": hex(page.value_()), + "Page Flags": decode_page_flags(page), + "Page Size": page_size(page).value_(), + "Page PFN": hex(page_to_pfn(page).value_()), + "Page Physical": hex(page_to_phys(page).value_()), + "Page Virtual": hex(page_to_virt(page).value_()), + "Page Refcount": page._refcount.counter.value_(), + "Page Mapcount": page._mapcount.counter.value_(), + "Page Index": hex(page.index.value_()), + "Page Memcg Data": hex(page.memcg_data.value_()), + } + + memcg_name, memcg_path = get_memcg_info(page) + fields["Memcg Name"] = memcg_name + fields["Memcg Path"] = memcg_path + fields["Page Mapping"] = hex(page.mapping.value_()) + fields["Page Anon/File"] = "Anon" if page.mapping.value_() & 0x1 else "File" + + vma = vma_find(mm, addr) + fields["Page VMA"] = hex(vma.value_()) + fields["VMA Start"] = hex(vma.vm_start.value_()) + fields["VMA End"] = hex(vma.vm_end.value_()) + + # Calculate the maximum field name length for alignment + max_field_len = max(len(field) for field in fields) + + # Print aligned fields + for field, value in fields.items(): + print(f"{field}:".ljust(max_field_len + 2) + f"{value}") + + # Additional information about the page + if PageSlab(page): + print("This page belongs to the slab allocator.") + + if PageCompound(page): + print("This page is part of a compound page.") + if PageHead(page): + print("This page is the head page of a compound page.") + if PageTail(page): + print("This page is the tail page of a compound page.") + print(f"{'Head Page:'.ljust(max_field_len + 2)}{hex(compound_head(page).value_())}") + print(f"{'Compound Order:'.ljust(max_field_len + 2)}{compound_order(page).value_()}") + print(f"{'Number of Pages:'.ljust(max_field_len + 2)}{compound_nr(page).value_()}") + else: + print("This page is not part of a compound page.") + +def main(): + """Main function to parse arguments and display page state.""" + parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawTextHelpFormatter) + parser.add_argument('pid', metavar='PID', type=int, help='Target process ID (PID)') + parser.add_argument('vaddr', metavar='VADDR', type=str, help='Target virtual address in hexadecimal format (e.g., 0x7fff1234abcd)') + args = parser.parse_args() + + try: + vaddr = int(args.vaddr, 16) + except ValueError: + print(f"Error: Invalid virtual address format: {args.vaddr}") + return + + task = find_task(args.pid) + mm = task.mm + page = follow_page(mm, vaddr) + + if page: + show_page_state(page, vaddr, mm, args.pid, task) + else: + print(f"Address {hex(vaddr)} is not mapped.") + +if __name__ == "__main__": + main() \ No newline at end of file -- 2.25.1 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR 2025-04-23 1:48 [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR Ye Liu @ 2025-04-23 9:45 ` Florian Weimer 2025-04-24 2:17 ` Ye Liu 2025-04-23 22:00 ` SeongJae Park 1 sibling, 1 reply; 9+ messages in thread From: Florian Weimer @ 2025-04-23 9:45 UTC (permalink / raw) To: Ye Liu Cc: akpm, linux-debuggers, linux-kernel, linux-mm, linux-toolchains, osandov, paulmck, sweettea-kernel, liuye * Ye Liu: > From: Ye Liu <liuye@kylinos.cn> > > Introduces a new drgn script, `show_page_info.py`, which allows users > to analyze the state of a page given a process ID (PID) and a virtual > address (VADDR). This can help kernel developers or debuggers easily > inspect page-related information in a live kernel or vmcore. > > The script extracts information such as the page flags, mapping, and > other metadata relevant to diagnosing memory issues. > > Output example: > sudo ./show_page_info.py 1 0x7f43df5acf00 > PID: 1 Comm: systemd mm: 0xffff8881273bbc40 > Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70 > Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000 > User Virtual Address: 0x7f43df5acf00 > Page Address: 0xffffea00049a0b00 > Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active| > PG_private|PG_reported > Page Size: 16384 > Page PFN: 0x12682c > Page Physical: 0x12682c000 > Page Virtual: 0xffff88812682c000 > Page Refcount: 37 > Page Mapcount: 7 > Page Index: 0x0 > Page Memcg Data: 0xffff88812642c000 > Memcg Name: init.scope > Memcg Path: /sys/fs/cgroup/memory/init.scope > Page Mapping: 0xffff88810f086a70 > Page Anon/File: File > Page VMA: 0xffff88810e4af3b8 > VMA Start: 0x7f43df5ac000 > VMA End: 0x7f43df5b0000 > This page is part of a compound page. > This page is the head page of a compound page. > Head Page: 0xffffea00049a0b00 > Compound Order: 2 > Number of Pages: 4 Does this show the page access flags anywhere in the output? If not, would it be possible to include this information? Thanks, Florian ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR 2025-04-23 9:45 ` Florian Weimer @ 2025-04-24 2:17 ` Ye Liu 0 siblings, 0 replies; 9+ messages in thread From: Ye Liu @ 2025-04-24 2:17 UTC (permalink / raw) To: Florian Weimer Cc: akpm, linux-debuggers, linux-kernel, linux-mm, linux-toolchains, osandov, paulmck, sweettea-kernel, liuye 在 2025/4/23 17:45, Florian Weimer 写道: > * Ye Liu: > >> From: Ye Liu <liuye@kylinos.cn> >> >> Introduces a new drgn script, `show_page_info.py`, which allows users >> to analyze the state of a page given a process ID (PID) and a virtual >> address (VADDR). This can help kernel developers or debuggers easily >> inspect page-related information in a live kernel or vmcore. >> >> The script extracts information such as the page flags, mapping, and >> other metadata relevant to diagnosing memory issues. >> >> Output example: >> sudo ./show_page_info.py 1 0x7f43df5acf00 >> PID: 1 Comm: systemd mm: 0xffff8881273bbc40 >> Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70 >> Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000 >> User Virtual Address: 0x7f43df5acf00 >> Page Address: 0xffffea00049a0b00 >> Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active| >> PG_private|PG_reported >> Page Size: 16384 >> Page PFN: 0x12682c >> Page Physical: 0x12682c000 >> Page Virtual: 0xffff88812682c000 >> Page Refcount: 37 >> Page Mapcount: 7 >> Page Index: 0x0 >> Page Memcg Data: 0xffff88812642c000 >> Memcg Name: init.scope >> Memcg Path: /sys/fs/cgroup/memory/init.scope >> Page Mapping: 0xffff88810f086a70 >> Page Anon/File: File >> Page VMA: 0xffff88810e4af3b8 >> VMA Start: 0x7f43df5ac000 >> VMA End: 0x7f43df5b0000 >> This page is part of a compound page. >> This page is the head page of a compound page. >> Head Page: 0xffffea00049a0b00 >> Compound Order: 2 >> Number of Pages: 4 > Does this show the page access flags anywhere in the output? If not, > would it be possible to include this information? This script is currently a basic version, and we plan to gradually add more detailed information about pages, including the page access flags you mentioned, as well as PGD, PUD, PMD, PTE, file/anon rmap folios, and more. This will be refined over time. Thanks, Ye Liu > Thanks, > Florian > ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR 2025-04-23 1:48 [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR Ye Liu 2025-04-23 9:45 ` Florian Weimer @ 2025-04-23 22:00 ` SeongJae Park 2025-04-24 1:55 ` Ye Liu 1 sibling, 1 reply; 9+ messages in thread From: SeongJae Park @ 2025-04-23 22:00 UTC (permalink / raw) To: Ye Liu Cc: SeongJae Park, akpm, linux-debuggers, linux-kernel, linux-mm, linux-toolchains, osandov, paulmck, sweettea-kernel, liuye On Wed, 23 Apr 2025 09:48:50 +0800 Ye Liu <ye.liu@linux.dev> wrote: > From: Ye Liu <liuye@kylinos.cn> > > Introduces a new drgn script, `show_page_info.py`, which allows users > to analyze the state of a page given a process ID (PID) and a virtual > address (VADDR). This can help kernel developers or debuggers easily > inspect page-related information in a live kernel or vmcore. > > The script extracts information such as the page flags, mapping, and > other metadata relevant to diagnosing memory issues. > > Output example: > sudo ./show_page_info.py 1 0x7f43df5acf00 > PID: 1 Comm: systemd mm: 0xffff8881273bbc40 > Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70 > Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000 > User Virtual Address: 0x7f43df5acf00 > Page Address: 0xffffea00049a0b00 > Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active| > PG_private|PG_reported > Page Size: 16384 Should this be called folio size? Or, could this simply removed since Compound Order is given below? > Page PFN: 0x12682c > Page Physical: 0x12682c000 > Page Virtual: 0xffff88812682c000 > Page Refcount: 37 > Page Mapcount: 7 > Page Index: 0x0 > Page Memcg Data: 0xffff88812642c000 > Memcg Name: init.scope > Memcg Path: /sys/fs/cgroup/memory/init.scope > Page Mapping: 0xffff88810f086a70 > Page Anon/File: File > Page VMA: 0xffff88810e4af3b8 > VMA Start: 0x7f43df5ac000 > VMA End: 0x7f43df5b0000 > This page is part of a compound page. > This page is the head page of a compound page. > Head Page: 0xffffea00049a0b00 > Compound Order: 2 > Number of Pages: 4 > > Signed-off-by: Ye Liu <liuye@kylinos.cn> > > Changes in v3: > - Adjust display style. > - Link to v2:https://lore.kernel.org/all/20250421080748.114750-1-ye.liu@linux.dev/ > > Changes in v2: > - Move the show_page_info.py file to tools/mm. > - Link to v1: https://lore.kernel.org/all/20250415075024.248232-1-ye.liu@linux.dev/ > --- > MAINTAINERS | 5 ++ > tools/mm/show_page_info.py | 120 +++++++++++++++++++++++++++++++++++++ > 2 files changed, 125 insertions(+) > create mode 100755 tools/mm/show_page_info.py > > diff --git a/MAINTAINERS b/MAINTAINERS > index 17ed0b5ffdd2..85686a30dc72 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -18351,6 +18351,11 @@ F: Documentation/mm/page_table_check.rst > F: include/linux/page_table_check.h > F: mm/page_table_check.c > > +PAGE STATE DEBUG SCRIPT > +M: Ye Liu <liuye@kylinos.cn> > +S: Maintained > +F: tools/mm/show_page_info.py > + > PANASONIC LAPTOP ACPI EXTRAS DRIVER > M: Kenneth Chan <kenneth.t.chan@gmail.com> > L: platform-driver-x86@vger.kernel.org > diff --git a/tools/mm/show_page_info.py b/tools/mm/show_page_info.py > new file mode 100755 > index 000000000000..8622c5499dfe > --- /dev/null > +++ b/tools/mm/show_page_info.py [...] > +def main(): > + """Main function to parse arguments and display page state.""" > + parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawTextHelpFormatter) > + parser.add_argument('pid', metavar='PID', type=int, help='Target process ID (PID)') > + parser.add_argument('vaddr', metavar='VADDR', type=str, help='Target virtual address in hexadecimal format (e.g., 0x7fff1234abcd)') > + args = parser.parse_args() > + > + try: > + vaddr = int(args.vaddr, 16) > + except ValueError: > + print(f"Error: Invalid virtual address format: {args.vaddr}") > + return > + > + task = find_task(args.pid) > + mm = task.mm > + page = follow_page(mm, vaddr) I tried this script on my test machine and got the below error: $ cat ./a.c #include <stdio.h> int main(void) { int foo; printf("hello\n"); printf("%x\n", &foo); scanf("%d\n", &foo); return 0; } $ gcc ./a.c $ ./a.out & [2] 45666 hello f7eb7c0c $ sudo ./tools/mm/show_page_info.py 45666 0xf7eb7c0c Traceback (most recent call last): File "/usr/local/bin/drgn", line 33, in <module> sys.exit(load_entry_point('drgn==0.0.30+82.ge2b60e4b', 'console_scripts', 'drgn')()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/cli.py", line 461, in _main runpy.run_path(script, init_globals={"prog": prog}, run_name="__main__") File "<frozen runpy>", line 291, in run_path File "<frozen runpy>", line 98, in _run_module_code File "<frozen runpy>", line 88, in _run_code File "./tools/mm/show_page_info.py", line 120, in <module> main() File "./tools/mm/show_page_info.py", line 112, in main page = follow_page(mm, vaddr) ^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/mm.py", line 1068, in follow_page return phys_to_page(follow_phys(mm, addr)) ^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/mm.py", line 1109, in follow_phys return Object(prog, "phys_addr_t", _linux_helper_follow_phys(prog, mm.pgd, addr)) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ _drgn.FaultError: address is not mapped: 0xf7eb7c0c Am I doing something wrong? Thanks, SJ [...] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR 2025-04-23 22:00 ` SeongJae Park @ 2025-04-24 1:55 ` Ye Liu 2025-04-24 2:51 ` SeongJae Park 0 siblings, 1 reply; 9+ messages in thread From: Ye Liu @ 2025-04-24 1:55 UTC (permalink / raw) To: SeongJae Park Cc: akpm, linux-debuggers, linux-kernel, linux-mm, linux-toolchains, osandov, paulmck, sweettea-kernel, liuye 在 2025/4/24 06:00, SeongJae Park 写道: > On Wed, 23 Apr 2025 09:48:50 +0800 Ye Liu <ye.liu@linux.dev> wrote: > >> From: Ye Liu <liuye@kylinos.cn> >> >> Introduces a new drgn script, `show_page_info.py`, which allows users >> to analyze the state of a page given a process ID (PID) and a virtual >> address (VADDR). This can help kernel developers or debuggers easily >> inspect page-related information in a live kernel or vmcore. >> >> The script extracts information such as the page flags, mapping, and >> other metadata relevant to diagnosing memory issues. >> >> Output example: >> sudo ./show_page_info.py 1 0x7f43df5acf00 >> PID: 1 Comm: systemd mm: 0xffff8881273bbc40 >> Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70 >> Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000 >> User Virtual Address: 0x7f43df5acf00 >> Page Address: 0xffffea00049a0b00 >> Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active| >> PG_private|PG_reported >> Page Size: 16384 > Should this be called folio size? Or, could this simply removed since Compound > Order is given below? Page size refers to the base page size, which equals PAGESIZE. Folio size can be calculated using the Compound Order, but of course, it can also be shown directly as a result. >> Page PFN: 0x12682c >> Page Physical: 0x12682c000 >> Page Virtual: 0xffff88812682c000 >> Page Refcount: 37 >> Page Mapcount: 7 >> Page Index: 0x0 >> Page Memcg Data: 0xffff88812642c000 >> Memcg Name: init.scope >> Memcg Path: /sys/fs/cgroup/memory/init.scope >> Page Mapping: 0xffff88810f086a70 >> Page Anon/File: File >> Page VMA: 0xffff88810e4af3b8 >> VMA Start: 0x7f43df5ac000 >> VMA End: 0x7f43df5b0000 >> This page is part of a compound page. >> This page is the head page of a compound page. >> Head Page: 0xffffea00049a0b00 >> Compound Order: 2 >> Number of Pages: 4 >> >> Signed-off-by: Ye Liu <liuye@kylinos.cn> >> >> Changes in v3: >> - Adjust display style. >> - Link to v2:https://lore.kernel.org/all/20250421080748.114750-1-ye.liu@linux.dev/ >> >> Changes in v2: >> - Move the show_page_info.py file to tools/mm. >> - Link to v1: https://lore.kernel.org/all/20250415075024.248232-1-ye.liu@linux.dev/ >> --- >> MAINTAINERS | 5 ++ >> tools/mm/show_page_info.py | 120 +++++++++++++++++++++++++++++++++++++ >> 2 files changed, 125 insertions(+) >> create mode 100755 tools/mm/show_page_info.py >> >> diff --git a/MAINTAINERS b/MAINTAINERS >> index 17ed0b5ffdd2..85686a30dc72 100644 >> --- a/MAINTAINERS >> +++ b/MAINTAINERS >> @@ -18351,6 +18351,11 @@ F: Documentation/mm/page_table_check.rst >> F: include/linux/page_table_check.h >> F: mm/page_table_check.c >> >> +PAGE STATE DEBUG SCRIPT >> +M: Ye Liu <liuye@kylinos.cn> >> +S: Maintained >> +F: tools/mm/show_page_info.py >> + >> PANASONIC LAPTOP ACPI EXTRAS DRIVER >> M: Kenneth Chan <kenneth.t.chan@gmail.com> >> L: platform-driver-x86@vger.kernel.org >> diff --git a/tools/mm/show_page_info.py b/tools/mm/show_page_info.py >> new file mode 100755 >> index 000000000000..8622c5499dfe >> --- /dev/null >> +++ b/tools/mm/show_page_info.py > [...] >> +def main(): >> + """Main function to parse arguments and display page state.""" >> + parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawTextHelpFormatter) >> + parser.add_argument('pid', metavar='PID', type=int, help='Target process ID (PID)') >> + parser.add_argument('vaddr', metavar='VADDR', type=str, help='Target virtual address in hexadecimal format (e.g., 0x7fff1234abcd)') >> + args = parser.parse_args() >> + >> + try: >> + vaddr = int(args.vaddr, 16) >> + except ValueError: >> + print(f"Error: Invalid virtual address format: {args.vaddr}") >> + return >> + >> + task = find_task(args.pid) >> + mm = task.mm >> + page = follow_page(mm, vaddr) > I tried this script on my test machine and got the below error: > > $ cat ./a.c > #include <stdio.h> > > int main(void) > { > int foo; > printf("hello\n"); > printf("%x\n", &foo); To avoid address truncation, you can use the %p format specifier instead of %x or %lx when printing a pointer (memory address). Thanks, Ye Liu > scanf("%d\n", &foo); > return 0; > } > $ gcc ./a.c > $ ./a.out & > [2] 45666 > hello > f7eb7c0c > > $ sudo ./tools/mm/show_page_info.py 45666 0xf7eb7c0c > Traceback (most recent call last): > File "/usr/local/bin/drgn", line 33, in <module> > sys.exit(load_entry_point('drgn==0.0.30+82.ge2b60e4b', 'console_scripts', 'drgn')()) > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/cli.py", line 461, in _main > runpy.run_path(script, init_globals={"prog": prog}, run_name="__main__") > File "<frozen runpy>", line 291, in run_path > File "<frozen runpy>", line 98, in _run_module_code > File "<frozen runpy>", line 88, in _run_code > File "./tools/mm/show_page_info.py", line 120, in <module> > main() > File "./tools/mm/show_page_info.py", line 112, in main > page = follow_page(mm, vaddr) > ^^^^^^^^^^^^^^^^^^^^^^ > File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/mm.py", line 1068, in follow_page > return phys_to_page(follow_phys(mm, addr)) > ^^^^^^^^^^^^^^^^^^^^^ > File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/mm.py", line 1109, in follow_phys > return Object(prog, "phys_addr_t", _linux_helper_follow_phys(prog, mm.pgd, addr)) > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > _drgn.FaultError: address is not mapped: 0xf7eb7c0c > > Am I doing something wrong? > > > Thanks, > SJ > > [...] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR 2025-04-24 1:55 ` Ye Liu @ 2025-04-24 2:51 ` SeongJae Park 2025-04-24 3:24 ` Ye Liu 2025-04-24 3:27 ` Ye Liu 0 siblings, 2 replies; 9+ messages in thread From: SeongJae Park @ 2025-04-24 2:51 UTC (permalink / raw) To: Ye Liu Cc: SeongJae Park, akpm, linux-debuggers, linux-kernel, linux-mm, linux-toolchains, osandov, paulmck, sweettea-kernel, liuye On Thu, 24 Apr 2025 09:55:22 +0800 Ye Liu <ye.liu@linux.dev> wrote: > > 在 2025/4/24 06:00, SeongJae Park 写道: > > On Wed, 23 Apr 2025 09:48:50 +0800 Ye Liu <ye.liu@linux.dev> wrote: > > > >> From: Ye Liu <liuye@kylinos.cn> > >> > >> Introduces a new drgn script, `show_page_info.py`, which allows users > >> to analyze the state of a page given a process ID (PID) and a virtual > >> address (VADDR). This can help kernel developers or debuggers easily > >> inspect page-related information in a live kernel or vmcore. > >> > >> The script extracts information such as the page flags, mapping, and > >> other metadata relevant to diagnosing memory issues. > >> > >> Output example: > >> sudo ./show_page_info.py 1 0x7f43df5acf00 > >> PID: 1 Comm: systemd mm: 0xffff8881273bbc40 > >> Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70 > >> Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000 > >> User Virtual Address: 0x7f43df5acf00 > >> Page Address: 0xffffea00049a0b00 > >> Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active| > >> PG_private|PG_reported > >> Page Size: 16384 > > Should this be called folio size? Or, could this simply removed since Compound > > Order is given below? > > > Page size refers to the base page size, which equals PAGESIZE. Shouldn't 'prog["PAGE_SIZE"]' is used for what you are saying? This tool is using drgn.helpers.linux.page_size()[1] to print this, though? +def show_page_state(page, addr, mm, pid, task): + """Display detailed information about a page.""" + print(f'PID: {pid} Comm: {task.comm.string_().decode()} mm: {hex(mm)}') + print(format_page_data(prog.read(page.value_(), 64))) + fields = { + "User Virtual Address": hex(addr), + "Page Address": hex(page.value_()), + "Page Flags": decode_page_flags(page), + "Page Size": page_size(page).value_(), [1] https://drgn.readthedocs.io/en/stable/helpers.html#drgn.helpers.linux.mm.page_size > Folio size can be calculated using the Compound Order, but of course, > it can also be shown directly as a result. > > >> Page PFN: 0x12682c > >> Page Physical: 0x12682c000 > >> Page Virtual: 0xffff88812682c000 > >> Page Refcount: 37 > >> Page Mapcount: 7 > >> Page Index: 0x0 > >> Page Memcg Data: 0xffff88812642c000 > >> Memcg Name: init.scope > >> Memcg Path: /sys/fs/cgroup/memory/init.scope > >> Page Mapping: 0xffff88810f086a70 > >> Page Anon/File: File > >> Page VMA: 0xffff88810e4af3b8 > >> VMA Start: 0x7f43df5ac000 > >> VMA End: 0x7f43df5b0000 > >> This page is part of a compound page. > >> This page is the head page of a compound page. > >> Head Page: 0xffffea00049a0b00 > >> Compound Order: 2 > >> Number of Pages: 4 > >> > >> Signed-off-by: Ye Liu <liuye@kylinos.cn> > >> > >> Changes in v3: > >> - Adjust display style. > >> - Link to v2:https://lore.kernel.org/all/20250421080748.114750-1-ye.liu@linux.dev/ > >> > >> Changes in v2: > >> - Move the show_page_info.py file to tools/mm. > >> - Link to v1: https://lore.kernel.org/all/20250415075024.248232-1-ye.liu@linux.dev/ > >> --- > >> MAINTAINERS | 5 ++ > >> tools/mm/show_page_info.py | 120 +++++++++++++++++++++++++++++++++++++ > >> 2 files changed, 125 insertions(+) > >> create mode 100755 tools/mm/show_page_info.py > >> > >> diff --git a/MAINTAINERS b/MAINTAINERS > >> index 17ed0b5ffdd2..85686a30dc72 100644 > >> --- a/MAINTAINERS > >> +++ b/MAINTAINERS > >> @@ -18351,6 +18351,11 @@ F: Documentation/mm/page_table_check.rst > >> F: include/linux/page_table_check.h > >> F: mm/page_table_check.c > >> > >> +PAGE STATE DEBUG SCRIPT > >> +M: Ye Liu <liuye@kylinos.cn> > >> +S: Maintained > >> +F: tools/mm/show_page_info.py > >> + > >> PANASONIC LAPTOP ACPI EXTRAS DRIVER > >> M: Kenneth Chan <kenneth.t.chan@gmail.com> > >> L: platform-driver-x86@vger.kernel.org > >> diff --git a/tools/mm/show_page_info.py b/tools/mm/show_page_info.py > >> new file mode 100755 > >> index 000000000000..8622c5499dfe > >> --- /dev/null > >> +++ b/tools/mm/show_page_info.py > > [...] > >> +def main(): > >> + """Main function to parse arguments and display page state.""" > >> + parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawTextHelpFormatter) > >> + parser.add_argument('pid', metavar='PID', type=int, help='Target process ID (PID)') > >> + parser.add_argument('vaddr', metavar='VADDR', type=str, help='Target virtual address in hexadecimal format (e.g., 0x7fff1234abcd)') > >> + args = parser.parse_args() > >> + > >> + try: > >> + vaddr = int(args.vaddr, 16) > >> + except ValueError: > >> + print(f"Error: Invalid virtual address format: {args.vaddr}") > >> + return > >> + > >> + task = find_task(args.pid) > >> + mm = task.mm > >> + page = follow_page(mm, vaddr) > > I tried this script on my test machine and got the below error: > > > > $ cat ./a.c > > #include <stdio.h> > > > > int main(void) > > { > > int foo; > > printf("hello\n"); > > printf("%x\n", &foo); > > To avoid address truncation, you can use the %p format specifier > instead of %x or %lx when printing a pointer (memory address). Ah, you're correct, thank you. After fixing my test, the error I reported before is disappeared. But I think the follow_page() error handling would better to be updated to catch the exception and provide a better error message? Also, I'm getting below new error: $ sudo ./tools/mm/show_page_info.py 47657 0x7fffaf925b6c PID: 47657 Comm: a.out mm: 0xffff959c8a022100 Raw: 0017ffffc0020828 ffffea6b0c201408 ffffea6b0fc65648 ffff959d32bec9c1 Raw: 00000007fffffffc 0000000000000000 0000000100000000 ffff959cba058000 Traceback (most recent call last): File "/usr/local/bin/drgn", line 33, in <module> sys.exit(load_entry_point('drgn==0.0.30+82.ge2b60e4b', 'console_scripts', 'drgn')()) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/cli.py", line 461, in _main runpy.run_path(script, init_globals={"prog": prog}, run_name="__main__") File "<frozen runpy>", line 291, in run_path File "<frozen runpy>", line 98, in _run_module_code File "<frozen runpy>", line 88, in _run_code File "./tools/mm/show_page_info.py", line 120, in <module> main() File "./tools/mm/show_page_info.py", line 115, in main show_page_state(page, vaddr, mm, args.pid, task) File "./tools/mm/show_page_info.py", line 63, in show_page_state memcg_name, memcg_path = get_memcg_info(page) ^^^^^^^^^^^^^^^^^^^^ File "./tools/mm/show_page_info.py", line 43, in get_memcg_info return cgroup_name(cgrp).decode(), f"/sys/fs/cgroup/memory{cgroup_path(cgrp).decode()}" ^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/cgroup.py", line 71, in cgroup_name return kernfs_name(cgrp.kn) ^^^^^^^^^^^^^^^^^^^^ File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/kernfs.py", line 32, in kernfs_name return kn.name.string_() if kn.parent else b"/" ^^^^^^^^^ AttributeError: 'struct kernfs_node' has no member 'parent'. Did you mean: '__parent'? Seems not entirely this script's fault but due to the recent 'struct kernfs_node' change or my old version of drgn? But anyway, I think it is better to provide a better error message to users. I'm also curious if you have a plan for finding and fixing or avoiding this kind of future breakages. Thanks, SJ [...] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR 2025-04-24 2:51 ` SeongJae Park @ 2025-04-24 3:24 ` Ye Liu 2025-04-24 3:49 ` SeongJae Park 2025-04-24 3:27 ` Ye Liu 1 sibling, 1 reply; 9+ messages in thread From: Ye Liu @ 2025-04-24 3:24 UTC (permalink / raw) To: SeongJae Park Cc: akpm, linux-debuggers, linux-kernel, linux-mm, linux-toolchains, osandov, paulmck, sweettea-kernel, liuye 在 2025/4/24 10:51, SeongJae Park 写道: > On Thu, 24 Apr 2025 09:55:22 +0800 Ye Liu <ye.liu@linux.dev> wrote: > >> 在 2025/4/24 06:00, SeongJae Park 写道: >>> On Wed, 23 Apr 2025 09:48:50 +0800 Ye Liu <ye.liu@linux.dev> wrote: >>> >>>> From: Ye Liu <liuye@kylinos.cn> >>>> >>>> Introduces a new drgn script, `show_page_info.py`, which allows users >>>> to analyze the state of a page given a process ID (PID) and a virtual >>>> address (VADDR). This can help kernel developers or debuggers easily >>>> inspect page-related information in a live kernel or vmcore. >>>> >>>> The script extracts information such as the page flags, mapping, and >>>> other metadata relevant to diagnosing memory issues. >>>> >>>> Output example: >>>> sudo ./show_page_info.py 1 0x7f43df5acf00 >>>> PID: 1 Comm: systemd mm: 0xffff8881273bbc40 >>>> Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70 >>>> Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000 >>>> User Virtual Address: 0x7f43df5acf00 >>>> Page Address: 0xffffea00049a0b00 >>>> Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active| >>>> PG_private|PG_reported >>>> Page Size: 16384 >>> Should this be called folio size? Or, could this simply removed since Compound >>> Order is given below? >> >> Page size refers to the base page size, which equals PAGESIZE. > Shouldn't 'prog["PAGE_SIZE"]' is used for what you are saying? This tool is > using drgn.helpers.linux.page_size()[1] to print this, though? > > +def show_page_state(page, addr, mm, pid, task): > + """Display detailed information about a page.""" > + print(f'PID: {pid} Comm: {task.comm.string_().decode()} mm: {hex(mm)}') > + print(format_page_data(prog.read(page.value_(), 64))) > + fields = { > + "User Virtual Address": hex(addr), > + "Page Address": hex(page.value_()), > + "Page Flags": decode_page_flags(page), > + "Page Size": page_size(page).value_(), > > [1] https://drgn.readthedocs.io/en/stable/helpers.html#drgn.helpers.linux.mm.page_size > >> Folio size can be calculated using the Compound Order, but of course, >> it can also be shown directly as a result. >> >>>> Page PFN: 0x12682c >>>> Page Physical: 0x12682c000 >>>> Page Virtual: 0xffff88812682c000 >>>> Page Refcount: 37 >>>> Page Mapcount: 7 >>>> Page Index: 0x0 >>>> Page Memcg Data: 0xffff88812642c000 >>>> Memcg Name: init.scope >>>> Memcg Path: /sys/fs/cgroup/memory/init.scope >>>> Page Mapping: 0xffff88810f086a70 >>>> Page Anon/File: File >>>> Page VMA: 0xffff88810e4af3b8 >>>> VMA Start: 0x7f43df5ac000 >>>> VMA End: 0x7f43df5b0000 >>>> This page is part of a compound page. >>>> This page is the head page of a compound page. >>>> Head Page: 0xffffea00049a0b00 >>>> Compound Order: 2 >>>> Number of Pages: 4 >>>> >>>> Signed-off-by: Ye Liu <liuye@kylinos.cn> >>>> >>>> Changes in v3: >>>> - Adjust display style. >>>> - Link to v2:https://lore.kernel.org/all/20250421080748.114750-1-ye.liu@linux.dev/ >>>> >>>> Changes in v2: >>>> - Move the show_page_info.py file to tools/mm. >>>> - Link to v1: https://lore.kernel.org/all/20250415075024.248232-1-ye.liu@linux.dev/ >>>> --- >>>> MAINTAINERS | 5 ++ >>>> tools/mm/show_page_info.py | 120 +++++++++++++++++++++++++++++++++++++ >>>> 2 files changed, 125 insertions(+) >>>> create mode 100755 tools/mm/show_page_info.py >>>> >>>> diff --git a/MAINTAINERS b/MAINTAINERS >>>> index 17ed0b5ffdd2..85686a30dc72 100644 >>>> --- a/MAINTAINERS >>>> +++ b/MAINTAINERS >>>> @@ -18351,6 +18351,11 @@ F: Documentation/mm/page_table_check.rst >>>> F: include/linux/page_table_check.h >>>> F: mm/page_table_check.c >>>> >>>> +PAGE STATE DEBUG SCRIPT >>>> +M: Ye Liu <liuye@kylinos.cn> >>>> +S: Maintained >>>> +F: tools/mm/show_page_info.py >>>> + >>>> PANASONIC LAPTOP ACPI EXTRAS DRIVER >>>> M: Kenneth Chan <kenneth.t.chan@gmail.com> >>>> L: platform-driver-x86@vger.kernel.org >>>> diff --git a/tools/mm/show_page_info.py b/tools/mm/show_page_info.py >>>> new file mode 100755 >>>> index 000000000000..8622c5499dfe >>>> --- /dev/null >>>> +++ b/tools/mm/show_page_info.py >>> [...] >>>> +def main(): >>>> + """Main function to parse arguments and display page state.""" >>>> + parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawTextHelpFormatter) >>>> + parser.add_argument('pid', metavar='PID', type=int, help='Target process ID (PID)') >>>> + parser.add_argument('vaddr', metavar='VADDR', type=str, help='Target virtual address in hexadecimal format (e.g., 0x7fff1234abcd)') >>>> + args = parser.parse_args() >>>> + >>>> + try: >>>> + vaddr = int(args.vaddr, 16) >>>> + except ValueError: >>>> + print(f"Error: Invalid virtual address format: {args.vaddr}") >>>> + return >>>> + >>>> + task = find_task(args.pid) >>>> + mm = task.mm >>>> + page = follow_page(mm, vaddr) >>> I tried this script on my test machine and got the below error: >>> >>> $ cat ./a.c >>> #include <stdio.h> >>> >>> int main(void) >>> { >>> int foo; >>> printf("hello\n"); >>> printf("%x\n", &foo); >> To avoid address truncation, you can use the %p format specifier >> instead of %x or %lx when printing a pointer (memory address). > Ah, you're correct, thank you. After fixing my test, the error I reported > before is disappeared. But I think the follow_page() error handling would > better to be updated to catch the exception and provide a better error message? You're absolutely right, I initially overlooked the error handling in follow_page(). I’ll update it to catch exceptions and provide clearer, more user-friendly error messages. > Also, I'm getting below new error: > > $ sudo ./tools/mm/show_page_info.py 47657 0x7fffaf925b6c > PID: 47657 Comm: a.out mm: 0xffff959c8a022100 > Raw: 0017ffffc0020828 ffffea6b0c201408 ffffea6b0fc65648 ffff959d32bec9c1 > Raw: 00000007fffffffc 0000000000000000 0000000100000000 ffff959cba058000 > Traceback (most recent call last): > File "/usr/local/bin/drgn", line 33, in <module> > sys.exit(load_entry_point('drgn==0.0.30+82.ge2b60e4b', 'console_scripts', 'drgn')()) > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/cli.py", line 461, in _main > runpy.run_path(script, init_globals={"prog": prog}, run_name="__main__") > File "<frozen runpy>", line 291, in run_path > File "<frozen runpy>", line 98, in _run_module_code > File "<frozen runpy>", line 88, in _run_code > File "./tools/mm/show_page_info.py", line 120, in <module> > main() > File "./tools/mm/show_page_info.py", line 115, in main > show_page_state(page, vaddr, mm, args.pid, task) > File "./tools/mm/show_page_info.py", line 63, in show_page_state > memcg_name, memcg_path = get_memcg_info(page) > ^^^^^^^^^^^^^^^^^^^^ > File "./tools/mm/show_page_info.py", line 43, in get_memcg_info > return cgroup_name(cgrp).decode(), f"/sys/fs/cgroup/memory{cgroup_path(cgrp).decode()}" > ^^^^^^^^^^^^^^^^^ > File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/cgroup.py", line 71, in cgroup_name > return kernfs_name(cgrp.kn) > ^^^^^^^^^^^^^^^^^^^^ > File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/kernfs.py", line 32, in kernfs_name > return kn.name.string_() if kn.parent else b"/" > ^^^^^^^^^ > AttributeError: 'struct kernfs_node' has no member 'parent'. Did you mean: '__parent'? > > Seems not entirely this script's fault but due to the recent 'struct > kernfs_node' change or my old version of drgn? But anyway, I think it is > better to provide a better error message to users. I'm also curious if you > have a plan for finding and fixing or avoiding this kind of future breakages. As for the new error you encountered, it does appear to stem from a recent change to the struct kernfs_node, or possibly from a mismatch between kernel headers and the drgn version. While it may not be a bug in the script itself, I agree that the script should handle such scenarios more gracefully. Regarding compatibility across versions, this is definitely something worth paying attention to. Currently, the script is being adapted based on the latest drgn and kernel versions. If future changes to kernel structures occur, I plan to patch the script accordingly to maintain compatibility. That said, I’m very open to suggestions — do you have any ideas on how we could better detect or guard against these kinds of breakages proactively? Thanks again for raising this! Thanks, Ye Liu ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR 2025-04-24 3:24 ` Ye Liu @ 2025-04-24 3:49 ` SeongJae Park 0 siblings, 0 replies; 9+ messages in thread From: SeongJae Park @ 2025-04-24 3:49 UTC (permalink / raw) To: Ye Liu Cc: SeongJae Park, akpm, linux-debuggers, linux-kernel, linux-mm, linux-toolchains, osandov, paulmck, sweettea-kernel, liuye On Thu, 24 Apr 2025 11:24:33 +0800 Ye Liu <ye.liu@linux.dev> wrote: [...] > Regarding compatibility across versions, this is definitely something worth > paying attention to. Currently, the script is being adapted based on the > latest drgn and kernel versions. If future changes to kernel structures > occur, I plan to patch the script accordingly to maintain compatibility. > > That said, I’m very open to suggestions — do you have any ideas on how > we could better detect or guard against these kinds of breakages > proactively? No, unfortunately :'( I'm a drgn newbie user and trying to learn ways to use it better. I therefore thought this problem could also happen to me, and asked the question to know if you or others have a good solution. > > Thanks again for raising this! I'm so glad to hear this. :) Thanks, SJ [...] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR 2025-04-24 2:51 ` SeongJae Park 2025-04-24 3:24 ` Ye Liu @ 2025-04-24 3:27 ` Ye Liu 1 sibling, 0 replies; 9+ messages in thread From: Ye Liu @ 2025-04-24 3:27 UTC (permalink / raw) To: SeongJae Park Cc: akpm, linux-debuggers, linux-kernel, linux-mm, linux-toolchains, osandov, paulmck, sweettea-kernel, liuye 在 2025/4/24 10:51, SeongJae Park 写道: > On Thu, 24 Apr 2025 09:55:22 +0800 Ye Liu <ye.liu@linux.dev> wrote: > >> 在 2025/4/24 06:00, SeongJae Park 写道: >>> On Wed, 23 Apr 2025 09:48:50 +0800 Ye Liu <ye.liu@linux.dev> wrote: >>> >>>> From: Ye Liu <liuye@kylinos.cn> >>>> >>>> Introduces a new drgn script, `show_page_info.py`, which allows users >>>> to analyze the state of a page given a process ID (PID) and a virtual >>>> address (VADDR). This can help kernel developers or debuggers easily >>>> inspect page-related information in a live kernel or vmcore. >>>> >>>> The script extracts information such as the page flags, mapping, and >>>> other metadata relevant to diagnosing memory issues. >>>> >>>> Output example: >>>> sudo ./show_page_info.py 1 0x7f43df5acf00 >>>> PID: 1 Comm: systemd mm: 0xffff8881273bbc40 >>>> Raw: 0017ffffc000416c ffffea00043a4508 ffffea0004381e08 ffff88810f086a70 >>>> Raw: 0000000000000000 ffff888120c9b0c0 0000002500000007 ffff88812642c000 >>>> User Virtual Address: 0x7f43df5acf00 >>>> Page Address: 0xffffea00049a0b00 >>>> Page Flags: PG_referenced|PG_uptodate|PG_lru|PG_head|PG_active| >>>> PG_private|PG_reported >>>> Page Size: 16384 >>> Should this be called folio size? Or, could this simply removed since Compound >>> Order is given below? >> >> Page size refers to the base page size, which equals PAGESIZE. > Shouldn't 'prog["PAGE_SIZE"]' is used for what you are saying? This tool is > using drgn.helpers.linux.page_size()[1] to print this, though? > > +def show_page_state(page, addr, mm, pid, task): > + """Display detailed information about a page.""" > + print(f'PID: {pid} Comm: {task.comm.string_().decode()} mm: {hex(mm)}') > + print(format_page_data(prog.read(page.value_(), 64))) > + fields = { > + "User Virtual Address": hex(addr), > + "Page Address": hex(page.value_()), > + "Page Flags": decode_page_flags(page), > + "Page Size": page_size(page).value_(), > > [1] https://drgn.readthedocs.io/en/stable/helpers.html#drgn.helpers.linux.mm.page_size You're right — I'll update it to use prog["PAGE_SIZE"] here. >> Folio size can be calculated using the Compound Order, but of course, >> it can also be shown directly as a result. >> >>>> Page PFN: 0x12682c >>>> Page Physical: 0x12682c000 >>>> Page Virtual: 0xffff88812682c000 >>>> Page Refcount: 37 >>>> Page Mapcount: 7 >>>> Page Index: 0x0 >>>> Page Memcg Data: 0xffff88812642c000 >>>> Memcg Name: init.scope >>>> Memcg Path: /sys/fs/cgroup/memory/init.scope >>>> Page Mapping: 0xffff88810f086a70 >>>> Page Anon/File: File >>>> Page VMA: 0xffff88810e4af3b8 >>>> VMA Start: 0x7f43df5ac000 >>>> VMA End: 0x7f43df5b0000 >>>> This page is part of a compound page. >>>> This page is the head page of a compound page. >>>> Head Page: 0xffffea00049a0b00 >>>> Compound Order: 2 >>>> Number of Pages: 4 >>>> >>>> Signed-off-by: Ye Liu <liuye@kylinos.cn> >>>> >>>> Changes in v3: >>>> - Adjust display style. >>>> - Link to v2:https://lore.kernel.org/all/20250421080748.114750-1-ye.liu@linux.dev/ >>>> >>>> Changes in v2: >>>> - Move the show_page_info.py file to tools/mm. >>>> - Link to v1: https://lore.kernel.org/all/20250415075024.248232-1-ye.liu@linux.dev/ >>>> --- >>>> MAINTAINERS | 5 ++ >>>> tools/mm/show_page_info.py | 120 +++++++++++++++++++++++++++++++++++++ >>>> 2 files changed, 125 insertions(+) >>>> create mode 100755 tools/mm/show_page_info.py >>>> >>>> diff --git a/MAINTAINERS b/MAINTAINERS >>>> index 17ed0b5ffdd2..85686a30dc72 100644 >>>> --- a/MAINTAINERS >>>> +++ b/MAINTAINERS >>>> @@ -18351,6 +18351,11 @@ F: Documentation/mm/page_table_check.rst >>>> F: include/linux/page_table_check.h >>>> F: mm/page_table_check.c >>>> >>>> +PAGE STATE DEBUG SCRIPT >>>> +M: Ye Liu <liuye@kylinos.cn> >>>> +S: Maintained >>>> +F: tools/mm/show_page_info.py >>>> + >>>> PANASONIC LAPTOP ACPI EXTRAS DRIVER >>>> M: Kenneth Chan <kenneth.t.chan@gmail.com> >>>> L: platform-driver-x86@vger.kernel.org >>>> diff --git a/tools/mm/show_page_info.py b/tools/mm/show_page_info.py >>>> new file mode 100755 >>>> index 000000000000..8622c5499dfe >>>> --- /dev/null >>>> +++ b/tools/mm/show_page_info.py >>> [...] >>>> +def main(): >>>> + """Main function to parse arguments and display page state.""" >>>> + parser = argparse.ArgumentParser(description=DESC, formatter_class=argparse.RawTextHelpFormatter) >>>> + parser.add_argument('pid', metavar='PID', type=int, help='Target process ID (PID)') >>>> + parser.add_argument('vaddr', metavar='VADDR', type=str, help='Target virtual address in hexadecimal format (e.g., 0x7fff1234abcd)') >>>> + args = parser.parse_args() >>>> + >>>> + try: >>>> + vaddr = int(args.vaddr, 16) >>>> + except ValueError: >>>> + print(f"Error: Invalid virtual address format: {args.vaddr}") >>>> + return >>>> + >>>> + task = find_task(args.pid) >>>> + mm = task.mm >>>> + page = follow_page(mm, vaddr) >>> I tried this script on my test machine and got the below error: >>> >>> $ cat ./a.c >>> #include <stdio.h> >>> >>> int main(void) >>> { >>> int foo; >>> printf("hello\n"); >>> printf("%x\n", &foo); >> To avoid address truncation, you can use the %p format specifier >> instead of %x or %lx when printing a pointer (memory address). > Ah, you're correct, thank you. After fixing my test, the error I reported > before is disappeared. But I think the follow_page() error handling would > better to be updated to catch the exception and provide a better error message? > > Also, I'm getting below new error: > > $ sudo ./tools/mm/show_page_info.py 47657 0x7fffaf925b6c > PID: 47657 Comm: a.out mm: 0xffff959c8a022100 > Raw: 0017ffffc0020828 ffffea6b0c201408 ffffea6b0fc65648 ffff959d32bec9c1 > Raw: 00000007fffffffc 0000000000000000 0000000100000000 ffff959cba058000 > Traceback (most recent call last): > File "/usr/local/bin/drgn", line 33, in <module> > sys.exit(load_entry_point('drgn==0.0.30+82.ge2b60e4b', 'console_scripts', 'drgn')()) > ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/cli.py", line 461, in _main > runpy.run_path(script, init_globals={"prog": prog}, run_name="__main__") > File "<frozen runpy>", line 291, in run_path > File "<frozen runpy>", line 98, in _run_module_code > File "<frozen runpy>", line 88, in _run_code > File "./tools/mm/show_page_info.py", line 120, in <module> > main() > File "./tools/mm/show_page_info.py", line 115, in main > show_page_state(page, vaddr, mm, args.pid, task) > File "./tools/mm/show_page_info.py", line 63, in show_page_state > memcg_name, memcg_path = get_memcg_info(page) > ^^^^^^^^^^^^^^^^^^^^ > File "./tools/mm/show_page_info.py", line 43, in get_memcg_info > return cgroup_name(cgrp).decode(), f"/sys/fs/cgroup/memory{cgroup_path(cgrp).decode()}" > ^^^^^^^^^^^^^^^^^ > File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/cgroup.py", line 71, in cgroup_name > return kernfs_name(cgrp.kn) > ^^^^^^^^^^^^^^^^^^^^ > File "/usr/local/lib/python3.11/dist-packages/drgn-0.0.30+82.ge2b60e4b-py3.11-linux-x86_64.egg/drgn/helpers/linux/kernfs.py", line 32, in kernfs_name > return kn.name.string_() if kn.parent else b"/" > ^^^^^^^^^ > AttributeError: 'struct kernfs_node' has no member 'parent'. Did you mean: '__parent'? > > Seems not entirely this script's fault but due to the recent 'struct > kernfs_node' change or my old version of drgn? But anyway, I think it is > better to provide a better error message to users. I'm also curious if you > have a plan for finding and fixing or avoiding this kind of future breakages. > > > Thanks, > SJ > > [...] ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-04-24 3:49 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2025-04-23 1:48 [PATCH v3] tools/mm: Add script to display page state for a given PID and VADDR Ye Liu 2025-04-23 9:45 ` Florian Weimer 2025-04-24 2:17 ` Ye Liu 2025-04-23 22:00 ` SeongJae Park 2025-04-24 1:55 ` Ye Liu 2025-04-24 2:51 ` SeongJae Park 2025-04-24 3:24 ` Ye Liu 2025-04-24 3:49 ` SeongJae Park 2025-04-24 3:27 ` Ye Liu
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for NNTP newsgroup(s).