diff options
Diffstat (limited to 'mm/memory-failure.c')
| -rw-r--r-- | mm/memory-failure.c | 48 | 
1 files changed, 19 insertions, 29 deletions
diff --git a/mm/memory-failure.c b/mm/memory-failure.c index 4acdf393a801..4b80ccee4535 100644 --- a/mm/memory-failure.c +++ b/mm/memory-failure.c @@ -178,25 +178,19 @@ EXPORT_SYMBOL_GPL(hwpoison_filter);   * ``action optional'' if they are not immediately affected by the error   * ``action required'' if error happened in current execution context   */ -static int kill_proc(struct task_struct *t, unsigned long addr, int trapno, +static int kill_proc(struct task_struct *t, unsigned long addr,  			unsigned long pfn, struct page *page, int flags)  { -	struct siginfo si; +	short addr_lsb;  	int ret;  	pr_err("Memory failure: %#lx: Killing %s:%d due to hardware memory corruption\n",  		pfn, t->comm, t->pid); -	si.si_signo = SIGBUS; -	si.si_errno = 0; -	si.si_addr = (void *)addr; -#ifdef __ARCH_SI_TRAPNO -	si.si_trapno = trapno; -#endif -	si.si_addr_lsb = compound_order(compound_head(page)) + PAGE_SHIFT; +	addr_lsb = compound_order(compound_head(page)) + PAGE_SHIFT;  	if ((flags & MF_ACTION_REQUIRED) && t->mm == current->mm) { -		si.si_code = BUS_MCEERR_AR; -		ret = force_sig_info(SIGBUS, &si, current); +		ret = force_sig_mceerr(BUS_MCEERR_AR, (void __user *)addr, +				       addr_lsb, current);  	} else {  		/*  		 * Don't use force here, it's convenient if the signal @@ -204,8 +198,8 @@ static int kill_proc(struct task_struct *t, unsigned long addr, int trapno,  		 * This could cause a loop when the user sets SIGBUS  		 * to SIG_IGN, but hopefully no one will do that?  		 */ -		si.si_code = BUS_MCEERR_AO; -		ret = send_sig_info(SIGBUS, &si, t);  /* synchronous? */ +		ret = send_sig_mceerr(BUS_MCEERR_AO, (void __user *)addr, +				      addr_lsb, t);  /* synchronous? */  	}  	if (ret < 0)  		pr_info("Memory failure: Error sending signal to %s:%d: %d\n", @@ -323,7 +317,7 @@ static void add_to_kill(struct task_struct *tsk, struct page *p,   * Also when FAIL is set do a force kill because something went   * wrong earlier.   */ -static void kill_procs(struct list_head *to_kill, int forcekill, int trapno, +static void kill_procs(struct list_head *to_kill, int forcekill,  			  bool fail, struct page *page, unsigned long pfn,  			  int flags)  { @@ -348,7 +342,7 @@ static void kill_procs(struct list_head *to_kill, int forcekill, int trapno,  			 * check for that, but we need to tell the  			 * process anyways.  			 */ -			else if (kill_proc(tk->tsk, tk->addr, trapno, +			else if (kill_proc(tk->tsk, tk->addr,  					      pfn, page, flags) < 0)  				pr_err("Memory failure: %#lx: Cannot send advisory machine check signal to %s:%d\n",  				       pfn, tk->tsk->comm, tk->tsk->pid); @@ -927,7 +921,7 @@ EXPORT_SYMBOL_GPL(get_hwpoison_page);   * the pages and send SIGBUS to the processes if the data was dirty.   */  static bool hwpoison_user_mappings(struct page *p, unsigned long pfn, -				  int trapno, int flags, struct page **hpagep) +				  int flags, struct page **hpagep)  {  	enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS;  	struct address_space *mapping; @@ -1017,7 +1011,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,  	 * any accesses to the poisoned memory.  	 */  	forcekill = PageDirty(hpage) || (flags & MF_MUST_KILL); -	kill_procs(&tokill, forcekill, trapno, !unmap_success, p, pfn, flags); +	kill_procs(&tokill, forcekill, !unmap_success, p, pfn, flags);  	return unmap_success;  } @@ -1045,7 +1039,7 @@ static int identify_page_state(unsigned long pfn, struct page *p,  	return page_action(ps, p, pfn);  } -static int memory_failure_hugetlb(unsigned long pfn, int trapno, int flags) +static int memory_failure_hugetlb(unsigned long pfn, int flags)  {  	struct page *p = pfn_to_page(pfn);  	struct page *head = compound_head(p); @@ -1090,7 +1084,7 @@ static int memory_failure_hugetlb(unsigned long pfn, int trapno, int flags)  		return 0;  	} -	if (!hwpoison_user_mappings(p, pfn, trapno, flags, &head)) { +	if (!hwpoison_user_mappings(p, pfn, flags, &head)) {  		action_result(pfn, MF_MSG_UNMAP_FAILED, MF_IGNORED);  		res = -EBUSY;  		goto out; @@ -1105,7 +1099,6 @@ out:  /**   * memory_failure - Handle memory failure of a page.   * @pfn: Page Number of the corrupted page - * @trapno: Trap number reported in the signal to user space.   * @flags: fine tune action taken   *   * This function is called by the low level machine check code @@ -1120,7 +1113,7 @@ out:   * Must run in process context (e.g. a work queue) with interrupts   * enabled and no spinlocks hold.   */ -int memory_failure(unsigned long pfn, int trapno, int flags) +int memory_failure(unsigned long pfn, int flags)  {  	struct page *p;  	struct page *hpage; @@ -1129,7 +1122,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)  	unsigned long page_flags;  	if (!sysctl_memory_failure_recovery) -		panic("Memory failure from trap %d on page %lx", trapno, pfn); +		panic("Memory failure on page %lx", pfn);  	if (!pfn_valid(pfn)) {  		pr_err("Memory failure: %#lx: memory outside kernel control\n", @@ -1139,7 +1132,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)  	p = pfn_to_page(pfn);  	if (PageHuge(p)) -		return memory_failure_hugetlb(pfn, trapno, flags); +		return memory_failure_hugetlb(pfn, flags);  	if (TestSetPageHWPoison(p)) {  		pr_err("Memory failure: %#lx: already hardware poisoned\n",  			pfn); @@ -1268,7 +1261,7 @@ int memory_failure(unsigned long pfn, int trapno, int flags)  	 * When the raw error page is thp tail page, hpage points to the raw  	 * page after thp split.  	 */ -	if (!hwpoison_user_mappings(p, pfn, trapno, flags, &hpage)) { +	if (!hwpoison_user_mappings(p, pfn, flags, &hpage)) {  		action_result(pfn, MF_MSG_UNMAP_FAILED, MF_IGNORED);  		res = -EBUSY;  		goto out; @@ -1296,7 +1289,6 @@ EXPORT_SYMBOL_GPL(memory_failure);  struct memory_failure_entry {  	unsigned long pfn; -	int trapno;  	int flags;  }; @@ -1312,7 +1304,6 @@ static DEFINE_PER_CPU(struct memory_failure_cpu, memory_failure_cpu);  /**   * memory_failure_queue - Schedule handling memory failure of a page.   * @pfn: Page Number of the corrupted page - * @trapno: Trap number reported in the signal to user space.   * @flags: Flags for memory failure handling   *   * This function is called by the low level hardware error handler @@ -1326,13 +1317,12 @@ static DEFINE_PER_CPU(struct memory_failure_cpu, memory_failure_cpu);   *   * Can run in IRQ context.   */ -void memory_failure_queue(unsigned long pfn, int trapno, int flags) +void memory_failure_queue(unsigned long pfn, int flags)  {  	struct memory_failure_cpu *mf_cpu;  	unsigned long proc_flags;  	struct memory_failure_entry entry = {  		.pfn =		pfn, -		.trapno =	trapno,  		.flags =	flags,  	}; @@ -1365,7 +1355,7 @@ static void memory_failure_work_func(struct work_struct *work)  		if (entry.flags & MF_SOFT_OFFLINE)  			soft_offline_page(pfn_to_page(entry.pfn), entry.flags);  		else -			memory_failure(entry.pfn, entry.trapno, entry.flags); +			memory_failure(entry.pfn, entry.flags);  	}  }  |