Skip to content

Commit f79ad50

Browse files
bsingharorampe
authored andcommitted
powerpc/mm/radix: Fix crashes on Power9 DD1 with radix MMU and STRICT_RWX
When using the radix MMU on Power9 DD1, to work around a hardware problem, radix__pte_update() is required to do a two stage update of the PTE. First we write a zero value into the PTE, then we flush the TLB, and then we write the new PTE value. In the normal case that works OK, but it does not work if we're updating the PTE that maps the code we're executing, because the mapping is removed by the TLB flush and we can no longer execute from it. Unfortunately the STRICT_RWX code needs to do exactly that. The exact symptoms when we hit this case vary, sometimes we print an oops and then get stuck after that, but I've also seen a machine just get stuck continually page faulting with no oops printed. The variance is presumably due to the exact layout of the text and the page size used for the mappings. In all cases we are unable to boot to a shell. There are possible solutions such as creating a second mapping of the TLB flush code, executing from that, and then jumping back to the original. However we don't want to add that level of complexity for a DD1 work around. So just detect that we're running on Power9 DD1 and refrain from changing the permissions, effectively disabling STRICT_RWX on Power9 DD1. Fixes: 7614ff3 ("powerpc/mm/radix: Implement STRICT_RWX/mark_rodata_ro() for Radix") Cc: [email protected] # v4.13+ Reported-by: Andrew Jeffery <[email protected]> [Changelog as suggested by Michael Ellerman <[email protected]>] Signed-off-by: Balbir Singh <[email protected]> Signed-off-by: Michael Ellerman <[email protected]>
1 parent 0f46a79 commit f79ad50

File tree

1 file changed

+10
-0
lines changed

1 file changed

+10
-0
lines changed

arch/powerpc/mm/pgtable-radix.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,16 @@ void radix__mark_rodata_ro(void)
169169
{
170170
unsigned long start, end;
171171

172+
/*
173+
* mark_rodata_ro() will mark itself as !writable at some point.
174+
* Due to DD1 workaround in radix__pte_update(), we'll end up with
175+
* an invalid pte and the system will crash quite severly.
176+
*/
177+
if (cpu_has_feature(CPU_FTR_POWER9_DD1)) {
178+
pr_warn("Warning: Unable to mark rodata read only on P9 DD1\n");
179+
return;
180+
}
181+
172182
start = (unsigned long)_stext;
173183
end = (unsigned long)__init_begin;
174184

0 commit comments

Comments
 (0)