[Skiboot] [PATCH 43/61] xive/p10: Add automatic Context Save and Restore support

Vasant Hegde hegdevasant at linux.vnet.ibm.com
Mon Jul 19 23:19:54 AEST 2021


From: Cédric Le Goater <clg at kaod.org>

The save-restore feature is forced when available. It would have been
better to introduce some negotiation but the CAM line value is
returned by get_vp_info() before the save-restore feature can be
enabled by KVM in xive_native_enable_vp().

This is compatible with the current KVM implementation for P9.

Signed-off-by: Cédric Le Goater <clg at kaod.org>
Signed-off-by: Vasant Hegde <hegdevasant at linux.vnet.ibm.com>
---
 hw/xive2.c           | 48 ++++++++++++++++++++++++++++++++++++++++++++
 include/opal-api.h   |  1 +
 include/xive2-regs.h |  8 +++++++-
 3 files changed, 56 insertions(+), 1 deletion(-)

diff --git a/hw/xive2.c b/hw/xive2.c
index 4b97dae74..05cb325bb 100644
--- a/hw/xive2.c
+++ b/hw/xive2.c
@@ -1517,6 +1517,7 @@ static const struct {
 	{ CQ_XIVE_CAP_PHB_ABT, "PHB address based trigger mode support" },
 	{ CQ_XIVE_CAP_EXPLOITATION_MODE, "Exploitation mode" },
 	{ CQ_XIVE_CAP_STORE_EOI, "StoreEOI mode support" },
+	{ CQ_XIVE_CAP_VP_SAVE_RESTORE, "VP Context Save and Restore" },
 };
 
 static void xive_dump_capabilities(struct xive *x, uint64_t cap_val)
