From 819d3cb189b526ae3391104f12ed538abe00a1ea Mon Sep 17 00:00:00 2001 From: ian Date: Sun, 18 May 2014 00:55:26 +0000 Subject: [PATCH] MFC 265861, 265870: Make the hardware memory and instruction barrier functions work on armv4 and armv5 as well. Add cpu_l2cache_drain_writebuf(), use it to implement generic_bs_barrier(). git-svn-id: svn://svn.freebsd.org/base/stable/10@266387 ccf9f872-aa2e-dd11-9fc8-001c23d0bc1f --- sys/arm/arm/bus_space_generic.c | 14 +++++++++++++- sys/arm/arm/cpufunc.c | 11 +++++++++++ sys/arm/arm/pl310.c | 13 +++++++++++++ sys/arm/include/atomic.h | 6 +++--- sys/arm/include/cpufunc.h | 2 ++ 5 files changed, 42 insertions(+), 4 deletions(-) diff --git a/sys/arm/arm/bus_space_generic.c b/sys/arm/arm/bus_space_generic.c index 8d272c406..35052ecf9 100644 --- a/sys/arm/arm/bus_space_generic.c +++ b/sys/arm/arm/bus_space_generic.c @@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include /* Prototypes for all the bus_space structure functions */ @@ -110,5 +111,16 @@ generic_bs_barrier(void *t, bus_space_handle_t bsh, bus_size_t offset, bus_size_t len, int flags) { - /* Nothing to do. */ + /* + * dsb() will drain the L1 write buffer and establish a memory access + * barrier point on platforms where that has meaning. On a write we + * also need to drain the L2 write buffer, because most on-chip memory + * mapped devices are downstream of the L2 cache. Note that this needs + * to be done even for memory mapped as Device type, because while + * Device memory is not cached, writes to it are still buffered. + */ + dsb(); + if (flags & BUS_SPACE_BARRIER_WRITE) { + cpu_l2cache_drain_writebuf(); + } } diff --git a/sys/arm/arm/cpufunc.c b/sys/arm/arm/cpufunc.c index dce17b4f6..1f4bb2e8c 100644 --- a/sys/arm/arm/cpufunc.c +++ b/sys/arm/arm/cpufunc.c @@ -150,6 +150,7 @@ struct cpu_functions arm9_cpufuncs = { (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ + (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ /* Other functions */ @@ -214,6 +215,7 @@ struct cpu_functions armv5_ec_cpufuncs = { (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ + (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ /* Other functions */ @@ -276,6 +278,7 @@ struct cpu_functions sheeva_cpufuncs = { sheeva_l2cache_wbinv_range, /* l2cache_wbinv_range */ sheeva_l2cache_inv_range, /* l2cache_inv_range */ sheeva_l2cache_wb_range, /* l2cache_wb_range */ + (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ /* Other functions */ @@ -338,6 +341,7 @@ struct cpu_functions arm10_cpufuncs = { (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ + (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ /* Other functions */ @@ -401,6 +405,7 @@ struct cpu_functions pj4bv7_cpufuncs = { (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ + (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ /* Other functions */ @@ -466,6 +471,7 @@ struct cpu_functions xscale_cpufuncs = { (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ + (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ /* Other functions */ @@ -530,6 +536,7 @@ struct cpu_functions xscalec3_cpufuncs = { xscalec3_l2cache_purge_rng, /* l2cache_wbinv_range */ xscalec3_l2cache_flush_rng, /* l2cache_inv_range */ xscalec3_l2cache_clean_rng, /* l2cache_wb_range */ + (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ /* Other functions */ @@ -593,6 +600,7 @@ struct cpu_functions fa526_cpufuncs = { (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ + (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ /* Other functions */ @@ -656,6 +664,7 @@ struct cpu_functions arm1136_cpufuncs = { (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ + (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ /* Other functions */ @@ -718,6 +727,7 @@ struct cpu_functions arm1176_cpufuncs = { (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ + (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ /* Other functions */ @@ -789,6 +799,7 @@ struct cpu_functions cortexa_cpufuncs = { (void *)cpufunc_nullop, /* l2cache_wbinv_range */ (void *)cpufunc_nullop, /* l2cache_inv_range */ (void *)cpufunc_nullop, /* l2cache_wb_range */ + (void *)cpufunc_nullop, /* l2cache_drain_writebuf */ /* Other functions */ diff --git a/sys/arm/arm/pl310.c b/sys/arm/arm/pl310.c index 83e690711..cf19d6c4b 100644 --- a/sys/arm/arm/pl310.c +++ b/sys/arm/arm/pl310.c @@ -349,6 +349,18 @@ pl310_inv_range(vm_paddr_t start, vm_size_t size) PL310_UNLOCK(pl310_softc); } +static void +pl310_drain_writebuf(void) +{ + + if ((pl310_softc == NULL) || !pl310_softc->sc_enabled) + return; + + PL310_LOCK(pl310_softc); + pl310_cache_sync(); + PL310_UNLOCK(pl310_softc); +} + static void pl310_set_way_sizes(struct pl310_softc *sc) { @@ -484,6 +496,7 @@ pl310_attach(device_t dev) cpufuncs.cf_l2cache_wbinv_range = pl310_wbinv_range; cpufuncs.cf_l2cache_inv_range = pl310_inv_range; cpufuncs.cf_l2cache_wb_range = pl310_wb_range; + cpufuncs.cf_l2cache_drain_writebuf = pl310_drain_writebuf; return (0); } diff --git a/sys/arm/include/atomic.h b/sys/arm/include/atomic.h index 4ac5a3fb0..f07fcef78 100644 --- a/sys/arm/include/atomic.h +++ b/sys/arm/include/atomic.h @@ -58,9 +58,9 @@ #define dsb() __asm __volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0) : "memory") #define dmb() __asm __volatile("mcr p15, 0, %0, c7, c10, 5" : : "r" (0) : "memory") #else -#define isb() -#define dsb() -#define dmb() +#define isb() __asm __volatile("mcr p15, 0, %0, c7, c5, 4" : : "r" (0) : "memory") +#define dsb() __asm __volatile("mcr p15, 0, %0, c7, c10, 4" : : "r" (0) : "memory") +#define dmb() dsb() #endif #define mb() dmb() diff --git a/sys/arm/include/cpufunc.h b/sys/arm/include/cpufunc.h index c2a96a815..16887b0fc 100644 --- a/sys/arm/include/cpufunc.h +++ b/sys/arm/include/cpufunc.h @@ -151,6 +151,7 @@ struct cpu_functions { void (*cf_l2cache_wbinv_range) (vm_offset_t, vm_size_t); void (*cf_l2cache_inv_range) (vm_offset_t, vm_size_t); void (*cf_l2cache_wb_range) (vm_offset_t, vm_size_t); + void (*cf_l2cache_drain_writebuf) (void); /* Other functions */ @@ -252,6 +253,7 @@ void tlb_broadcast(int); #define cpu_l2cache_wb_range(a, s) cpufuncs.cf_l2cache_wb_range((a), (s)) #define cpu_l2cache_inv_range(a, s) cpufuncs.cf_l2cache_inv_range((a), (s)) #define cpu_l2cache_wbinv_range(a, s) cpufuncs.cf_l2cache_wbinv_range((a), (s)) +#define cpu_l2cache_drain_writebuf() cpufuncs.cf_l2cache_drain_writebuf() #define cpu_flush_prefetchbuf() cpufuncs.cf_flush_prefetchbuf() #define cpu_drain_writebuf() cpufuncs.cf_drain_writebuf() -- 2.45.0