Commit 2ec41967 authored by Ankit Agrawal's avatar Ankit Agrawal Committed by Andrew Morton
Browse files

mm: handle poisoning of pfn without struct pages

Poison (or ECC) errors can be very common on a large size cluster.  The
kernel MM currently does not handle ECC errors / poison on a memory region
that is not backed by struct pages.  If a memory region mapped using
remap_pfn_range() for example, but not added to the kernel, MM will not
have associated struct pages.  Add a new mechanism to handle memory
failure on such memory.

Make kernel MM expose a function to allow modules managing the device
memory to register the device memory SPA and the address space associated
it.  MM maintains this information as an interval tree.  On poison, MM can
search for the range that the poisoned PFN belong and use the
address_space to determine the mapping VMA.

In this implementation, kernel MM follows the following sequence that is
largely similar to the memory_failure() handler for struct page backed
memory:

1. memory_failure() is triggered on reception of a poison error.  An
   absence of struct page is detected and consequently
   memory_failure_pfn() is executed.

2. memory_failure_pfn() collects the processes mapped to the PFN.

3. memory_failure_pfn() sends SIGBUS to all the processes mapping the
   faulty PFN using kill_procs().

Note that there is one primary difference versus the handling of the
poison on struct pages, which is to skip unmapping to the faulty PFN. 
This is done to handle the huge PFNMAP support added recently [1] that
enables VM_PFNMAP vmas to map at PMD or PUD level.  A poison to a PFN
mapped in such as way would need breaking the PMD/PUD mapping into PTEs
that will get mirrored into the S2.  This can greatly increase the cost of
table walks and have a major performance impact.

Link: https://lore.kernel.org/all/20240826204353.2228736-1-peterx@redhat.com/ [1]
Link: https://lkml.kernel.org/r/20251102184434.2406-3-ankita@nvidia.com


Signed-off-by: default avatarAnkit Agrawal <ankita@nvidia.com>
Cc: Aniket Agashe <aniketa@nvidia.com>
Cc: Borislav Betkov <bp@alien8.de>
Cc: David Hildenbrand <david@redhat.com>
Cc: Hanjun Guo <guohanjun@huawei.com>
Cc: Ira Weiny <ira.weiny@intel.com>
Cc: Jason Gunthorpe <jgg@nvidia.com>
Cc: Joanthan Cameron <Jonathan.Cameron@huawei.com>
Cc: Kevin Tian <kevin.tian@intel.com>
Cc: Kirti Wankhede <kwankhede@nvidia.com>
Cc: Len Brown <lenb@kernel.org>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: "Luck, Tony" <tony.luck@intel.com>
Cc: Matthew R. Ochs <mochs@nvidia.com>
Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
Cc: Miaohe Lin <linmiaohe@huawei.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Naoya Horiguchi <nao.horiguchi@gmail.com>
Cc: Neo Jia <cjia@nvidia.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Shuai Xue <xueshuai@linux.alibaba.com>
Cc: Smita Koralahalli Channabasappa <smita.koralahallichannabasappa@amd.com>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Tarun Gupta <targupta@nvidia.com>
Cc: Uwe Kleine-König <u.kleine-koenig@baylibre.com>
Cc: Vikram Sethi <vsethi@nvidia.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Zhi Wang <zhiw@nvidia.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
parent 30d0a129
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -11557,6 +11557,7 @@ M: Miaohe Lin <linmiaohe@huawei.com>
R:	Naoya Horiguchi <nao.horiguchi@gmail.com>
L:	linux-mm@kvack.org
S:	Maintained
F:	include/linux/memory-failure.h
F:	mm/hwpoison-inject.c
F:	mm/memory-failure.c
+17 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef _LINUX_MEMORY_FAILURE_H
#define _LINUX_MEMORY_FAILURE_H

#include <linux/interval_tree.h>

struct pfn_address_space;

struct pfn_address_space {
	struct interval_tree_node node;
	struct address_space *mapping;
};

int register_pfn_address_space(struct pfn_address_space *pfn_space);
void unregister_pfn_address_space(struct pfn_address_space *pfn_space);

#endif /* _LINUX_MEMORY_FAILURE_H */
+1 −0
Original line number Diff line number Diff line
@@ -4285,6 +4285,7 @@ enum mf_action_page_type {
	MF_MSG_DAX,
	MF_MSG_UNSPLIT_THP,
	MF_MSG_ALREADY_POISONED,
	MF_MSG_PFN_MAP,
	MF_MSG_UNKNOWN,
};

+1 −0
Original line number Diff line number Diff line
@@ -375,6 +375,7 @@ TRACE_EVENT(aer_event,
	EM ( MF_MSG_DAX, "dax page" )					\
	EM ( MF_MSG_UNSPLIT_THP, "unsplit thp" )			\
	EM ( MF_MSG_ALREADY_POISONED, "already poisoned" )		\
	EM ( MF_MSG_PFN_MAP, "non struct page pfn" )                    \
	EMe ( MF_MSG_UNKNOWN, "unknown page" )

/*
+1 −0
Original line number Diff line number Diff line
@@ -741,6 +741,7 @@ config MEMORY_FAILURE
	depends on ARCH_SUPPORTS_MEMORY_FAILURE
	bool "Enable recovery from hardware memory errors"
	select RAS
	select INTERVAL_TREE
	help
	  Enables code to recover from some memory failures on systems
	  with MCA recovery. This allows a system to continue running
Loading