diff options
| author | Andi Kleen <ak@linux.intel.com> | 2010-10-22 11:40:48 -0400 |
|---|---|---|
| committer | Andi Kleen <ak@linux.intel.com> | 2010-10-22 11:40:48 -0400 |
| commit | 46e387bbd82d438b9131e237e6e2cb55a825da49 (patch) | |
| tree | 414948afd6b4d63c6ea8cc79ce022128bc1bf2eb /arch/x86/mm/fault.c | |
| parent | e9d08567ef72a2d0fb9b14dded386352d3136442 (diff) | |
| parent | 3ef8fd7f720fc4f462fcdcae2fcde6f1c0536bfe (diff) | |
Merge branch 'hwpoison-hugepages' into hwpoison
Conflicts:
mm/memory-failure.c
Diffstat (limited to 'arch/x86/mm/fault.c')
| -rw-r--r-- | arch/x86/mm/fault.c | 19 |
1 files changed, 13 insertions, 6 deletions
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 79b0b372d2d0..852b319edbdc 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <linux/kprobes.h> /* __kprobes, ... */ | 11 | #include <linux/kprobes.h> /* __kprobes, ... */ |
| 12 | #include <linux/mmiotrace.h> /* kmmio_handler, ... */ | 12 | #include <linux/mmiotrace.h> /* kmmio_handler, ... */ |
| 13 | #include <linux/perf_event.h> /* perf_sw_event */ | 13 | #include <linux/perf_event.h> /* perf_sw_event */ |
| 14 | #include <linux/hugetlb.h> /* hstate_index_to_shift */ | ||
| 14 | 15 | ||
| 15 | #include <asm/traps.h> /* dotraplinkage, ... */ | 16 | #include <asm/traps.h> /* dotraplinkage, ... */ |
| 16 | #include <asm/pgalloc.h> /* pgd_*(), ... */ | 17 | #include <asm/pgalloc.h> /* pgd_*(), ... */ |
| @@ -160,15 +161,20 @@ is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr) | |||
| 160 | 161 | ||
| 161 | static void | 162 | static void |
| 162 | force_sig_info_fault(int si_signo, int si_code, unsigned long address, | 163 | force_sig_info_fault(int si_signo, int si_code, unsigned long address, |
| 163 | struct task_struct *tsk) | 164 | struct task_struct *tsk, int fault) |
| 164 | { | 165 | { |
| 166 | unsigned lsb = 0; | ||
| 165 | siginfo_t info; | 167 | siginfo_t info; |
| 166 | 168 | ||
| 167 | info.si_signo = si_signo; | 169 | info.si_signo = si_signo; |
| 168 | info.si_errno = 0; | 170 | info.si_errno = 0; |
| 169 | info.si_code = si_code; | 171 | info.si_code = si_code; |
| 170 | info.si_addr = (void __user *)address; | 172 | info.si_addr = (void __user *)address; |
| 171 | info.si_addr_lsb = si_code == BUS_MCEERR_AR ? PAGE_SHIFT : 0; | 173 | if (fault & VM_FAULT_HWPOISON_LARGE) |
| 174 | lsb = hstate_index_to_shift(VM_FAULT_GET_HINDEX(fault)); | ||
| 175 | if (fault & VM_FAULT_HWPOISON) | ||
| 176 | lsb = PAGE_SHIFT; | ||
| 177 | info.si_addr_lsb = lsb; | ||
| 172 | 178 | ||
| 173 | force_sig_info(si_signo, &info, tsk); | 179 | force_sig_info(si_signo, &info, tsk); |
| 174 | } | 180 | } |
| @@ -722,7 +728,7 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, | |||
| 722 | tsk->thread.error_code = error_code | (address >= TASK_SIZE); | 728 | tsk->thread.error_code = error_code | (address >= TASK_SIZE); |
| 723 | tsk->thread.trap_no = 14; | 729 | tsk->thread.trap_no = 14; |
| 724 | 730 | ||
| 725 | force_sig_info_fault(SIGSEGV, si_code, address, tsk); | 731 | force_sig_info_fault(SIGSEGV, si_code, address, tsk, 0); |
| 726 | 732 | ||
| 727 | return; | 733 | return; |
| 728 | } | 734 | } |
| @@ -807,14 +813,14 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, | |||
| 807 | tsk->thread.trap_no = 14; | 813 | tsk->thread.trap_no = 14; |
| 808 | 814 | ||
| 809 | #ifdef CONFIG_MEMORY_FAILURE | 815 | #ifdef CONFIG_MEMORY_FAILURE |
| 810 | if (fault & VM_FAULT_HWPOISON) { | 816 | if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) { |
| 811 | printk(KERN_ERR | 817 | printk(KERN_ERR |
| 812 | "MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n", | 818 | "MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n", |
| 813 | tsk->comm, tsk->pid, address); | 819 | tsk->comm, tsk->pid, address); |
| 814 | code = BUS_MCEERR_AR; | 820 | code = BUS_MCEERR_AR; |
| 815 | } | 821 | } |
| 816 | #endif | 822 | #endif |
| 817 | force_sig_info_fault(SIGBUS, code, address, tsk); | 823 | force_sig_info_fault(SIGBUS, code, address, tsk, fault); |
| 818 | } | 824 | } |
| 819 | 825 | ||
| 820 | static noinline void | 826 | static noinline void |
| @@ -824,7 +830,8 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, | |||
| 824 | if (fault & VM_FAULT_OOM) { | 830 | if (fault & VM_FAULT_OOM) { |
| 825 | out_of_memory(regs, error_code, address); | 831 | out_of_memory(regs, error_code, address); |
| 826 | } else { | 832 | } else { |
| 827 | if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON)) | 833 | if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON| |
| 834 | VM_FAULT_HWPOISON_LARGE)) | ||
| 828 | do_sigbus(regs, error_code, address, fault); | 835 | do_sigbus(regs, error_code, address, fault); |
| 829 | else | 836 | else |
| 830 | BUG(); | 837 | BUG(); |
