|
@@ -427,6 +427,11 @@ static int __do_page_fault(struct pt_regs *regs, unsigned long address,
|
|
|
|
|
|
perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
|
|
|
|
|
|
+ if (error_code & DSISR_KEYFAULT) {
|
|
|
+ _exception(SIGSEGV, regs, SEGV_PKUERR, address);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* We want to do this outside mmap_sem, because reading code around nip
|
|
|
* can result in fault, which will cause a deadlock when called with
|
|
@@ -498,6 +503,23 @@ good_area:
|
|
|
* the fault.
|
|
|
*/
|
|
|
fault = handle_mm_fault(vma, address, flags);
|
|
|
+
|
|
|
+#ifdef CONFIG_PPC_MEM_KEYS
|
|
|
+ /*
|
|
|
+ * if the HPTE is not hashed, hardware will not detect
|
|
|
+ * a key fault. Lets check if we failed because of a
|
|
|
+ * software detected key fault.
|
|
|
+ */
|
|
|
+ if (unlikely(fault & VM_FAULT_SIGSEGV) &&
|
|
|
+ !arch_vma_access_permitted(vma, flags & FAULT_FLAG_WRITE,
|
|
|
+ is_exec, 0)) {
|
|
|
+ int pkey = vma_pkey(vma);
|
|
|
+
|
|
|
+ if (likely(pkey))
|
|
|
+ return __bad_area(regs, address, SEGV_PKUERR);
|
|
|
+ }
|
|
|
+#endif /* CONFIG_PPC_MEM_KEYS */
|
|
|
+
|
|
|
major |= fault & VM_FAULT_MAJOR;
|
|
|
|
|
|
/*
|