From 85add65a91ab1b2db08047003c978f4c2c767593 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20=C3=85berg?= Date: Tue, 16 Jan 2024 15:06:30 +0100 Subject: [PATCH] grlib/l2c: Prevent concurrent register access 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 #include #include +#include /*#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);