Accesses to the L2C registers performed by the L2C driver are now serialized with spin locks. This avoids concurrent access to the L2C registers by multiple processors. Proposed by GRLIB-TN-0021.
Update #4925. --- bsps/shared/grlib/l2c/l2c.c | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/bsps/shared/grlib/l2c/l2c.c b/bsps/shared/grlib/l2c/l2c.c index f989a8eda1..9e2d135179 100644 --- a/bsps/shared/grlib/l2c/l2c.c +++ b/bsps/shared/grlib/l2c/l2c.c @@ -38,6 +38,7 @@ #include <grlib/grlib.h> #include <bsp.h> #include <grlib/l2c.h> +#include <grlib/grlib_impl.h> /*#define STATIC*/ #define STATIC static @@ -317,6 +318,8 @@ struct l2cache_priv { int ft_support; int split_support; int atomic_flush; + /* Avoid concurrent accesses to L2C registers. */ + SPIN_DECLARE(devlock); /* User defined ISR */ l2cache_isr_t isr; @@ -383,8 +386,25 @@ static struct l2cache_priv *l2cachepriv = NULL; static char * repl_names[4] = {"LRU","Random","Master-Idx-1","Master-IDx-2"}; #endif -#define REG_WRITE(addr, val) (*(volatile unsigned int *)(addr) = (unsigned int)(val)) -#define REG_READ(addr) (*(volatile unsigned int *)(addr)) +static void REG_WRITE(volatile unsigned int *addr, unsigned int val) { + struct l2cache_priv *priv = l2cachepriv; + SPIN_IRQFLAGS(irqflags); + + SPIN_LOCK_IRQ(&priv->devlock, irqflags); + *addr = val; + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); +} + +static unsigned int REG_READ(volatile unsigned int *addr) { + struct l2cache_priv *priv = l2cachepriv; + SPIN_IRQFLAGS(irqflags); + unsigned int val; + + SPIN_LOCK_IRQ(&priv->devlock, irqflags); + val = *addr; + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); + return val; +} #if defined(__sparc__) static inline uint32_t atomic_swap32(uint32_t *addr, uint32_t val) { @@ -397,7 +417,15 @@ static inline uint32_t atomic_swap32(uint32_t *addr, uint32_t val) { return val; } -#define REG_WRITE_ATOMIC(addr, val) atomic_swap32((uint32_t *)addr, val) +static void REG_WRITE_ATOMIC(volatile unsigned int *addr, unsigned int val) { + struct l2cache_priv *priv = l2cachepriv; + SPIN_IRQFLAGS(irqflags); + + SPIN_LOCK_IRQ(&priv->devlock, irqflags); + atomic_swap32((uint32_t *) addr, val); + SPIN_UNLOCK_IRQ(&priv->devlock, irqflags); +} + #else #define REG_WRITE_ATOMIC(addr, val) REG_WRITE(addr, val) #endif @@ -513,6 +541,7 @@ int l2cache_init1(struct drvmgr_dev *dev) priv->dev = dev; strncpy(&priv->devname[0], "l2cache0", DEVNAME_LEN); l2cachepriv = priv; + SPIN_INIT(&priv->devlock, priv->devname); /* Initialize L2CACHE Hardware */ status = l2cache_init(priv); -- 2.34.1 _______________________________________________ devel mailing list devel@rtems.org http://lists.rtems.org/mailman/listinfo/devel