summaryrefslogtreecommitdiffstats
path: root/hw/xive.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2017-09-10 17:36:00 +1000
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-09-12 22:52:08 -0500
commit2eea386767728cf4fa13b5fc983bcffef0d51dfe (patch)
tree9fc0f1c8f15d855e0aea08ee29d1bba3eeb7a23e /hw/xive.c
parent3ef155f8e7d17728ab2c888294301d0d9509ef61 (diff)
downloadblackbird-skiboot-2eea386767728cf4fa13b5fc983bcffef0d51dfe.tar.gz
blackbird-skiboot-2eea386767728cf4fa13b5fc983bcffef0d51dfe.zip
xive: Add exerciser for cache watch/scrub facility in DEBUG builds
This runs 1000 iterations exercising the cache watch and scrub facilities on VPs and ENDs at boot. This exposes a HW bug with the scrub which will be worked around in a subsequent patch. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
Diffstat (limited to 'hw/xive.c')
-rw-r--r--hw/xive.c141
1 files changed, 96 insertions, 45 deletions
diff --git a/hw/xive.c b/hw/xive.c
index 4f08e655..d8d51dee 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -44,10 +44,12 @@
#define XIVE_DEBUG_DUPLICATES
#define XIVE_PERCPU_LOG
#define XIVE_DEBUG_INIT_CACHE_UPDATES
+#define XIVE_EXTRA_CHECK_INIT_CACHE
#else
#undef XIVE_DEBUG_DUPLICATES
#undef XIVE_PERCPU_LOG
#undef XIVE_DEBUG_INIT_CACHE_UPDATES
+#undef XIVE_EXTRA_CHECK_INIT_CACHE
#endif
/*
@@ -2870,6 +2872,95 @@ void xive_cpu_callin(struct cpu_thread *cpu)
in_be64(xs->tm_ring1 + TM_QW3_HV_PHYS));
}
+#ifdef XIVE_DEBUG_INIT_CACHE_UPDATES
+static bool xive_check_eq_update(struct xive *x, uint32_t idx, struct xive_eq *eq)
+{
+ struct xive_eq *eq_p = xive_get_eq(x, idx);
+ struct xive_eq eq2;
+
+ assert(eq_p);
+ eq2 = *eq_p;
+ if (memcmp(eq, &eq2, sizeof(eq)) != 0) {
+ xive_err(x, "EQ update mismatch idx %d\n", idx);
+ xive_err(x, "want: %08x %08x %08x %08x\n",
+ eq->w0, eq->w1, eq->w2, eq->w3);
+ xive_err(x, " %08x %08x %08x %08x\n",
+ eq->w4, eq->w5, eq->w6, eq->w7);
+ xive_err(x, "got : %08x %08x %08x %08x\n",
+ eq2.w0, eq2.w1, eq2.w2, eq2.w3);
+ xive_err(x, " %08x %08x %08x %08x\n",
+ eq2.w4, eq2.w5, eq2.w6, eq2.w7);
+ return false;
+ }
+ return true;
+}
+
+static bool xive_check_vpc_update(struct xive *x, uint32_t idx, struct xive_vp *vp)
+{
+ struct xive_vp *vp_p = xive_get_vp(x, idx);
+ struct xive_vp vp2;
+
+ assert(vp_p);
+ vp2 = *vp_p;
+ if (memcmp(vp, &vp2, sizeof(vp)) != 0) {
+ xive_err(x, "VP update mismatch idx %d\n", idx);
+ xive_err(x, "want: %08x %08x %08x %08x\n",
+ vp->w0, vp->w1, vp->w2, vp->w3);
+ xive_err(x, " %08x %08x %08x %08x\n",
+ vp->w4, vp->w5, vp->w6, vp->w7);
+ xive_err(x, "got : %08x %08x %08x %08x\n",
+ vp2.w0, vp2.w1, vp2.w2, vp2.w3);
+ xive_err(x, " %08x %08x %08x %08x\n",
+ vp2.w4, vp2.w5, vp2.w6, vp2.w7);
+ return false;
+ }
+ return true;
+}
+#else
+static inline bool xive_check_eq_update(struct xive *x __unused,
+ uint32_t idx __unused,
+ struct xive_eq *eq __unused)
+{
+ return true;
+}
+
+static inline bool xive_check_vpc_update(struct xive *x __unused,
+ uint32_t idx __unused,
+ struct xive_vp *vp __unused)
+{
+ return true;
+}
+#endif
+
+#ifdef XIVE_EXTRA_CHECK_INIT_CACHE
+static void xive_special_cache_check(struct xive *x, uint32_t blk, uint32_t idx)
+{
+ struct xive_vp vp = {};
+ uint32_t i;
+
+ for (i = 0; i < 1000; i++) {
+ struct xive_vp *vp_m = xive_get_vp(x, idx);
+
+ memset(vp_m, (~i) & 0xff, sizeof(*vp_m));
+ sync();
+ vp.w1 = (i << 16) | i;
+ xive_vpc_cache_update(x, blk, idx,
+ 0, 8, &vp, false, true);
+ if (!xive_check_vpc_update(x, idx, &vp)) {
+ xive_dbg(x, "Test failed at %d iterations\n", i);
+ return;
+ }
+ }
+ xive_dbg(x, "1000 iterations test success at %d/0x%x\n", blk, idx);
+}
+#else
+static inline void xive_special_cache_check(struct xive *x __unused,
+ uint32_t blk __unused,
+ uint32_t idx __unused)
+{
+}
+#endif
+
static void xive_setup_hw_for_emu(struct xive_cpu_state *xs)
{
struct xive_eq eq;
@@ -2897,58 +2988,18 @@ static void xive_setup_hw_for_emu(struct xive_cpu_state *xs)
xive_eqc_cache_update(x_eq, xs->eq_blk,
xs->eq_idx + XIVE_EMULATION_PRIO,
0, 4, &eq, false, true);
+ xive_check_eq_update(x_eq, xs->eq_idx + XIVE_EMULATION_PRIO, &eq);
+
+ /* Extra testing of cache watch & scrub facilities */
+ xive_special_cache_check(x_vp, xs->vp_blk, xs->vp_idx);
-#ifdef XIVE_DEBUG_INIT_CACHE_UPDATES
- if (1) {
- struct xive_eq *eq_p = xive_get_eq(x_eq,
- xs->eq_idx +
- XIVE_EMULATION_PRIO);
- struct xive_eq eq2;
-
- assert(eq_p);
- eq2 = *eq_p;
- if (memcmp(&eq, &eq2, sizeof(eq)) != 0) {
- xive_err(x_eq, "EQ update mismatch idx %d\n",
- xs->eq_idx);
- xive_err(x_eq, "want: %08x %08x %08x %08x\n",
- eq.w0, eq.w1, eq.w2, eq.w3);
- xive_err(x_eq, " %08x %08x %08x %08x\n",
- eq.w4, eq.w5, eq.w6, eq.w7);
- xive_err(x_eq, "got : %08x %08x %08x %08x\n",
- eq2.w0, eq2.w1, eq2.w2, eq2.w3);
- xive_err(x_eq, " %08x %08x %08x %08x\n",
- eq2.w4, eq2.w5, eq2.w6, eq2.w7);
- }
- }
-#endif
/* Initialize/enable the VP */
xive_init_default_vp(&vp, xs->eq_blk, xs->eq_idx);
/* Use the cache watch to write it out */
xive_vpc_cache_update(x_vp, xs->vp_blk, xs->vp_idx,
0, 8, &vp, false, true);
-
- /* Debug code */
-#ifdef XIVE_DEBUG_INIT_CACHE_UPDATES
- if (1) {
- struct xive_vp *vp_p = xive_get_vp(x_vp, xs->vp_idx);
- struct xive_vp vp2;
-
- assert(vp_p);
- vp2 = *vp_p;
- if (memcmp(&vp, &vp2, sizeof(vp)) != 0) {
- xive_err(x_vp, "VP update mismatch idx %d\n", xs->vp_idx);
- xive_err(x_vp, "want: %08x %08x %08x %08x\n",
- vp.w0, vp.w1, vp.w2, vp.w3);
- xive_err(x_vp, " %08x %08x %08x %08x\n",
- vp.w4, vp.w5, vp.w6, vp.w7);
- xive_err(x_vp, "got : %08x %08x %08x %08x\n",
- vp2.w0, vp2.w1, vp2.w2, vp2.w3);
- xive_err(x_vp, " %08x %08x %08x %08x\n",
- vp2.w4, vp2.w5, vp2.w6, vp2.w7);
- }
- }
-#endif
+ xive_check_vpc_update(x_vp, xs->vp_idx, &vp);
}
static void xive_init_cpu_emulation(struct xive_cpu_state *xs,
OpenPOWER on IntegriCloud