[PATCH] pagemap: expose hwpoison entry

From: Naoya Horiguchi
Date: Tue Mar 16 2021 - 01:22:21 EST


not-signed-off-by-yet: Naoya Horiguchi <naoya.horiguchi@xxxxxxx>
---
fs/proc/task_mmu.c | 6 ++++++
include/linux/swapops.h | 12 ++++++++++++
tools/vm/page-types.c | 5 ++++-
3 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 602e3a52884d..08cea209bae7 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1300,6 +1300,7 @@ struct pagemapread {
#define PM_PFRAME_MASK GENMASK_ULL(PM_PFRAME_BITS - 1, 0)
#define PM_SOFT_DIRTY BIT_ULL(55)
#define PM_MMAP_EXCLUSIVE BIT_ULL(56)
+#define PM_HWPOISON BIT_ULL(60)
#define PM_FILE BIT_ULL(61)
#define PM_SWAP BIT_ULL(62)
#define PM_PRESENT BIT_ULL(63)
@@ -1385,6 +1386,11 @@ static pagemap_entry_t pte_to_pagemap_entry(struct p=
agemapread *pm,
if (is_migration_entry(entry))
page =3D migration_entry_to_page(entry);
=20
+ if (is_hwpoison_entry(entry)) {
+ page =3D hwpoison_entry_to_page(entry);
+ flags |=3D PM_HWPOISON;
+ }
+
if (is_device_private_entry(entry))
page =3D device_private_entry_to_page(entry);
}
diff --git a/include/linux/swapops.h b/include/linux/swapops.h
index d9b7c9132c2f..1b9dedbd06ab 100644
--- a/include/linux/swapops.h
+++ b/include/linux/swapops.h
@@ -323,6 +323,13 @@ static inline int is_hwpoison_entry(swp_entry_t entry)
return swp_type(entry) =3D=3D SWP_HWPOISON;
}
=20
+static inline struct page *hwpoison_entry_to_page(swp_entry_t entry)
+{
+ struct page *p =3D pfn_to_page(swp_offset(entry));
+ WARN_ON(!PageHWPoison(p));
+ return p;
+}
+
static inline void num_poisoned_pages_inc(void)
{
atomic_long_inc(&num_poisoned_pages);
@@ -345,6 +352,11 @@ static inline int is_hwpoison_entry(swp_entry_t swp)
return 0;
}
=20
+static inline struct page *hwpoison_entry_to_page(swp_entry_t entry)
+{
+ return NULL;
+}
+
static inline void num_poisoned_pages_inc(void)
{
}
diff --git a/tools/vm/page-types.c b/tools/vm/page-types.c
index 0517c744b04e..1160d5a14955 100644
--- a/tools/vm/page-types.c
+++ b/tools/vm/page-types.c
@@ -53,6 +53,7 @@
#define PM_SWAP_OFFSET(x) (((x) & PM_PFRAME_MASK) >> MAX_SWAPFILES_SHIFT)
#define PM_SOFT_DIRTY (1ULL << 55)
#define PM_MMAP_EXCLUSIVE (1ULL << 56)
+#define PM_HWPOISON (1ULL << 60)
#define PM_FILE (1ULL << 61)
#define PM_SWAP (1ULL << 62)
#define PM_PRESENT (1ULL << 63)
@@ -311,6 +312,8 @@ static unsigned long pagemap_pfn(uint64_t val)
=20
if (val & PM_PRESENT)
pfn =3D PM_PFRAME(val);
+ else if (val & PM_HWPOISON)
+ pfn =3D PM_SWAP_OFFSET(val);
else
pfn =3D 0;
=20
@@ -742,7 +745,7 @@ static void walk_vma(unsigned long index, unsigned long=
count)
pfn =3D pagemap_pfn(buf[i]);
if (pfn)
walk_pfn(index + i, pfn, 1, buf[i]);
- if (buf[i] & PM_SWAP)
+ else if (buf[i] & PM_SWAP)
walk_swap(index + i, buf[i]);
}
=20
--=20
2.25.1