diff options
author | Balbir Singh <bsingharora@gmail.com> | 2016-11-30 11:35:36 +1100 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2016-11-30 17:19:01 +1100 |
commit | 0ab5171b8971282d7562b77f9b14137a827117fc (patch) | |
tree | 7136afdb2aa02fd3aa05ab376a2ee434f9701b7d /arch/powerpc | |
parent | f0f7fe1ac35330f077357c787ec5bd8958bf300d (diff) | |
download | linux-0ab5171b8971282d7562b77f9b14137a827117fc.tar.bz2 |
powerpc/mm: Fix no execute fault handling on pre-POWER5
Aneesh/Ben reported that the change to do_page_fault() we made in commit
1d18ad026844 ("powerpc/mm: Detect instruction fetch denied and report")
needs to handle the case where CPU_FTR_COHERENT_ICACHE is missing but we
have CPU_FTR_NOEXECUTE. In those cases the check added for
SRR1_ISI_N_OR_G might trigger a false positive.
This patch adds a check for CPU_FTR_COHERENT_ICACHE in addition to the
MSR value.
Fixes: 1d18ad026844 ("powerpc/mm: Detect instruction fetch denied and report")
Reported-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Signed-off-by: Balbir Singh <bsingharora@gmail.com>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/mm/fault.c | 10 |
1 files changed, 9 insertions, 1 deletions
diff --git a/arch/powerpc/mm/fault.c b/arch/powerpc/mm/fault.c index a17029aaf939..6fd30ac7d14a 100644 --- a/arch/powerpc/mm/fault.c +++ b/arch/powerpc/mm/fault.c @@ -392,8 +392,16 @@ good_area: if (is_exec) { /* * An execution fault + no execute ? + * + * On CPUs that don't have CPU_FTR_COHERENT_ICACHE we + * deliberately create NX mappings, and use the fault to do the + * cache flush. This is usually handled in hash_page_do_lazy_icache() + * but we could end up here if that races with a concurrent PTE + * update. In that case we need to fall through here to the VMA + * check below. */ - if (regs->msr & SRR1_ISI_N_OR_G) + if (cpu_has_feature(CPU_FTR_COHERENT_ICACHE) && + (regs->msr & SRR1_ISI_N_OR_G)) goto bad_area; /* |