|
@@ -29,26 +29,6 @@
|
|
#define CREATE_TRACE_POINTS
|
|
#define CREATE_TRACE_POINTS
|
|
#include <asm/trace/exceptions.h>
|
|
#include <asm/trace/exceptions.h>
|
|
|
|
|
|
-/*
|
|
|
|
- * Page fault error code bits:
|
|
|
|
- *
|
|
|
|
- * bit 0 == 0: no page found 1: protection fault
|
|
|
|
- * bit 1 == 0: read access 1: write access
|
|
|
|
- * bit 2 == 0: kernel-mode access 1: user-mode access
|
|
|
|
- * bit 3 == 1: use of reserved bit detected
|
|
|
|
- * bit 4 == 1: fault was an instruction fetch
|
|
|
|
- * bit 5 == 1: protection keys block access
|
|
|
|
- */
|
|
|
|
-enum x86_pf_error_code {
|
|
|
|
-
|
|
|
|
- PF_PROT = 1 << 0,
|
|
|
|
- PF_WRITE = 1 << 1,
|
|
|
|
- PF_USER = 1 << 2,
|
|
|
|
- PF_RSVD = 1 << 3,
|
|
|
|
- PF_INSTR = 1 << 4,
|
|
|
|
- PF_PK = 1 << 5,
|
|
|
|
-};
|
|
|
|
-
|
|
|
|
/*
|
|
/*
|
|
* Returns 0 if mmiotrace is disabled, or if the fault is not
|
|
* Returns 0 if mmiotrace is disabled, or if the fault is not
|
|
* handled by mmiotrace:
|
|
* handled by mmiotrace:
|
|
@@ -150,7 +130,7 @@ is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr)
|
|
* If it was a exec (instruction fetch) fault on NX page, then
|
|
* If it was a exec (instruction fetch) fault on NX page, then
|
|
* do not ignore the fault:
|
|
* do not ignore the fault:
|
|
*/
|
|
*/
|
|
- if (error_code & PF_INSTR)
|
|
|
|
|
|
+ if (error_code & X86_PF_INSTR)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
instr = (void *)convert_ip_to_linear(current, regs);
|
|
instr = (void *)convert_ip_to_linear(current, regs);
|
|
@@ -180,7 +160,7 @@ is_prefetch(struct pt_regs *regs, unsigned long error_code, unsigned long addr)
|
|
* siginfo so userspace can discover which protection key was set
|
|
* siginfo so userspace can discover which protection key was set
|
|
* on the PTE.
|
|
* on the PTE.
|
|
*
|
|
*
|
|
- * If we get here, we know that the hardware signaled a PF_PK
|
|
|
|
|
|
+ * If we get here, we know that the hardware signaled a X86_PF_PK
|
|
* fault and that there was a VMA once we got in the fault
|
|
* fault and that there was a VMA once we got in the fault
|
|
* handler. It does *not* guarantee that the VMA we find here
|
|
* handler. It does *not* guarantee that the VMA we find here
|
|
* was the one that we faulted on.
|
|
* was the one that we faulted on.
|
|
@@ -205,7 +185,7 @@ static void fill_sig_info_pkey(int si_code, siginfo_t *info, u32 *pkey)
|
|
/*
|
|
/*
|
|
* force_sig_info_fault() is called from a number of
|
|
* force_sig_info_fault() is called from a number of
|
|
* contexts, some of which have a VMA and some of which
|
|
* contexts, some of which have a VMA and some of which
|
|
- * do not. The PF_PK handing happens after we have a
|
|
|
|
|
|
+ * do not. The X86_PF_PK handing happens after we have a
|
|
* valid VMA, so we should never reach this without a
|
|
* valid VMA, so we should never reach this without a
|
|
* valid VMA.
|
|
* valid VMA.
|
|
*/
|
|
*/
|
|
@@ -698,7 +678,7 @@ show_fault_oops(struct pt_regs *regs, unsigned long error_code,
|
|
if (!oops_may_print())
|
|
if (!oops_may_print())
|
|
return;
|
|
return;
|
|
|
|
|
|
- if (error_code & PF_INSTR) {
|
|
|
|
|
|
+ if (error_code & X86_PF_INSTR) {
|
|
unsigned int level;
|
|
unsigned int level;
|
|
pgd_t *pgd;
|
|
pgd_t *pgd;
|
|
pte_t *pte;
|
|
pte_t *pte;
|
|
@@ -780,7 +760,7 @@ no_context(struct pt_regs *regs, unsigned long error_code,
|
|
*/
|
|
*/
|
|
if (current->thread.sig_on_uaccess_err && signal) {
|
|
if (current->thread.sig_on_uaccess_err && signal) {
|
|
tsk->thread.trap_nr = X86_TRAP_PF;
|
|
tsk->thread.trap_nr = X86_TRAP_PF;
|
|
- tsk->thread.error_code = error_code | PF_USER;
|
|
|
|
|
|
+ tsk->thread.error_code = error_code | X86_PF_USER;
|
|
tsk->thread.cr2 = address;
|
|
tsk->thread.cr2 = address;
|
|
|
|
|
|
/* XXX: hwpoison faults will set the wrong code. */
|
|
/* XXX: hwpoison faults will set the wrong code. */
|
|
@@ -898,7 +878,7 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
|
|
struct task_struct *tsk = current;
|
|
struct task_struct *tsk = current;
|
|
|
|
|
|
/* User mode accesses just cause a SIGSEGV */
|
|
/* User mode accesses just cause a SIGSEGV */
|
|
- if (error_code & PF_USER) {
|
|
|
|
|
|
+ if (error_code & X86_PF_USER) {
|
|
/*
|
|
/*
|
|
* It's possible to have interrupts off here:
|
|
* It's possible to have interrupts off here:
|
|
*/
|
|
*/
|
|
@@ -919,7 +899,7 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
|
|
* Instruction fetch faults in the vsyscall page might need
|
|
* Instruction fetch faults in the vsyscall page might need
|
|
* emulation.
|
|
* emulation.
|
|
*/
|
|
*/
|
|
- if (unlikely((error_code & PF_INSTR) &&
|
|
|
|
|
|
+ if (unlikely((error_code & X86_PF_INSTR) &&
|
|
((address & ~0xfff) == VSYSCALL_ADDR))) {
|
|
((address & ~0xfff) == VSYSCALL_ADDR))) {
|
|
if (emulate_vsyscall(regs, address))
|
|
if (emulate_vsyscall(regs, address))
|
|
return;
|
|
return;
|
|
@@ -932,7 +912,7 @@ __bad_area_nosemaphore(struct pt_regs *regs, unsigned long error_code,
|
|
* are always protection faults.
|
|
* are always protection faults.
|
|
*/
|
|
*/
|
|
if (address >= TASK_SIZE_MAX)
|
|
if (address >= TASK_SIZE_MAX)
|
|
- error_code |= PF_PROT;
|
|
|
|
|
|
+ error_code |= X86_PF_PROT;
|
|
|
|
|
|
if (likely(show_unhandled_signals))
|
|
if (likely(show_unhandled_signals))
|
|
show_signal_msg(regs, error_code, address, tsk);
|
|
show_signal_msg(regs, error_code, address, tsk);
|
|
@@ -993,11 +973,11 @@ static inline bool bad_area_access_from_pkeys(unsigned long error_code,
|
|
|
|
|
|
if (!boot_cpu_has(X86_FEATURE_OSPKE))
|
|
if (!boot_cpu_has(X86_FEATURE_OSPKE))
|
|
return false;
|
|
return false;
|
|
- if (error_code & PF_PK)
|
|
|
|
|
|
+ if (error_code & X86_PF_PK)
|
|
return true;
|
|
return true;
|
|
/* this checks permission keys on the VMA: */
|
|
/* this checks permission keys on the VMA: */
|
|
- if (!arch_vma_access_permitted(vma, (error_code & PF_WRITE),
|
|
|
|
- (error_code & PF_INSTR), foreign))
|
|
|
|
|
|
+ if (!arch_vma_access_permitted(vma, (error_code & X86_PF_WRITE),
|
|
|
|
+ (error_code & X86_PF_INSTR), foreign))
|
|
return true;
|
|
return true;
|
|
return false;
|
|
return false;
|
|
}
|
|
}
|
|
@@ -1025,7 +1005,7 @@ do_sigbus(struct pt_regs *regs, unsigned long error_code, unsigned long address,
|
|
int code = BUS_ADRERR;
|
|
int code = BUS_ADRERR;
|
|
|
|
|
|
/* Kernel mode? Handle exceptions or die: */
|
|
/* Kernel mode? Handle exceptions or die: */
|
|
- if (!(error_code & PF_USER)) {
|
|
|
|
|
|
+ if (!(error_code & X86_PF_USER)) {
|
|
no_context(regs, error_code, address, SIGBUS, BUS_ADRERR);
|
|
no_context(regs, error_code, address, SIGBUS, BUS_ADRERR);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
@@ -1053,14 +1033,14 @@ static noinline void
|
|
mm_fault_error(struct pt_regs *regs, unsigned long error_code,
|
|
mm_fault_error(struct pt_regs *regs, unsigned long error_code,
|
|
unsigned long address, u32 *pkey, unsigned int fault)
|
|
unsigned long address, u32 *pkey, unsigned int fault)
|
|
{
|
|
{
|
|
- if (fatal_signal_pending(current) && !(error_code & PF_USER)) {
|
|
|
|
|
|
+ if (fatal_signal_pending(current) && !(error_code & X86_PF_USER)) {
|
|
no_context(regs, error_code, address, 0, 0);
|
|
no_context(regs, error_code, address, 0, 0);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
|
|
|
|
if (fault & VM_FAULT_OOM) {
|
|
if (fault & VM_FAULT_OOM) {
|
|
/* Kernel mode? Handle exceptions or die: */
|
|
/* Kernel mode? Handle exceptions or die: */
|
|
- if (!(error_code & PF_USER)) {
|
|
|
|
|
|
+ if (!(error_code & X86_PF_USER)) {
|
|
no_context(regs, error_code, address,
|
|
no_context(regs, error_code, address,
|
|
SIGSEGV, SEGV_MAPERR);
|
|
SIGSEGV, SEGV_MAPERR);
|
|
return;
|
|
return;
|
|
@@ -1085,16 +1065,16 @@ mm_fault_error(struct pt_regs *regs, unsigned long error_code,
|
|
|
|
|
|
static int spurious_fault_check(unsigned long error_code, pte_t *pte)
|
|
static int spurious_fault_check(unsigned long error_code, pte_t *pte)
|
|
{
|
|
{
|
|
- if ((error_code & PF_WRITE) && !pte_write(*pte))
|
|
|
|
|
|
+ if ((error_code & X86_PF_WRITE) && !pte_write(*pte))
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
- if ((error_code & PF_INSTR) && !pte_exec(*pte))
|
|
|
|
|
|
+ if ((error_code & X86_PF_INSTR) && !pte_exec(*pte))
|
|
return 0;
|
|
return 0;
|
|
/*
|
|
/*
|
|
* Note: We do not do lazy flushing on protection key
|
|
* Note: We do not do lazy flushing on protection key
|
|
- * changes, so no spurious fault will ever set PF_PK.
|
|
|
|
|
|
+ * changes, so no spurious fault will ever set X86_PF_PK.
|
|
*/
|
|
*/
|
|
- if ((error_code & PF_PK))
|
|
|
|
|
|
+ if ((error_code & X86_PF_PK))
|
|
return 1;
|
|
return 1;
|
|
|
|
|
|
return 1;
|
|
return 1;
|
|
@@ -1140,8 +1120,8 @@ spurious_fault(unsigned long error_code, unsigned long address)
|
|
* change, so user accesses are not expected to cause spurious
|
|
* change, so user accesses are not expected to cause spurious
|
|
* faults.
|
|
* faults.
|
|
*/
|
|
*/
|
|
- if (error_code != (PF_WRITE | PF_PROT)
|
|
|
|
- && error_code != (PF_INSTR | PF_PROT))
|
|
|
|
|
|
+ if (error_code != (X86_PF_WRITE | X86_PF_PROT) &&
|
|
|
|
+ error_code != (X86_PF_INSTR | X86_PF_PROT))
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
pgd = init_mm.pgd + pgd_index(address);
|
|
pgd = init_mm.pgd + pgd_index(address);
|
|
@@ -1201,19 +1181,19 @@ access_error(unsigned long error_code, struct vm_area_struct *vma)
|
|
* always an unconditional error and can never result in
|
|
* always an unconditional error and can never result in
|
|
* a follow-up action to resolve the fault, like a COW.
|
|
* a follow-up action to resolve the fault, like a COW.
|
|
*/
|
|
*/
|
|
- if (error_code & PF_PK)
|
|
|
|
|
|
+ if (error_code & X86_PF_PK)
|
|
return 1;
|
|
return 1;
|
|
|
|
|
|
/*
|
|
/*
|
|
* Make sure to check the VMA so that we do not perform
|
|
* Make sure to check the VMA so that we do not perform
|
|
- * faults just to hit a PF_PK as soon as we fill in a
|
|
|
|
|
|
+ * faults just to hit a X86_PF_PK as soon as we fill in a
|
|
* page.
|
|
* page.
|
|
*/
|
|
*/
|
|
- if (!arch_vma_access_permitted(vma, (error_code & PF_WRITE),
|
|
|
|
- (error_code & PF_INSTR), foreign))
|
|
|
|
|
|
+ if (!arch_vma_access_permitted(vma, (error_code & X86_PF_WRITE),
|
|
|
|
+ (error_code & X86_PF_INSTR), foreign))
|
|
return 1;
|
|
return 1;
|
|
|
|
|
|
- if (error_code & PF_WRITE) {
|
|
|
|
|
|
+ if (error_code & X86_PF_WRITE) {
|
|
/* write, present and write, not present: */
|
|
/* write, present and write, not present: */
|
|
if (unlikely(!(vma->vm_flags & VM_WRITE)))
|
|
if (unlikely(!(vma->vm_flags & VM_WRITE)))
|
|
return 1;
|
|
return 1;
|
|
@@ -1221,7 +1201,7 @@ access_error(unsigned long error_code, struct vm_area_struct *vma)
|
|
}
|
|
}
|
|
|
|
|
|
/* read, present: */
|
|
/* read, present: */
|
|
- if (unlikely(error_code & PF_PROT))
|
|
|
|
|
|
+ if (unlikely(error_code & X86_PF_PROT))
|
|
return 1;
|
|
return 1;
|
|
|
|
|
|
/* read, not present: */
|
|
/* read, not present: */
|
|
@@ -1244,7 +1224,7 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs)
|
|
if (!static_cpu_has(X86_FEATURE_SMAP))
|
|
if (!static_cpu_has(X86_FEATURE_SMAP))
|
|
return false;
|
|
return false;
|
|
|
|
|
|
- if (error_code & PF_USER)
|
|
|
|
|
|
+ if (error_code & X86_PF_USER)
|
|
return false;
|
|
return false;
|
|
|
|
|
|
if (!user_mode(regs) && (regs->flags & X86_EFLAGS_AC))
|
|
if (!user_mode(regs) && (regs->flags & X86_EFLAGS_AC))
|
|
@@ -1297,7 +1277,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
|
* protection error (error_code & 9) == 0.
|
|
* protection error (error_code & 9) == 0.
|
|
*/
|
|
*/
|
|
if (unlikely(fault_in_kernel_space(address))) {
|
|
if (unlikely(fault_in_kernel_space(address))) {
|
|
- if (!(error_code & (PF_RSVD | PF_USER | PF_PROT))) {
|
|
|
|
|
|
+ if (!(error_code & (X86_PF_RSVD | X86_PF_USER | X86_PF_PROT))) {
|
|
if (vmalloc_fault(address) >= 0)
|
|
if (vmalloc_fault(address) >= 0)
|
|
return;
|
|
return;
|
|
|
|
|
|
@@ -1325,7 +1305,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
|
if (unlikely(kprobes_fault(regs)))
|
|
if (unlikely(kprobes_fault(regs)))
|
|
return;
|
|
return;
|
|
|
|
|
|
- if (unlikely(error_code & PF_RSVD))
|
|
|
|
|
|
+ if (unlikely(error_code & X86_PF_RSVD))
|
|
pgtable_bad(regs, error_code, address);
|
|
pgtable_bad(regs, error_code, address);
|
|
|
|
|
|
if (unlikely(smap_violation(error_code, regs))) {
|
|
if (unlikely(smap_violation(error_code, regs))) {
|
|
@@ -1351,7 +1331,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
|
*/
|
|
*/
|
|
if (user_mode(regs)) {
|
|
if (user_mode(regs)) {
|
|
local_irq_enable();
|
|
local_irq_enable();
|
|
- error_code |= PF_USER;
|
|
|
|
|
|
+ error_code |= X86_PF_USER;
|
|
flags |= FAULT_FLAG_USER;
|
|
flags |= FAULT_FLAG_USER;
|
|
} else {
|
|
} else {
|
|
if (regs->flags & X86_EFLAGS_IF)
|
|
if (regs->flags & X86_EFLAGS_IF)
|
|
@@ -1360,9 +1340,9 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
|
|
|
|
|
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
|
|
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
|
|
|
|
|
|
- if (error_code & PF_WRITE)
|
|
|
|
|
|
+ if (error_code & X86_PF_WRITE)
|
|
flags |= FAULT_FLAG_WRITE;
|
|
flags |= FAULT_FLAG_WRITE;
|
|
- if (error_code & PF_INSTR)
|
|
|
|
|
|
+ if (error_code & X86_PF_INSTR)
|
|
flags |= FAULT_FLAG_INSTRUCTION;
|
|
flags |= FAULT_FLAG_INSTRUCTION;
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1382,7 +1362,7 @@ __do_page_fault(struct pt_regs *regs, unsigned long error_code,
|
|
* space check, thus avoiding the deadlock:
|
|
* space check, thus avoiding the deadlock:
|
|
*/
|
|
*/
|
|
if (unlikely(!down_read_trylock(&mm->mmap_sem))) {
|
|
if (unlikely(!down_read_trylock(&mm->mmap_sem))) {
|
|
- if ((error_code & PF_USER) == 0 &&
|
|
|
|
|
|
+ if (!(error_code & X86_PF_USER) &&
|
|
!search_exception_tables(regs->ip)) {
|
|
!search_exception_tables(regs->ip)) {
|
|
bad_area_nosemaphore(regs, error_code, address, NULL);
|
|
bad_area_nosemaphore(regs, error_code, address, NULL);
|
|
return;
|
|
return;
|
|
@@ -1409,7 +1389,7 @@ retry:
|
|
bad_area(regs, error_code, address);
|
|
bad_area(regs, error_code, address);
|
|
return;
|
|
return;
|
|
}
|
|
}
|
|
- if (error_code & PF_USER) {
|
|
|
|
|
|
+ if (error_code & X86_PF_USER) {
|
|
/*
|
|
/*
|
|
* Accessing the stack below %sp is always a bug.
|
|
* Accessing the stack below %sp is always a bug.
|
|
* The large cushion allows instructions like enter
|
|
* The large cushion allows instructions like enter
|