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
[email protected]
http://lists.rtems.org/mailman/listinfo/devel