Re: [PATCH v2] tools/mm: add hwpoison-panic tool
Miaohe Lin <[email protected]>
| Newsgroups | org.infradead.lists.linux-riscv,org.kernel.vger.linux-kernel,org.kvack.linux-mm |
|---|---|
| Message-ID | <[email protected]> |
On 2026/8/3 19:31, Breno Leitao wrote: > Add a tool that enables the vm.panic_on_unrecoverable_memory_failure > sysctl, picks a kernel-owned PFN and writes its physical address to > hard_offline_page. Three page kinds are selectable with -k: rodata > (default), slab or pgtable. In all cases the host should panic. > > Example: > > # ./hwpoison-panic -k slab --yes-panic-my-kernel > injecting hwpoison at phys 0x100032000 (pfn 0x100032, kind=slab) > expecting kernel panic: 'Memory failure: <pfn>: unrecoverable page' > > In dmesg, you will see: > > Memory failure: 0x100032: unhandlable page. > Memory failure: 0x100032: recovery action for reserved kernel page: Ignored > Kernel panic - not syncing: Memory failure: 0x100032: unrecoverable page > > This lives in tools/mm rather than selftests/mm because every successful > run crashes the machine, which is not something to run from CI. > > The --yes-panic-my-kernel argument is required so an accidental > invocation does not take the box down. > > Signed-off-by: Breno Leitao <[email protected]> This patch looks good to me with some nits below. > --- > Changes in v2: > - Reword the file header, the tool triggers a panic rather than > confirming one (SJ Park) > - Rename -f to --yes-panic-my-kernel and say in usage() what it costs > (SJ Park) > - Call check_prereqs() before getpagesize() (SJ Park) > - Use 64-bit types for physical addresses and PFNs. On a 32-bit build > the old long/unsigned long pair truncated addresses above 4G, and the > negative error sentinel was indistinguishable from a valid address at > or above 2G > - Link to v1: https://patch.msgid.link/20260731-memory_failure_rewrite_test-v1-1-6aa8c6435693@debian.org ... > + > +static int pick_kpageflags_phys_addr(uint64_t want, uint64_t *phys_addr) > +{ > + uint64_t pfn = (16UL << 20) / page_size; Could we use SZ_16M macro here? > + uint64_t flags; > + int ret = -1; > + int fd; > + > + fd = open(PROC_KPAGEFLAGS, O_RDONLY); > + if (fd < 0) > + return -1; > + > + for (; kpageflags_read(fd, pfn, &flags) == 0; pfn++) { > + if ((flags & want) && !(flags & BIT(HWPOISON)) && > + !(flags & BIT(NOPAGE)) && !(flags & BIT(COMPOUND_TAIL))) { > + *phys_addr = pfn * page_size; > + ret = 0; > + break; > + } > + } > + > + close(fd); > + return ret; > +} > + > +static int read_sysctl(unsigned long *val) > +{ > + FILE *f = fopen(SYSCTL_PATH, "r"); > + int ret; > + > + if (!f) > + return -1; > + ret = fscanf(f, "%lu", val) == 1 ? 0 : -1; > + fclose(f); > + > + return ret; > +} > + > +static int write_sysctl(unsigned long val) > +{ > + FILE *f = fopen(SYSCTL_PATH, "w"); > + int ret; > + > + if (!f) > + return -1; > + ret = fprintf(f, "%lu", val) < 0 ? -1 : 0; > + fclose(f); > + > + return ret; > +} > + > +/* hard_offline_page() injects with MF_SW_SIMULATED, so unpoison is allowed. */ > +static void unpoison_pfn(uint64_t pfn) > +{ > + char path[PATH_MAX], buf[32]; > + const char *debugfs; > + int fd, len; > + > + debugfs = debugfs__mount(); I might be miss something but I can't find the implementation of debugfs__mount. > + if (!debugfs) > + return; > + > + snprintf(path, sizeof(path), "%s/hwpoison/unpoison-pfn", debugfs); > + fd = open(path, O_WRONLY); > + if (fd < 0) > + return; > + > + len = snprintf(buf, sizeof(buf), "0x%llx\n", (unsigned long long)pfn); > + if (write(fd, buf, len) < 0) > + perror("unpoison-pfn"); > + close(fd); > +} > + ... > + > +static void check_prereqs(int armed) > +{ > + if (geteuid()) > + fatal("must run as root\n"); > + if (access(SYSCTL_PATH, W_OK)) > + fatal("%s not present (kernel without the sysctl?)\n", > + SYSCTL_PATH); > + if (access(INJECT_PATH, W_OK)) > + fatal("%s not present (no MEMORY_HOTPLUG?)\n", INJECT_PATH); MEMORY_HOTPLUG? Thanks. . _______________________________________________ linux-riscv mailing list [email protected] http://lists.infradead.org/mailman/listinfo/linux-riscv