diff options
Diffstat (limited to 'arch/x86')
-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 4c4508e8a204..1d15a27dd6ff 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 | } |
@@ -731,7 +737,7 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code, | |||
731 | tsk->thread.error_code = error_code | (address >= TASK_SIZE); | 737 | tsk->thread.error_code = error_code | (address >= TASK_SIZE); |
732 | tsk->thread.trap_no = 14; | 738 | tsk->thread.trap_no = 14; |
733 | 739 | ||
734 | force_sig_info_fault(SIGSEGV, si_code, address, tsk); | 740 | force_sig_info_fault(SIGSEGV, si_code, address, tsk, 0); |
735 | 741 | ||
736 | return; | 742 | return; |
737 | } | 743 | } |
@@ -816,14 +822,14 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address, | |||
816 | tsk->thread.trap_no = 14; | 822 | tsk->thread.trap_no = 14; |
817 | 823 | ||
818 | #ifdef CONFIG_MEMORY_FAILURE | 824 | #ifdef CONFIG_MEMORY_FAILURE |
819 | if (fault & VM_FAULT_HWPOISON) { | 825 | if (fault & (VM_FAULT_HWPOISON|VM_FAULT_HWPOISON_LARGE)) { |
820 | printk(KERN_ERR | 826 | printk(KERN_ERR |
821 | "MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n", | 827 | "MCE: Killing %s:%d due to hardware memory corruption fault at %lx\n", |
822 | tsk->comm, tsk->pid, address); | 828 | tsk->comm, tsk->pid, address); |
823 | code = BUS_MCEERR_AR; | 829 | code = BUS_MCEERR_AR; |
824 | } | 830 | } |
825 | #endif | 831 | #endif |
826 | force_sig_info_fault(SIGBUS, code, address, tsk); | 832 | force_sig_info_fault(SIGBUS, code, address, tsk, fault); |
827 | } | 833 | } |
828 | 834 | ||
829 | static noinline void | 835 | static noinline void |
@@ -833,7 +839,8 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code, | |||
833 | if (fault & VM_FAULT_OOM) { | 839 | if (fault & VM_FAULT_OOM) { |
834 | out_of_memory(regs, error_code, address); | 840 | out_of_memory(regs, error_code, address); |
835 | } else { | 841 | } else { |
836 | if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON)) | 842 | if (fault & (VM_FAULT_SIGBUS|VM_FAULT_HWPOISON| |
843 | VM_FAULT_HWPOISON_LARGE)) | ||
837 | do_sigbus(regs, error_code, address, fault); | 844 | do_sigbus(regs, error_code, address, fault); |
838 | else | 845 | else |
839 | BUG(); | 846 | BUG(); |