Skip to content

Commit

Permalink
mm/hwpoison: avoid the impact of hwpoison_filter() return value on mc…
Browse files Browse the repository at this point in the history
…e handler

When the hwpoison page meets the filter conditions, it should not be
regarded as successful memory_failure() processing for mce handler, but
should return a distinct value, otherwise mce handler regards the error
page has been identified and isolated, which may lead to calling
set_mce_nospec() to change page attribute, etc.

Here memory_failure() return -EOPNOTSUPP to indicate that the error
event is filtered, mce handler should not take any action for this
situation and hwpoison injector should treat as correct.

Link: https://lkml.kernel.org/r/20220223082135.2769649-1-luofei@unicloud.com
Signed-off-by: luofei <luofei@unicloud.com>
Acked-by: Borislav Petkov <bp@suse.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Miaohe Lin <linmiaohe@huawei.com>
Cc: Naoya Horiguchi <naoya.horiguchi@nec.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Tony Luck <tony.luck@intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
luofei authored and torvalds committed Mar 22, 2022
1 parent a581865 commit d1fe111
Show file tree
Hide file tree
Showing 5 changed files with 18 additions and 6 deletions.
8 changes: 5 additions & 3 deletions arch/x86/kernel/cpu/mce/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1304,10 +1304,12 @@ static void kill_me_maybe(struct callback_head *cb)

/*
* -EHWPOISON from memory_failure() means that it already sent SIGBUS
* to the current process with the proper error info, so no need to
* send SIGBUS here again.
* to the current process with the proper error info,
* -EOPNOTSUPP means hwpoison_filter() filtered the error event,
*
* In both cases, no further processing is required.
*/
if (ret == -EHWPOISON)
if (ret == -EHWPOISON || ret == -EOPNOTSUPP)
return;

pr_err("Memory error not recovered");
Expand Down
2 changes: 2 additions & 0 deletions drivers/base/memory.c
Original file line number Diff line number Diff line change
Expand Up @@ -555,6 +555,8 @@ static ssize_t hard_offline_page_store(struct device *dev,
return -EINVAL;
pfn >>= PAGE_SHIFT;
ret = memory_failure(pfn, 0);
if (ret == -EOPNOTSUPP)
ret = 0;
return ret ? ret : count;
}

Expand Down
3 changes: 2 additions & 1 deletion mm/hwpoison-inject.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ static int hwpoison_inject(void *data, u64 val)

inject:
pr_info("Injecting memory failure at pfn %#lx\n", pfn);
return memory_failure(pfn, 0);
err = memory_failure(pfn, 0);
return (err == -EOPNOTSUPP) ? 0 : err;
}

static int hwpoison_unpoison(void *data, u64 val)
Expand Down
2 changes: 2 additions & 0 deletions mm/madvise.c
Original file line number Diff line number Diff line change
Expand Up @@ -1067,6 +1067,8 @@ static int madvise_inject_error(int behavior,
pr_info("Injecting memory failure for pfn %#lx at process virtual address %#lx\n",
pfn, start);
ret = memory_failure(pfn, MF_COUNT_INCREASED);
if (ret == -EOPNOTSUPP)
ret = 0;
}

if (ret)
Expand Down
9 changes: 7 additions & 2 deletions mm/memory-failure.c
Original file line number Diff line number Diff line change
Expand Up @@ -1515,7 +1515,7 @@ static int memory_failure_hugetlb(unsigned long pfn, int flags)
if (TestClearPageHWPoison(head))
num_poisoned_pages_dec();
unlock_page(head);
return 0;
return -EOPNOTSUPP;
}
unlock_page(head);
res = MF_FAILED;
Expand Down Expand Up @@ -1602,7 +1602,7 @@ static int memory_failure_dev_pagemap(unsigned long pfn, int flags,
goto out;

if (hwpoison_filter(page)) {
rc = 0;
rc = -EOPNOTSUPP;
goto unlock;
}

Expand Down Expand Up @@ -1671,6 +1671,10 @@ static DEFINE_MUTEX(mf_mutex);
*
* Must run in process context (e.g. a work queue) with interrupts
* enabled and no spinlocks hold.
*
* Return: 0 for successfully handled the memory error,
* -EOPNOTSUPP for memory_filter() filtered the error event,
* < 0(except -EOPNOTSUPP) on failure.
*/
int memory_failure(unsigned long pfn, int flags)
{
Expand Down Expand Up @@ -1836,6 +1840,7 @@ int memory_failure(unsigned long pfn, int flags)
num_poisoned_pages_dec();
unlock_page(p);
put_page(p);
res = -EOPNOTSUPP;
goto unlock_mutex;
}

Expand Down

0 comments on commit d1fe111

Please sign in to comment.