[Skiboot] [PATCH v3 09/13] xive: Fix locking around cache scrub & watch
Benjamin Herrenschmidt
benh at kernel.crashing.org
Sun Sep 10 17:35:31 AEST 2017
Thankfully the missing locking only affects debug code and
init code that doesn't run concurrently. Also adds a DEBUG
option that checks the lock is properly held.
Signed-off-by: Benjamin Herrenschmidt <benh at kernel.crashing.org>
---
hw/xive.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/hw/xive.c b/hw/xive.c
index 1d306b93..c2360550 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -45,11 +45,13 @@
#define XIVE_PERCPU_LOG
#define XIVE_DEBUG_INIT_CACHE_UPDATES
#define XIVE_EXTRA_CHECK_INIT_CACHE
+#define XIVE_CHECK_LOCKS
#else
#undef XIVE_DEBUG_DUPLICATES
#undef XIVE_PERCPU_LOG
#undef XIVE_DEBUG_INIT_CACHE_UPDATES
#undef XIVE_EXTRA_CHECK_INIT_CACHE
+#undef XIVE_CHECK_LOCKS
#endif
/*
@@ -1245,6 +1247,10 @@ static int64_t __xive_cache_scrub(struct xive *x, enum xive_cache_type ctype,
uint64_t sreg, sregx, mreg, mregx;
uint64_t mval, sval;
+#ifdef XIVE_CHECK_LOCKS
+ assert(lock_held_by_me(&x->lock));
+#endif
+
/* Workaround a HW bug in XIVE where the scrub completion
* isn't ordered by loads, thus the data might still be
* in a queue and may not have reached coherency.
@@ -1341,6 +1347,9 @@ static int64_t __xive_cache_watch(struct xive *x, enum xive_cache_type ctype,
uint64_t dval0, sval, status;
int64_t i;
+#ifdef XIVE_CHECK_LOCKS
+ assert(lock_held_by_me(&x->lock));
+#endif
switch (ctype) {
case xive_cache_eqc:
sreg = VC_EQC_CWATCH_SPEC;
@@ -3016,6 +3025,7 @@ static void xive_setup_hw_for_emu(struct xive_cpu_state *xs)
xs->eq_page, XIVE_EMULATION_PRIO);
/* Use the cache watch to write it out */
+ lock(&x_eq->lock);
xive_eqc_cache_update(x_eq, xs->eq_blk,
xs->eq_idx + XIVE_EMULATION_PRIO,
0, 4, &eq, false, true);
@@ -3023,14 +3033,17 @@ static void xive_setup_hw_for_emu(struct xive_cpu_state *xs)
/* Extra testing of cache watch & scrub facilities */
xive_special_cache_check(x_vp, xs->vp_blk, xs->vp_idx);
+ unlock(&x_eq->lock);
/* Initialize/enable the VP */
xive_init_default_vp(&vp, xs->eq_blk, xs->eq_idx);
/* Use the cache watch to write it out */
+ lock(&x_vp->lock);
xive_vpc_cache_update(x_vp, xs->vp_blk, xs->vp_idx,
0, 8, &vp, false, true);
xive_check_vpc_update(x_vp, xs->vp_idx, &vp);
+ unlock(&x_vp->lock);
}
static void xive_init_cpu_emulation(struct xive_cpu_state *xs,
@@ -3075,8 +3088,10 @@ static void xive_init_cpu_exploitation(struct xive_cpu_state *xs)
xive_init_default_vp(&vp, xs->eq_blk, xs->eq_idx);
/* Use the cache watch to write it out */
+ lock(&x_vp->lock);
xive_vpc_cache_update(x_vp, xs->vp_blk, xs->vp_idx,
0, 8, &vp, false, true);
+ unlock(&x_vp->lock);
/* Clenaup remaining state */
xs->cppr = 0;
@@ -3263,9 +3278,11 @@ static uint32_t xive_read_eq(struct xive_cpu_state *xs, bool just_peek)
xs->eqbuf[(xs->eqptr + 2) & xs->eqmsk],
xs->eqbuf[(xs->eqptr + 3) & xs->eqmsk],
xs->eqgen, xs->eqptr, just_peek);
+ lock(&xs->xive->lock);
__xive_cache_scrub(xs->xive, xive_cache_eqc, xs->eq_blk,
xs->eq_idx + XIVE_EMULATION_PRIO,
false, false);
+ unlock(&xs->xive->lock);
eq = xive_get_eq(xs->xive, xs->eq_idx + XIVE_EMULATION_PRIO);
prerror("EQ @%p W0=%08x W1=%08x qbuf @%p\n",
eq, eq->w0, eq->w1, xs->eqbuf);
@@ -3503,9 +3520,11 @@ static int64_t opal_xive_get_xirr(uint32_t *out_xirr, bool just_poll)
#ifdef XIVE_PERCPU_LOG
{
struct xive_eq *eq;
+ lock(&xs->xive->lock);
__xive_cache_scrub(xs->xive, xive_cache_eqc, xs->eq_blk,
xs->eq_idx + XIVE_EMULATION_PRIO,
false, false);
+ unlock(&xs->xive->lock);
eq = xive_get_eq(xs->xive, xs->eq_idx + XIVE_EMULATION_PRIO);
log_add(xs, LOG_TYPE_EQD, 2, eq->w0, eq->w1);
}
--
2.13.5
More information about the Skiboot
mailing list