@@ -1548,6 +1549,8 @@ static const struct {
 	{ CQ_XIVE_CFG_GEN1_TIMA_HYP_BLK0, "Gen1 mode TIMA General Hypervisor Block0" },
 	{ CQ_XIVE_CFG_GEN1_TIMA_CROWD_DIS, "Gen1 mode TIMA Crowd disable" },
 	{ CQ_XIVE_CFG_GEN1_END_ESX, "Gen1 mode END ESx" },
+	{ CQ_XIVE_CFG_EN_VP_SAVE_RESTORE, "VP Context Save and Restore" },
+	{ CQ_XIVE_CFG_EN_VP_SAVE_REST_STRICT, "VP Context Save and Restore strict" },
 };
 
 static void xive_dump_configuration(struct xive *x, const char *prefix,
@@ -1599,6 +1602,11 @@ static bool xive_has_cap(struct xive *x, uint64_t cap)
 
 #define XIVE_CAN_STORE_EOI(x) xive_has_cap(x, CQ_XIVE_CAP_STORE_EOI)
 
+static bool xive_cfg_save_restore(struct xive *x)
+{
+	return !!(x->config & CQ_XIVE_CFG_EN_VP_SAVE_RESTORE);
+}
+
 static void xive_config_fused_core(struct xive *x)
 {
 	uint64_t val = xive_regr(x, TCTXT_CFG);
@@ -1659,6 +1667,14 @@ static bool xive_config_init(struct xive *x)
 	x->config |= CQ_XIVE_CFG_HYP_HARD_BLKID_OVERRIDE |
 		SETFIELD(CQ_XIVE_CFG_HYP_HARD_BLOCK_ID, 0ull, x->block_id);
 
+	/*
+	 * Enable "VP Context Save and Restore" by default. it is
+	 * compatible with KVM which currently does the context
+	 * save&restore in the entry/exit path of the vCPU
+	 */
+	if (x->capabilities & CQ_XIVE_CAP_VP_SAVE_RESTORE)
+		x->config |= CQ_XIVE_CFG_EN_VP_SAVE_RESTORE;
+
 	xive_dump_configuration(x, "new", x->config);
 	xive_regw(x, CQ_XIVE_CFG, x->config);
 	if (xive_regr(x, CQ_XIVE_CFG) != x->config) {
@@ -1908,6 +1924,9 @@ static void xive_create_mmio_dt_node(struct xive *x)
 	if (XIVE_CAN_STORE_EOI(x))
 		dt_add_property(xive_dt_node, "store-eoi-support", NULL, 0);
 
+	if (xive_cfg_save_restore(x))
+		dt_add_property(xive_dt_node, "vp-save-restore", NULL, 0);
+
 	xive_add_provisioning_properties();
 
 }
@@ -3501,6 +3520,8 @@ static int64_t opal_xive_get_vp_info(uint64_t vp_id,
 			return OPAL_PARAMETER;
 		if (xive_get_field32(NVP_W0_VALID, vp->w0))
 			*out_flags |= cpu_to_be64(OPAL_XIVE_VP_ENABLED);
+		if (xive_cfg_save_restore(x))
+			*out_flags |= cpu_to_be64(OPAL_XIVE_VP_SAVE_RESTORE);
 		if (xive_get_field32(END_W0_SILENT_ESCALATE, end->w0))
 			*out_flags |= cpu_to_be64(OPAL_XIVE_VP_SINGLE_ESCALATION);
 	}
@@ -3510,6 +3531,13 @@ static int64_t opal_xive_get_vp_info(uint64_t vp_id,
 
 		cam_value = (blk << x->vp_shift) | idx;
 
+		/*
+		 * If save-restore is enabled, force the CAM line
+		 * value with the H bit.
+		 */
+		if (xive_cfg_save_restore(x))
+			cam_value |= TM10_QW1W2_HO;
+
 		*out_cam_value = cpu_to_be64(cam_value);
 	}
 
@@ -3657,6 +3685,10 @@ static int64_t opal_xive_set_vp_info(uint64_t vp_id,
 	if (!vp)
 		return OPAL_PARAMETER;
 
+	/* Consistency check. */
+	if ((flags & OPAL_XIVE_VP_SAVE_RESTORE) && !xive_cfg_save_restore(x))
+		return OPAL_PARAMETER;
+
 	lock(&x->lock);
 
 	vp_new = *vp;
@@ -3669,6 +3701,22 @@ static int64_t opal_xive_set_vp_info(uint64_t vp_id,
 			rc = xive_setup_silent_gather(vp_id, true);
 		else
 			rc = xive_setup_silent_gather(vp_id, false);
+
+		/*
+		 * Prepare NVP to be HW owned for automatic save-restore
+		 */
+		if (xive_cfg_save_restore(x)) {
+			/*
+			 * Set NVP privilege level. Default to OS.
+			 * This check only makes sense for KVM guests
+			 * currently. We would need an extra flag to
+			 * distinguish from pool level.
+			 */
+			vp_new.w0 = xive_set_field32(NVP_W0_VPRIV, vp_new.w0, 0);
+
+			vp_new.w2 = xive_set_field32(NVP_W2_CPPR, vp_new.w2, 0xFF);
+			vp_new.w0 = xive_set_field32(NVP_W0_HW, vp_new.w0, 1);
+		}
 	} else {
 		/*
 		 * TODO (kvm): disabling a VP invalidates the associated ENDs.
diff --git a/include/opal-api.h b/include/opal-api.h
index eb6d83527..d7b301a30 100644
--- a/include/opal-api.h
+++ b/include/opal-api.h
@@ -1177,6 +1177,7 @@ enum {
 enum {
 	OPAL_XIVE_VP_ENABLED		= 0x00000001,
 	OPAL_XIVE_VP_SINGLE_ESCALATION	= 0x00000002,
+	OPAL_XIVE_VP_SAVE_RESTORE	= 0x00000004,
 };
 
 /* "Any chip" replacement for chip ID for allocation functions */
diff --git a/include/xive2-regs.h b/include/xive2-regs.h
index 6295dd191..ad1a9b79f 100644
--- a/include/xive2-regs.h
+++ b/include/xive2-regs.h
@@ -31,7 +31,7 @@
 #define       CQ_XIVE_CAP_VP_INT_PRIO_4_8       2
 #define       CQ_XIVE_CAP_VP_INT_PRIO_8         3
 #define    CQ_XIVE_CAP_BLOCK_ID_WIDTH           PPC_BITMASK(12,13)
-
+#define    CQ_XIVE_CAP_VP_SAVE_RESTORE          PPC_BIT(38)
 #define    CQ_XIVE_CAP_PHB_PQ_DISABLE           PPC_BIT(56)
 #define    CQ_XIVE_CAP_PHB_ABT                  PPC_BIT(57)
 #define    CQ_XIVE_CAP_EXPLOITATION_MODE        PPC_BIT(58)
@@ -68,6 +68,10 @@
 #define    CQ_XIVE_CFG_GEN1_TIMA_CROWD_DIS      PPC_BIT(27) /* 0 if bit[25]=0 */
 #define    CQ_XIVE_CFG_GEN1_END_ESX             PPC_BIT(28) /* END ESx stores
                                                                are dropped */
+#define    CQ_XIVE_CFG_EN_VP_SAVE_RESTORE       PPC_BIT(38) /* 0 if bit[25]=1 */
+#define    CQ_XIVE_CFG_EN_VP_SAVE_REST_STRICT   PPC_BIT(39) /* 0 if bit[25]=1 */
+
+#define    CQ_XIVE_CFG_EN_VP_SAVE_RESTORE       PPC_BIT(38) /* 0 if bit[25]=1 */
 
 /* Interrupt Controller Base Address Register - 512 pages (32M) */
 #define X_CQ_IC_BAR				0x08
@@ -508,6 +512,8 @@ struct xive_end {
 struct xive_nvp {
 	beint32_t	w0;
 #define NVP_W0_VALID			PPC_BIT32(0)
+#define NVP_W0_HW			PPC_BIT32(7)
+#define NVP_W0_VPRIV			PPC_BITMASK32(14,15)
 #define NVP_W0_ESC_END			PPC_BIT32(25)	/* 'N' bit 0:ESB  1:END */
 	beint32_t	w1;
 	beint32_t	w2;
-- 
2.31.1



More information about the Skiboot mailing list