aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2016-12-22 14:16:54 +1100
committerStewart Smith <stewart@linux.vnet.ibm.com>2017-01-05 15:41:02 +1100
commit21be2a908c5c9cb39b797f13b17616744438f733 (patch)
tree2cec0a1bfbc53777c5b6d864f9d9a55cb56ff38a
parentd3c57a1d8acbfa7848e7be84dc35171613117383 (diff)
downloadskiboot-21be2a908c5c9cb39b797f13b17616744438f733.zip
skiboot-21be2a908c5c9cb39b797f13b17616744438f733.tar.gz
skiboot-21be2a908c5c9cb39b797f13b17616744438f733.tar.bz2
xive: Add opal_xive_get/set_vp_info
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Stewart Smith <stewart@linux.vnet.ibm.com>
-rw-r--r--hw/xive.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/hw/xive.c b/hw/xive.c
index 045ca2c..ccab081 100644
--- a/hw/xive.c
+++ b/hw/xive.c
@@ -1221,6 +1221,12 @@ static int64_t xive_ivc_scrub(struct xive *x, uint64_t block, uint64_t idx)
return __xive_cache_scrub(x, xive_cache_ivc, block, idx, false, false);
}
+static int64_t xive_vpc_scrub_clean(struct xive *x, uint64_t block, uint64_t idx)
+{
+ /* IVC has no "want_inval" bit, it always invalidates */
+ return __xive_cache_scrub(x, xive_cache_vpc, block, idx, true, false);
+}
+
static int64_t __xive_cache_watch(struct xive *x, enum xive_cache_type ctype,
uint64_t block, uint64_t idx,
uint32_t start_dword, uint32_t dword_count,
@@ -3389,6 +3395,95 @@ static int64_t opal_xive_donate_page(uint32_t chip_id, uint64_t addr)
return OPAL_SUCCESS;
}
+static int64_t opal_xive_get_vp_info(uint64_t vp_id,
+ uint64_t *out_flags,
+ uint64_t *out_cam_value,
+ uint64_t *out_report_cl_pair)
+{
+ struct xive *x;
+ struct xive_vp *vp;
+ uint32_t blk, idx;
+ bool group;
+
+ if (!xive_decode_vp(vp_id, &blk, &idx, NULL, &group))
+ return OPAL_PARAMETER;
+ /* We don't do groups yet */
+ if (group)
+ return OPAL_PARAMETER;
+ x = xive_from_pc_blk(blk);
+ if (!x)
+ return OPAL_PARAMETER;
+ vp = xive_get_vp(x, idx);
+ if (!vp)
+ return OPAL_PARAMETER;
+
+ if (out_flags) {
+ *out_flags = 0;
+ if (vp->w0 & VP_W0_VALID)
+ *out_flags |= OPAL_XIVE_VP_ENABLED;
+ }
+
+ if (out_cam_value)
+ *out_cam_value = (blk << 19) | idx;
+
+ if (out_report_cl_pair) {
+ *out_report_cl_pair = ((uint64_t)(vp->w6 & 0x0fffffff)) << 32;
+ *out_report_cl_pair |= vp->w7 & 0xffffff00;
+ }
+ return OPAL_SUCCESS;
+}
+
+static int64_t opal_xive_set_vp_info(uint64_t vp_id,
+ uint64_t flags,
+ uint64_t report_cl_pair)
+{
+ struct xive *x;
+ struct xive_vp *vp, vp_new;
+ uint32_t blk, idx;
+ bool group;
+ int64_t rc;
+
+ if (!xive_decode_vp(vp_id, &blk, &idx, NULL, &group))
+ return OPAL_PARAMETER;
+ /* We don't do groups yet */
+ if (group)
+ return OPAL_PARAMETER;
+ if (report_cl_pair & 0xff)
+ return OPAL_PARAMETER;
+ x = xive_from_pc_blk(blk);
+ if (!x)
+ return OPAL_PARAMETER;
+ vp = xive_get_vp(x, idx);
+ if (!vp)
+ return OPAL_PARAMETER;
+
+ vp_new = *vp;
+ if (flags & OPAL_XIVE_VP_ENABLED)
+ vp_new.w0 |= VP_W0_VALID;
+ else
+ vp_new.w0 &= ~VP_W0_VALID;
+
+ vp_new.w7 = report_cl_pair & 0xffffffff;
+ vp_new.w6 = report_cl_pair >> 32;
+
+ lock(&x->lock);
+ rc = xive_vpc_cache_update(x, blk, idx, 0, 8, &vp_new, false, false);
+ if (rc) {
+ unlock(&x->lock);
+ return rc;
+ }
+
+ /* When disabling, we scrub clean (invalidate the entry) so
+ * we can avoid cache ops in alloc/free
+ */
+ if (!(flags & OPAL_XIVE_VP_ENABLED))
+ xive_vpc_scrub_clean(x, blk, idx);
+
+ unlock(&x->lock);
+
+ return OPAL_SUCCESS;
+}
+
static void xive_cleanup_cpu_cam(struct cpu_thread *c)
{
struct xive_cpu_state *xs = c->xstate;
@@ -3843,5 +3938,7 @@ void init_xive(void)
opal_register(OPAL_XIVE_FREE_IRQ, opal_xive_free_irq, 1);
opal_register(OPAL_XIVE_ALLOCATE_VP_BLOCK, opal_xive_alloc_vp_block, 1);
opal_register(OPAL_XIVE_FREE_VP_BLOCK, opal_xive_free_vp_block, 1);
+ opal_register(OPAL_XIVE_GET_VP_INFO, opal_xive_get_vp_info, 4);
+ opal_register(OPAL_XIVE_SET_VP_INFO, opal_xive_set_vp_info, 3);
}