Index: sys/arm/arm/sys_machdep.c =================================================================== --- sys/arm/arm/sys_machdep.c +++ sys/arm/arm/sys_machdep.c @@ -42,6 +42,10 @@ #include #include +#include +#include +#include + #include #ifndef _SYS_SYSPROTO_H_ @@ -59,12 +63,46 @@ arm32_sync_icache(struct thread *td, void *args) { struct arm_sync_icache_args ua; + uintptr_t addr; + pmap_t pmap; + size_t len, plen; int error; if ((error = copyin(args, &ua, sizeof(ua))) != 0) return (error); - cpu_icache_sync_range(ua.addr, ua.len); + if (ua.len > 0) { + addr = rounddown2(ua.addr, 32); + len = ua.len + (ua.addr - addr); + len = roundup2(len, 32); + + pmap = vmspace_pmap(curthread->td_proc->p_vmspace); + + /* Sync the first partial page */ + if ((addr & PAGE_MASK) != 0) { + plen = PAGE_SIZE - (addr & PAGE_MASK); + plen = MIN(plen, len); + + if (pmap_extract(pmap, addr) != 0) + cpu_icache_sync_range(addr, plen); + + addr += plen; + len -= plen; + } + + /* Sync all the full pages */ + while (len > PAGE_SIZE) { + if (pmap_extract(pmap, addr) != 0) + cpu_icache_sync_range(addr, PAGE_SIZE); + + addr += PAGE_SIZE; + len -= PAGE_SIZE; + } + + /* Sync the last partial page */ + if (len > 0 && pmap_extract(pmap, addr) != 0) + cpu_icache_sync_range(addr, len); + } td->td_retval[0] = 0; return (0);