/* * Copyright (C) 2008, 2009 Intel Corporation * Authors: Andi Kleen, Fengguang Wu * * This software may be redistributed and/or modified under the terms of * the GNU General Public License ("GPL") version 2 only as published by the * Free Software Foundation. * * High level machine check handler. Handles pages reported by the * hardware as being corrupted usually due to a multi-bit ECC memory or cache * failure. * * In addition there is a "soft offline" entry point that allows stop using * not-yet-corrupted-by-suspicious pages without killing anything. * * Handles page cache pages in various states. The tricky part * here is that we can access any page asynchronously in respect to * other VM users, because memory failures could happen anytime and * anywhere. This could violate some of their assumptions. This is why * this code has to be extremely careful. Generally it tries to use * normal locking rules, as in get the standard locks, even if that means * the error handling takes potentially a long time. * * There are several operations here with exponential complexity because * of unsuitable VM data structures. For example the operation to map back * from RMAP chains to processes has to walk the complete process list and * has non linear complexity with the number. But since memory corruptions * are rare we hope to get away with this. This avoids impacting the core * VM. *//* * Notebook: * - hugetlb needs more code * - kcore/oldmem/vmcore/mem/kmem check for hwpoison pages * - pass bad pages to kdump next kernel */#include <linux/kernel.h>#include <linux/mm.h>#include <linux/page-flags.h>#include <linux/kernel-page-flags.h>#include <linux/sched.h>#include <linux/ksm.h>#include <linux/rmap.h>#include <linux/export.h>#include <linux/pagemap.h>#include <linux/swap.h>#include <linux/backing-dev.h>#include <linux/migrate.h>#include <linux/page-isolation.h>#include <linux/suspend.h>#include <linux/slab.h>#include <linux/swapops.h>#include <linux/hugetlb.h>#include <linux/memory_hotplug.h>#include <linux/mm_inline.h>#include <linux/kfifo.h>#include"internal.h"int sysctl_memory_failure_early_kill __read_mostly =0;int sysctl_memory_failure_recovery __read_mostly =1;
atomic_long_t mce_bad_pages __read_mostly =ATOMIC_LONG_INIT(0);#if defined(CONFIG_HWPOISON_INJECT) || defined(CONFIG_HWPOISON_INJECT_MODULE)
u32 hwpoison_filter_enable =0;
u32 hwpoison_filter_dev_major = ~0U;
u32 hwpoison_filter_dev_minor = ~0U;
u64 hwpoison_filter_flags_mask;
u64 hwpoison_filter_flags_value;EXPORT_SYMBOL_GPL(hwpoison_filter_enable);EXPORT_SYMBOL_GPL(hwpoison_filter_dev_major);EXPORT_SYMBOL_GPL(hwpoison_filter_dev_minor);EXPORT_SYMBOL_GPL(hwpoison_filter_flags_mask);EXPORT_SYMBOL_GPL(hwpoison_filter_flags_value);static inthwpoison_filter_dev(struct page *p