From: Dave Hansen <dave.hansen@linux.intel.com>
To: linux-kernel@vger.kernel.org
Cc: Dave Hansen <dave.hansen@linux.intel.com>,
sean.j.christopherson@intel.com, peterz@infradead.org,
tglx@linutronix.de, x86@kernel.org, luto@kernel.org
Subject: [RFC][PATCH 2/8] x86/mm: break out kernel address space handling
Date: Fri, 07 Sep 2018 12:48:55 -0700 [thread overview]
Message-ID: <20180907194855.74E03836@viggo.jf.intel.com> (raw)
In-Reply-To: <20180907194852.3C351B82@viggo.jf.intel.com>
From: Dave Hansen <dave.hansen@linux.intel.com>
The page fault handler (__do_page_fault()) basically has two sections:
one for handling faults in the kernel porttion of the address space
and another for faults in the user porttion of the address space.
But, these two parts don't stick out that well. Let's make that more
clear from code separation and naming. Pull kernel fault
handling into its own helper, and reflect that naming by renaming
spurious_fault() -> spurious_kernel_fault().
Also, rewrite the vmalloc handling comment a bit. It was a bit
stale and also glossed over the reserved bit handling.
Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Sean Christopherson <sean.j.christopherson@intel.com>
Cc: "Peter Zijlstra (Intel)" <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: x86@kernel.org
Cc: Andy Lutomirski <luto@kernel.org>
---
b/arch/x86/mm/fault.c | 98 ++++++++++++++++++++++++++++++--------------------
1 file changed, 59 insertions(+), 39 deletions(-)
diff -puN arch/x86/mm/fault.c~pkeys-fault-warnings-00 arch/x86/mm/fault.c
--- a/arch/x86/mm/fault.c~pkeys-fault-warnings-00 2018-09-07 11:21:46.145751902 -0700
+++ b/arch/x86/mm/fault.c 2018-09-07 11:23:37.643751624 -0700
@@ -1033,7 +1033,7 @@ mm_fault_error(struct pt_regs *regs, uns
}
}
-static int spurious_fault_check(unsigned long error_code, pte_t *pte)
+static int spurious_kernel_fault_check(unsigned long error_code, pte_t *pte)
{
if ((error_code & X86_PF_WRITE) && !pte_write(*pte))
return 0;
@@ -1072,7 +1072,7 @@ static int spurious_fault_check(unsigned
* (Optional Invalidation).
*/
static noinline int
-spurious_fault(unsigned long error_code, unsigned long address)
+spurious_kernel_fault(unsigned long error_code, unsigned long address)
{
pgd_t *pgd;
p4d_t *p4d;
@@ -1103,27 +1103,27 @@ spurious_fault(unsigned long error_code,
return 0;
if (p4d_large(*p4d))
- return spurious_fault_check(error_code, (pte_t *) p4d);
+ return spurious_kernel_fault_check(error_code, (pte_t *) p4d);
pud = pud_offset(p4d, address);
if (!pud_present(*pud))
return 0;
if (pud_large(*pud))
- return spurious_fault_check(error_code, (pte_t *) pud);
+ return spurious_kernel_fault_check(error_code, (pte_t *) pud);
pmd = pmd_offset(pud, address);
if (!pmd_present(*pmd))
return 0;
if (pmd_large(*pmd))
- return spurious_fault_check(error_code, (pte_t *) pmd);
+ return spurious_kernel_fault_check(error_code, (pte_t *) pmd);
pte = pte_offset_kernel(pmd, address);
if (!pte_present(*pte))
return 0;
- ret = spurious_fault_check(error_code, pte);
+ ret = spurious_kernel_fault_check(error_code, pte);
if (!ret)
return 0;
@@ -1131,12 +1131,12 @@ spurious_fault(unsigned long error_code,
* Make sure we have permissions in PMD.
* If not, then there's a bug in the page tables:
*/
- ret = spurious_fault_check(error_code, (pte_t *) pmd);
+ ret = spurious_kernel_fault_check(error_code, (pte_t *) pmd);
WARN_ONCE(!ret, "PMD has incorrect permission bits\n");
return ret;
}
-NOKPROBE_SYMBOL(spurious_fault);
+NOKPROBE_SYMBOL(spurious_kernel_fault);
int show_unhandled_signals = 1;
@@ -1203,6 +1203,55 @@ static inline bool smap_violation(int er
return true;
}
+static void
+do_kern_addr_space_fault(struct pt_regs *regs, unsigned long hw_error_code,
+ unsigned long address)
+{
+ /*
+ * We can fault-in kernel-space virtual memory on-demand. The
+ * 'reference' page table is init_mm.pgd.
+ *
+ * NOTE! We MUST NOT take any locks for this case. We may
+ * be in an interrupt or a critical region, and should
+ * only copy the information from the master page table,
+ * nothing more.
+ *
+ * Before doing this on-demand faulting, ensure that the
+ * fault is not any of the following:
+ * 1. A fault on a PTE with a reserved bit set.
+ * 2. A fault caused by a user-mode access. (Do not demand-
+ * fault kernel memory due to user-mode accesses).
+ * 3. A fault caused by a page-level protection violation.
+ * (A demand fault would be on a non-present page which
+ * would have X86_PF_PROT==0).
+ */
+ if (!(hw_error_code & (X86_PF_RSVD | X86_PF_USER | X86_PF_PROT))) {
+ if (vmalloc_fault(address) >= 0)
+ return;
+ }
+
+ /* Was the fault spurious, caused by lazy TLB invalidation? */
+ if (spurious_kernel_fault(hw_error_code, address))
+ return;
+
+ /* kprobes don't want to hook the spurious faults: */
+ if (kprobes_fault(regs))
+ return;
+
+ /*
+ * This is a "bad" fault in the kernel address space. There
+ * is no reasonable explanation for it. We will either kill
+ * the process for making a bad access, or oops the kernel.
+ */
+
+ /*
+ * Don't take the mm semaphore here. If we fixup a prefetch
+ * fault we could otherwise deadlock:
+ */
+ bad_area_nosemaphore(regs, hw_error_code, address, NULL);
+}
+NOKPROBE_SYMBOL(do_kern_addr_space_fault);
+
/*
* This routine handles page faults. It determines the address,
* and the problem, and then passes it off to one of the appropriate
@@ -1228,38 +1277,9 @@ __do_page_fault(struct pt_regs *regs, un
if (unlikely(kmmio_fault(regs, address)))
return;
- /*
- * We fault-in kernel-space virtual memory on-demand. The
- * 'reference' page table is init_mm.pgd.
- *
- * NOTE! We MUST NOT take any locks for this case. We may
- * be in an interrupt or a critical region, and should
- * only copy the information from the master page table,
- * nothing more.
- *
- * This verifies that the fault happens in kernel space
- * (hw_error_code & 4) == 0, and that the fault was not a
- * protection error (hw_error_code & 9) == 0.
- */
+ /* Was the fault on kernel-controlled part of the address space? */
if (unlikely(fault_in_kernel_space(address))) {
- if (!(hw_error_code & (X86_PF_RSVD | X86_PF_USER | X86_PF_PROT))) {
- if (vmalloc_fault(address) >= 0)
- return;
- }
-
- /* Can handle a stale RO->RW TLB: */
- if (spurious_fault(hw_error_code, address))
- return;
-
- /* kprobes don't want to hook the spurious faults: */
- if (kprobes_fault(regs))
- return;
- /*
- * Don't take the mm semaphore here. If we fixup a prefetch
- * fault we could otherwise deadlock:
- */
- bad_area_nosemaphore(regs, hw_error_code, address, NULL);
-
+ do_kern_addr_space_fault(regs, hw_error_code, address);
return;
}
_
next prev parent reply other threads:[~2018-09-07 19:51 UTC|newest]
Thread overview: 25+ messages / expand[flat|nested] mbox.gz Atom feed top
2018-09-07 19:48 [RFC][PATCH 0/8] x86/mm: page fault handling cleanups Dave Hansen
2018-09-07 19:48 ` [RFC][PATCH 1/8] x86/mm: clarify hardware vs. software "error_code" Dave Hansen
2018-09-07 22:48 ` Andy Lutomirski
2018-09-10 20:07 ` Dave Hansen
2018-09-10 21:17 ` Andy Lutomirski
2018-09-07 19:48 ` Dave Hansen [this message]
2018-09-07 21:06 ` [RFC][PATCH 2/8] x86/mm: break out kernel address space handling Sean Christopherson
2018-09-07 21:51 ` Dave Hansen
2018-09-07 22:21 ` Andy Lutomirski
2018-09-07 22:37 ` Dave Hansen
2018-09-07 19:48 ` [RFC][PATCH 3/8] x86/mm: break out user " Dave Hansen
2018-09-08 9:38 ` Peter Zijlstra
2018-09-10 20:20 ` Dave Hansen
2018-09-07 19:48 ` [RFC][PATCH 4/8] x86/mm: add clarifying comments for user addr space Dave Hansen
2018-09-07 19:49 ` [RFC][PATCH 5/8] x86/mm: fix exception table comments Dave Hansen
2018-09-07 21:04 ` Sean Christopherson
2018-09-07 21:51 ` Dave Hansen
2018-09-10 20:43 ` Sean Christopherson
2018-09-08 0:37 ` Jann Horn
2018-09-07 19:49 ` [RFC][PATCH 6/8] x86/mm: add vsyscall address helper Dave Hansen
2018-09-08 0:46 ` Jann Horn
2018-09-07 19:49 ` [RFC][PATCH 7/8] x86/mm/vsyscall: consider vsyscall page part of user address space Dave Hansen
2018-09-07 22:58 ` Andy Lutomirski
2018-09-08 1:16 ` Jann Horn
2018-09-07 19:49 ` [RFC][PATCH 8/8] x86/mm: remove spurious fault pkey check Dave Hansen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20180907194855.74E03836@viggo.jf.intel.com \
--to=dave.hansen@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=peterz@infradead.org \
--cc=sean.j.christopherson@intel.com \
--cc=tglx@linutronix.de \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome