mmu_radix_sync_icache() adds the offset of va within its page to the
physical address it gets from mmu_radix_extract_locked(). That address
already includes the offset - the extract routines return the physical
address of the byte, not of the frame - so the offset is counted twice
and __syncicache() is handed frame + 2 * offset.
The hash MMU counterpart, moea64_sync_icache(), has to add the offset
because PVO_PADDR() yields only the frame. Here the addition is wrong.
Unless va sits at the very start of a page, the cache lines that get
synced are therefore not the ones that were modified. This has gone
unnoticed because POWER9 keeps its instruction cache coherent with
stores in hardware: a thread spinning on an instruction sees another
CPU's store to it within microseconds even when nothing is synced at
all. The wrong address is not harmless, though. Once the offset
reaches half a page the sync lands in the following physical page, and
if the page being synced is the last one of a physical memory region
that address may not be covered by the direct map, in which case the
kernel takes a data storage interrupt.
Both users of this method pass addresses at arbitrary page offsets:
ppc_instr_emulate() syncs the faulting srr0 before retrying an illegal
instruction, and proc_rwmem() syncs after writing to another process,
which is how ptrace(2) and the DTrace pid provider install breakpoints.
Drop the addition.
Fixes: 6f0b2a235a13 ("powerpc/pmap: Add pmap_sync_icache() for radix pmap")
MFC after: 1 week