mirror of https://gitee.com/openkylin/linux.git
x86/fault: Remove sw_error_code
All of the fault handling code now corrently checks user_mode(regs) as needed, and nothing depends on the X86_PF_USER bit being munged. Get rid of the sw_error code and use hw_error_code everywhere. Signed-off-by: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Dave Hansen <dave.hansen@linux.intel.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Rik van Riel <riel@surriel.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Yu-cheng Yu <yu-cheng.yu@intel.com> Link: http://lkml.kernel.org/r/078f5b8ae6e8c79ff8ee7345b5c476c45003e5ac.1542841400.git.luto@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
parent
1ad33f5aec
commit
0ed32f1aa6
|
@ -1217,7 +1217,6 @@ void do_user_addr_fault(struct pt_regs *regs,
|
|||
unsigned long hw_error_code,
|
||||
unsigned long address)
|
||||
{
|
||||
unsigned long sw_error_code;
|
||||
struct vm_area_struct *vma;
|
||||
struct task_struct *tsk;
|
||||
struct mm_struct *mm;
|
||||
|
@ -1262,13 +1261,6 @@ void do_user_addr_fault(struct pt_regs *regs,
|
|||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* hw_error_code is literally the "page fault error code" passed to
|
||||
* the kernel directly from the hardware. But, we will shortly be
|
||||
* modifying it in software, so give it a new name.
|
||||
*/
|
||||
sw_error_code = hw_error_code;
|
||||
|
||||
/*
|
||||
* It's safe to allow irq's after cr2 has been saved and the
|
||||
* vmalloc fault has been handled.
|
||||
|
@ -1278,26 +1270,6 @@ void do_user_addr_fault(struct pt_regs *regs,
|
|||
*/
|
||||
if (user_mode(regs)) {
|
||||
local_irq_enable();
|
||||
/*
|
||||
* Up to this point, X86_PF_USER set in hw_error_code
|
||||
* indicated a user-mode access. But, after this,
|
||||
* X86_PF_USER in sw_error_code will indicate either
|
||||
* that, *or* an implicit kernel(supervisor)-mode access
|
||||
* which originated from user mode.
|
||||
*/
|
||||
if (!(hw_error_code & X86_PF_USER)) {
|
||||
/*
|
||||
* The CPU was in user mode, but the CPU says
|
||||
* the fault was not a user-mode access.
|
||||
* Must be an implicit kernel-mode access,
|
||||
* which we do not expect to happen in the
|
||||
* user address space.
|
||||
*/
|
||||
pr_warn_once("kernel-mode error from user-mode: %lx\n",
|
||||
hw_error_code);
|
||||
|
||||
sw_error_code |= X86_PF_USER;
|
||||
}
|
||||
flags |= FAULT_FLAG_USER;
|
||||
} else {
|
||||
if (regs->flags & X86_EFLAGS_IF)
|
||||
|
@ -1306,9 +1278,9 @@ void do_user_addr_fault(struct pt_regs *regs,
|
|||
|
||||
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
|
||||
|
||||
if (sw_error_code & X86_PF_WRITE)
|
||||
if (hw_error_code & X86_PF_WRITE)
|
||||
flags |= FAULT_FLAG_WRITE;
|
||||
if (sw_error_code & X86_PF_INSTR)
|
||||
if (hw_error_code & X86_PF_INSTR)
|
||||
flags |= FAULT_FLAG_INSTRUCTION;
|
||||
|
||||
#ifdef CONFIG_X86_64
|
||||
|
@ -1321,7 +1293,7 @@ void do_user_addr_fault(struct pt_regs *regs,
|
|||
* The vsyscall page does not have a "real" VMA, so do this
|
||||
* emulation before we go searching for VMAs.
|
||||
*/
|
||||
if ((sw_error_code & X86_PF_INSTR) && is_vsyscall_vaddr(address)) {
|
||||
if ((hw_error_code & X86_PF_INSTR) && is_vsyscall_vaddr(address)) {
|
||||
if (emulate_vsyscall(regs, address))
|
||||
return;
|
||||
}
|
||||
|
@ -1345,7 +1317,7 @@ void do_user_addr_fault(struct pt_regs *regs,
|
|||
* Fault from code in kernel from
|
||||
* which we do not expect faults.
|
||||
*/
|
||||
bad_area_nosemaphore(regs, sw_error_code, address);
|
||||
bad_area_nosemaphore(regs, hw_error_code, address);
|
||||
return;
|
||||
}
|
||||
retry:
|
||||
|
@ -1361,17 +1333,17 @@ void do_user_addr_fault(struct pt_regs *regs,
|
|||
|
||||
vma = find_vma(mm, address);
|
||||
if (unlikely(!vma)) {
|
||||
bad_area(regs, sw_error_code, address);
|
||||
bad_area(regs, hw_error_code, address);
|
||||
return;
|
||||
}
|
||||
if (likely(vma->vm_start <= address))
|
||||
goto good_area;
|
||||
if (unlikely(!(vma->vm_flags & VM_GROWSDOWN))) {
|
||||
bad_area(regs, sw_error_code, address);
|
||||
bad_area(regs, hw_error_code, address);
|
||||
return;
|
||||
}
|
||||
if (unlikely(expand_stack(vma, address))) {
|
||||
bad_area(regs, sw_error_code, address);
|
||||
bad_area(regs, hw_error_code, address);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1380,8 +1352,8 @@ void do_user_addr_fault(struct pt_regs *regs,
|
|||
* we can handle it..
|
||||
*/
|
||||
good_area:
|
||||
if (unlikely(access_error(sw_error_code, vma))) {
|
||||
bad_area_access_error(regs, sw_error_code, address, vma);
|
||||
if (unlikely(access_error(hw_error_code, vma))) {
|
||||
bad_area_access_error(regs, hw_error_code, address, vma);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1420,13 +1392,13 @@ void do_user_addr_fault(struct pt_regs *regs,
|
|||
return;
|
||||
|
||||
/* Not returning to user mode? Handle exceptions or die: */
|
||||
no_context(regs, sw_error_code, address, SIGBUS, BUS_ADRERR);
|
||||
no_context(regs, hw_error_code, address, SIGBUS, BUS_ADRERR);
|
||||
return;
|
||||
}
|
||||
|
||||
up_read(&mm->mmap_sem);
|
||||
if (unlikely(fault & VM_FAULT_ERROR)) {
|
||||
mm_fault_error(regs, sw_error_code, address, fault);
|
||||
mm_fault_error(regs, hw_error_code, address, fault);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue