mirror of
https://github.com/raspberrypi/linux.git
synced 2025-12-07 18:40:10 +00:00
mm,swapops: update check in is_pfn_swap_entry for hwpoison entries
Tony reported that the Machine check recovery was broken in v6.9-rc1, as he was hitting a VM_BUG_ON when injecting uncorrectable memory errors to DRAM. After some more digging and debugging on his side, he realized that this went back to v6.1, with the introduction of 'commit0d206b5d2e("mm/swap: add swp_offset_pfn() to fetch PFN from swap entry")'. That commit, among other things, introduced swp_offset_pfn(), replacing hwpoison_entry_to_pfn() in its favour. The patch also introduced a VM_BUG_ON() check for is_pfn_swap_entry(), but is_pfn_swap_entry() never got updated to cover hwpoison entries, which means that we would hit the VM_BUG_ON whenever we would call swp_offset_pfn() for such entries on environments with CONFIG_DEBUG_VM set. Fix this by updating the check to cover hwpoison entries as well, and update the comment while we are it. Link: https://lkml.kernel.org/r/20240407130537.16977-1-osalvador@suse.de Fixes:0d206b5d2e("mm/swap: add swp_offset_pfn() to fetch PFN from swap entry") Signed-off-by: Oscar Salvador <osalvador@suse.de> Reported-by: Tony Luck <tony.luck@intel.com> Closes: https://lore.kernel.org/all/Zg8kLSl2yAlA3o5D@agluck-desk3/ Tested-by: Tony Luck <tony.luck@intel.com> Reviewed-by: Peter Xu <peterx@redhat.com> Reviewed-by: David Hildenbrand <david@redhat.com> Acked-by: Miaohe Lin <linmiaohe@huawei.com> Cc: <stable@vger.kernel.org> [6.1.x] Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
committed by
Andrew Morton
parent
1983184c22
commit
07a57a338a
@@ -390,6 +390,35 @@ static inline bool is_migration_entry_dirty(swp_entry_t entry)
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_MIGRATION */
|
#endif /* CONFIG_MIGRATION */
|
||||||
|
|
||||||
|
#ifdef CONFIG_MEMORY_FAILURE
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Support for hardware poisoned pages
|
||||||
|
*/
|
||||||
|
static inline swp_entry_t make_hwpoison_entry(struct page *page)
|
||||||
|
{
|
||||||
|
BUG_ON(!PageLocked(page));
|
||||||
|
return swp_entry(SWP_HWPOISON, page_to_pfn(page));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int is_hwpoison_entry(swp_entry_t entry)
|
||||||
|
{
|
||||||
|
return swp_type(entry) == SWP_HWPOISON;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
static inline swp_entry_t make_hwpoison_entry(struct page *page)
|
||||||
|
{
|
||||||
|
return swp_entry(0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int is_hwpoison_entry(swp_entry_t swp)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
typedef unsigned long pte_marker;
|
typedef unsigned long pte_marker;
|
||||||
|
|
||||||
#define PTE_MARKER_UFFD_WP BIT(0)
|
#define PTE_MARKER_UFFD_WP BIT(0)
|
||||||
@@ -483,8 +512,9 @@ static inline struct folio *pfn_swap_entry_folio(swp_entry_t entry)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* A pfn swap entry is a special type of swap entry that always has a pfn stored
|
* A pfn swap entry is a special type of swap entry that always has a pfn stored
|
||||||
* in the swap offset. They are used to represent unaddressable device memory
|
* in the swap offset. They can either be used to represent unaddressable device
|
||||||
* and to restrict access to a page undergoing migration.
|
* memory, to restrict access to a page undergoing migration or to represent a
|
||||||
|
* pfn which has been hwpoisoned and unmapped.
|
||||||
*/
|
*/
|
||||||
static inline bool is_pfn_swap_entry(swp_entry_t entry)
|
static inline bool is_pfn_swap_entry(swp_entry_t entry)
|
||||||
{
|
{
|
||||||
@@ -492,7 +522,7 @@ static inline bool is_pfn_swap_entry(swp_entry_t entry)
|
|||||||
BUILD_BUG_ON(SWP_TYPE_SHIFT < SWP_PFN_BITS);
|
BUILD_BUG_ON(SWP_TYPE_SHIFT < SWP_PFN_BITS);
|
||||||
|
|
||||||
return is_migration_entry(entry) || is_device_private_entry(entry) ||
|
return is_migration_entry(entry) || is_device_private_entry(entry) ||
|
||||||
is_device_exclusive_entry(entry);
|
is_device_exclusive_entry(entry) || is_hwpoison_entry(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct page_vma_mapped_walk;
|
struct page_vma_mapped_walk;
|
||||||
@@ -561,35 +591,6 @@ static inline int is_pmd_migration_entry(pmd_t pmd)
|
|||||||
}
|
}
|
||||||
#endif /* CONFIG_ARCH_ENABLE_THP_MIGRATION */
|
#endif /* CONFIG_ARCH_ENABLE_THP_MIGRATION */
|
||||||
|
|
||||||
#ifdef CONFIG_MEMORY_FAILURE
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Support for hardware poisoned pages
|
|
||||||
*/
|
|
||||||
static inline swp_entry_t make_hwpoison_entry(struct page *page)
|
|
||||||
{
|
|
||||||
BUG_ON(!PageLocked(page));
|
|
||||||
return swp_entry(SWP_HWPOISON, page_to_pfn(page));
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int is_hwpoison_entry(swp_entry_t entry)
|
|
||||||
{
|
|
||||||
return swp_type(entry) == SWP_HWPOISON;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
static inline swp_entry_t make_hwpoison_entry(struct page *page)
|
|
||||||
{
|
|
||||||
return swp_entry(0, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline int is_hwpoison_entry(swp_entry_t swp)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static inline int non_swap_entry(swp_entry_t entry)
|
static inline int non_swap_entry(swp_entry_t entry)
|
||||||
{
|
{
|
||||||
return swp_type(entry) >= MAX_SWAPFILES;
|
return swp_type(entry) >= MAX_SWAPFILES;
|
||||||
|
|||||||
Reference in New Issue
Block a user