powerpc: Handle exceptions caused by pkey violation
Handle Data and Instruction exceptions caused by memory protection-key. The CPU will detect the key fault if the HPTE is already programmed with the key. However if the HPTE is not hashed, a key fault will not be detected by the hardware. The software will detect pkey violation in such a case. Signed-off-by: Ram Pai <linuxram@us.ibm.com> Signed-off-by: Thiago Jung Bauermann <bauerman@linux.vnet.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
This commit is contained in:
Родитель
1137573acf
Коммит
e6c2a4797e
|
@ -312,7 +312,6 @@
|
|||
DSISR_BAD_EXT_CTRL)
|
||||
#define DSISR_BAD_FAULT_64S (DSISR_BAD_FAULT_32S | \
|
||||
DSISR_ATTR_CONFLICT | \
|
||||
DSISR_KEYFAULT | \
|
||||
DSISR_UNSUPP_MMU | \
|
||||
DSISR_PRTABLE_FAULT | \
|
||||
DSISR_ICSWX_NO_CT | \
|
||||
|
|
|
@ -1527,7 +1527,7 @@ USE_TEXT_SECTION()
|
|||
.balign IFETCH_ALIGN_BYTES
|
||||
do_hash_page:
|
||||
#ifdef CONFIG_PPC_BOOK3S_64
|
||||
lis r0,(DSISR_BAD_FAULT_64S|DSISR_DABRMATCH)@h
|
||||
lis r0,(DSISR_BAD_FAULT_64S | DSISR_DABRMATCH | DSISR_KEYFAULT)@h
|
||||
ori r0,r0,DSISR_BAD_FAULT_64S@l
|
||||
and. r0,r4,r0 /* weird error? */
|
||||
bne- handle_page_fault /* if not, try to insert a HPTE */
|
||||
|
|
|
@ -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;
|
||||
|
||||
/*
|
||||
|
|
Загрузка…
Ссылка в новой задаче