/* * 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 2bit ECC memory or cache * failure. * * Handles page cache pages in various states. The tricky part * here is that we can access any page asynchronous to other VM * users, because memory failures could happen anytime and anywhere, * possibly violating 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. * * 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 * mappings. In short it can be quite slow. But since memory corruptions * are rare we hope to get away with this. *//* * Notebook: * - hugetlb needs more code * - kcore/oldmem/vmcore/mem/kmem check for hwpoison pages * - pass bad pages to kdump next kernel */#define DEBUG 1 /* remove me in 2.6.34 */#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/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/hugetlb.h>#include"internal.h"intsysctl_memory_failure_early_kill__read_mostly=0;intsysctl_memory_failure_recovery__read_mostly=1;atomic_long_tmce_bad_pages__read_mostly=ATOMIC_LONG_INIT(0);#if defined(CONFIG_HWPOISON_INJECT) || defined(CONFIG_HWPOISON_INJECT_MODULE)u32hwpoison_filter_enable=0;u32hwpoison_filter_dev_major=~0U;u32hwpoison_filter_dev_minor=~0U;u64hwpoison_filter_flags_mask;u64hwpoison_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);staticinthwpoison_filter_dev(structpage*p){structaddress_space*mapping;dev_tdev;if(hwpoison_filter_dev_major==~0U&&hwpoison_filter_dev_minor==~0U)return0;/* * page_mapping() does not accept slab page */if(PageSlab(p))return-EINVAL;mapping=page_mapping(p);if(mapping==NULL||mapping->host==NULL)return-EINVAL;dev=mapping->host->i_sb->s_dev;if(hwpoison_filter_dev_major!=~0U&&a