Date: Sat, 17 May 2014 22:50:16 +0000 (UTC) From: Ian Lepore <ian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r266373 - in stable/10/sys/arm: arm include Message-ID: <201405172250.s4HMoGKq060042@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: ian Date: Sat May 17 22:50:16 2014 New Revision: 266373 URL: http://svnweb.freebsd.org/changeset/base/266373 Log: MFC 264990, 264994, 265020, 265025: Call cpu_icache_sync_range() rather than sync_all since we know the range and flushing the entire icache is needlessly expensive. Provide a proper armv7 implementation of icache_sync_all rather than using armv7_idcache_wbinv_all, because wbinv_all doesn't broadcast the operation to other cores. In elf_cpu_load_file() use icache_sync_all() and explain why it's needed (and why other sync operations aren't). Remove cpu_idcache_wbinv_all() from kdb_cpu_trap(), it's no longer needed. Explain why wbinv_all is SMP-safe when dumping, and add a missing l2 cache flush. (Either it was missing here, or it isn't needed in the minidump case. Adding it here seems like the safer path to consistancy.) Modified: stable/10/sys/arm/arm/cpufunc.c stable/10/sys/arm/arm/cpufunc_asm_armv7.S stable/10/sys/arm/arm/dump_machdep.c stable/10/sys/arm/arm/elf_machdep.c stable/10/sys/arm/include/cpufunc.h stable/10/sys/arm/include/kdb.h Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/arm/arm/cpufunc.c ============================================================================== --- stable/10/sys/arm/arm/cpufunc.c Sat May 17 22:31:40 2014 (r266372) +++ stable/10/sys/arm/arm/cpufunc.c Sat May 17 22:50:16 2014 (r266373) @@ -769,7 +769,7 @@ struct cpu_functions cortexa_cpufuncs = /* Cache operations */ - armv7_idcache_wbinv_all, /* icache_sync_all */ + armv7_icache_sync_all, /* icache_sync_all */ armv7_icache_sync_range, /* icache_sync_range */ armv7_dcache_wbinv_all, /* dcache_wbinv_all */ Modified: stable/10/sys/arm/arm/cpufunc_asm_armv7.S ============================================================================== --- stable/10/sys/arm/arm/cpufunc_asm_armv7.S Sat May 17 22:31:40 2014 (r266372) +++ stable/10/sys/arm/arm/cpufunc_asm_armv7.S Sat May 17 22:50:16 2014 (r266373) @@ -250,6 +250,13 @@ ENTRY(armv7_idcache_wbinv_range) RET END(armv7_idcache_wbinv_range) +ENTRY_NP(armv7_icache_sync_all) + mcr p15, 0, r0, c7, c1, 0 /* Invalidate all I cache to PoU Inner Shareable */ + isb /* instruction synchronization barrier */ + dsb /* data synchronization barrier */ + RET +END(armv7_icache_sync_all) + ENTRY_NP(armv7_icache_sync_range) ldr ip, .Larmv7_line_size .Larmv7_sync_next: Modified: stable/10/sys/arm/arm/dump_machdep.c ============================================================================== --- stable/10/sys/arm/arm/dump_machdep.c Sat May 17 22:31:40 2014 (r266372) +++ stable/10/sys/arm/arm/dump_machdep.c Sat May 17 22:50:16 2014 (r266373) @@ -174,8 +174,14 @@ cb_dumpdata(struct md_pa *mdp, int seqnr printf(" chunk %d: %dMB (%d pages)", seqnr, pgs * PAGE_SIZE / ( 1024*1024), pgs); - /* Make sure we write coherent datas. */ + /* + * Make sure we write coherent data. Note that in the SMP case this + * only operates on the L1 cache of the current CPU, but all other CPUs + * have already been stopped, and their flush/invalidate was done as + * part of stopping. + */ cpu_idcache_wbinv_all(); + cpu_l2cache_wbinv_all(); #ifdef __XSCALE__ xscale_cache_clean_minidata(); #endif Modified: stable/10/sys/arm/arm/elf_machdep.c ============================================================================== --- stable/10/sys/arm/arm/elf_machdep.c Sat May 17 22:31:40 2014 (r266372) +++ stable/10/sys/arm/arm/elf_machdep.c Sat May 17 22:50:16 2014 (r266373) @@ -220,9 +220,19 @@ int elf_cpu_load_file(linker_file_t lf __unused) { - cpu_idcache_wbinv_all(); - cpu_l2cache_wbinv_all(); - cpu_tlb_flushID(); + /* + * The pmap code does not do an icache sync upon establishing executable + * mappings in the kernel pmap. It's an optimization based on the fact + * that kernel memory allocations always have EXECUTABLE protection even + * when the memory isn't going to hold executable code. The only time + * kernel memory holding instructions does need a sync is after loading + * a kernel module, and that's when this function gets called. Normal + * data cache maintenance has already been done by the IO code, and TLB + * maintenance has been done by the pmap code, so all we have to do here + * is invalidate the instruction cache (which also invalidates the + * branch predictor cache on platforms that have one). + */ + cpu_icache_sync_all(); return (0); } Modified: stable/10/sys/arm/include/cpufunc.h ============================================================================== --- stable/10/sys/arm/include/cpufunc.h Sat May 17 22:31:40 2014 (r266372) +++ stable/10/sys/arm/include/cpufunc.h Sat May 17 22:50:16 2014 (r266373) @@ -411,6 +411,7 @@ void armv6_idcache_wbinv_range (vm_offse void armv7_setttb (u_int); void armv7_tlb_flushID (void); void armv7_tlb_flushID_SE (u_int); +void armv7_icache_sync_all (); void armv7_icache_sync_range (vm_offset_t, vm_size_t); void armv7_idcache_wbinv_range (vm_offset_t, vm_size_t); void armv7_idcache_inv_all (void); Modified: stable/10/sys/arm/include/kdb.h ============================================================================== --- stable/10/sys/arm/include/kdb.h Sat May 17 22:31:40 2014 (r266372) +++ stable/10/sys/arm/include/kdb.h Sat May 17 22:50:16 2014 (r266373) @@ -49,14 +49,12 @@ static __inline void kdb_cpu_sync_icache(unsigned char *addr, size_t size) { - cpu_icache_sync_all(); + cpu_icache_sync_range((vm_offset_t)addr, size); } static __inline void kdb_cpu_trap(int type, int code) { - - cpu_idcache_wbinv_all(); } #endif /* _MACHINE_KDB_H_ */
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201405172250.s4HMoGKq060042>