ARMv8 (like ARMv7) does not guarantee coherence between the instruction and data caches. After writing data to memory that contains executable instructions, cache maintenance (flush, invalidate) is needed. The arm64 pmap implements this, but only for the case where the address space that needs flushing is currently active on this CPU. However, that is not the case when a debugger (e.g. GDB) writes a breakpoint into instruction memory using ptrace(2). Diff below adds support for that case.
With this diff breakpoints in GDB seem to work reliably. ok? Index: arch/arm64/arm64/pmap.c =================================================================== RCS file: /cvs/src/sys/arch/arm64/arm64/pmap.c,v retrieving revision 1.55 diff -u -p -r1.55 pmap.c --- arch/arm64/arm64/pmap.c 15 Aug 2018 20:18:31 -0000 1.55 +++ arch/arm64/arm64/pmap.c 15 Aug 2018 21:59:34 -0000 @@ -1537,9 +1537,44 @@ pmap_init(void) void pmap_proc_iflush(struct process *pr, vaddr_t va, vsize_t len) { - /* We only need to do anything if it is the current process. */ - if (pr == curproc->p_p) + struct pmap *pm = vm_map_pmap(&pr->ps_vmspace->vm_map); + vaddr_t kva = zero_page + cpu_number() * PAGE_SIZE; + paddr_t pa; + vsize_t clen; + vsize_t off; + + /* + * If we're caled for the current processes, we can simply + * flush the data cache to the point of point of unification + * and invalidate the instruction cache. + */ + if (pr == curproc->p_p) { cpu_icache_sync_range(va, len); + return; + } + + /* + * Flush and invalidate through an aliased mapping. This + * assumes the instruction cache is either VIPT or PIPT, + * i.e. if the CPU implements the IVIPT extension. This is + * true for all hardware we run on. + */ + while (len > 0) { + /* add one to always round up to the next page */ + clen = round_page(va + 1) - va; + if (clen > len) + clen = len; + + off = va - trunc_page(va); + if (pmap_extract(pm, trunc_page(va), &pa)) { + pmap_kenter_pa(kva, pa, PROT_READ|PROT_WRITE); + cpu_icache_sync_range(kva + off, clen); + pmap_kremove_pg(kva); + } + + len -= clen; + va += clen; + } } void