[Intel-gfx] [PATCH 1/6] drm/i915: Implement L3 partitioning set-up from the workaround list.

Francisco Jerez currojerez at riseup.net
Wed Oct 7 04:44:00 PDT 2015


This programs the L3 configuration based on the sizes given for each
partition as arguments.  The relevant register writes are added to the
workaround list so that they are re-applied to each context while it's
initialized, preventing state leaks from other userspace processes
which may have modified the L3 partitioning from its boot-up state,
since all relevant registers are part of the software and hardware
command checker whitelists.

Some userspace clients (DDX and current versions of Mesa not patched
with my L3 partitioning series [1]) assume that the L3 configuration,
in particular the URB size, comes up in certain state when a context
is created, but nothing in the kernel guarantees this assumption, the
registers that control the partitioning of the L3 cache were being
left untouched.

Note that the VLV_L3SQCREG1_SQGHPCI_DEFAULT macro defined here has the
same value as the previously defined VLV_B0_WA_L3SQCREG1_VALUE, but
the latter will be removed in a future commit.

[1] http://lists.freedesktop.org/archives/mesa-dev/2015-September/093550.html

Signed-off-by: Francisco Jerez <currojerez at riseup.net>
---
 drivers/gpu/drm/i915/i915_reg.h         | 13 ++++++
 drivers/gpu/drm/i915/intel_ringbuffer.c | 80 +++++++++++++++++++++++++++++++++
 2 files changed, 93 insertions(+)

diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index a7c9e8c..663bc8f 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -5920,11 +5920,21 @@ enum skl_disp_power_wells {
 # define CHV_HZ_8X8_MODE_IN_1X				(1<<15)
 # define BDW_HIZ_POWER_COMPILER_CLOCK_GATING_DISABLE	(1<<3)
 
+#define GEN8_L3CNTLREG				0x7034
+#define  GEN8_L3CNTLREG_URB_ALLOC(n)		((n) << 1)
+#define  GEN8_L3CNTLREG_RO_ALLOC(n)		((n) << 11)
+#define  GEN8_L3CNTLREG_DC_ALLOC(n)		((n) << 18)
+#define  GEN8_L3CNTLREG_ALL_ALLOC(n)		((n) << 25)
+
 #define GEN9_SLICE_COMMON_ECO_CHICKEN0		0x7308
 #define  DISABLE_PIXEL_MASK_CAMMING		(1<<14)
 
 #define GEN7_L3SQCREG1				0xB010
 #define  VLV_B0_WA_L3SQCREG1_VALUE		0x00D30000
+#define  IVB_L3SQCREG1_SQGHPCI_DEFAULT		0x00730000
+#define  VLV_L3SQCREG1_SQGHPCI_DEFAULT		0x00D30000
+#define  HSW_L3SQCREG1_SQGHPCI_DEFAULT		0x00610000
+#define  GEN7_L3SQCREG1_CONV_DC_UC		(1 << 24)
 
 #define GEN8_L3SQCREG1				0xB100
 #define  BDW_WA_L3SQCREG1_DEFAULT		0x784000
@@ -5933,6 +5943,9 @@ enum skl_disp_power_wells {
 #define  GEN7_WA_FOR_GEN7_L3_CONTROL			0x3C47FF8C
 #define  GEN7_L3AGDIS				(1<<19)
 #define GEN7_L3CNTLREG2				0xB020
+#define  GEN7_L3CNTLREG2_URB_ALLOC(n)		((n) << 1)
+#define  GEN7_L3CNTLREG2_RO_ALLOC(n)		((n) << 14)
+#define  GEN7_L3CNTLREG2_DC_ALLOC(n)		((n) << 21)
 #define GEN7_L3CNTLREG3				0xB024
 
 #define GEN7_L3_CHICKEN_MODE_REGISTER		0xB030
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 9035f8c..54ca344 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -800,6 +800,86 @@ static int wa_add(struct drm_i915_private *dev_priv,
 
 #define WA_WRITE(addr, val) WA_REG(addr, 0xffffffff, val)
 
+/**
+ * init_l3_partitioning_workarounds - Add L3 partitioning set-up to the WA list.
+ *
+ * @ring - Ring to program the L3 partitioning for.
+ * @n_urb - Number of ways to allocate for the URB.
+ * @n_ro - Number of ways to allocate for read-only L3 clients.
+ * @n_dc - Number of ways to allocate for the DC read-write L3 client.
+ * @n_all - Number of ways to allocate for the common pool shared
+ *          among all L3 clients.
+ *
+ * Note that for this to work correctly the L3 cache must be
+ * completely flushed whenever the workaround list is applied to a
+ * context.
+ */
+static int init_l3_partitioning_workarounds(struct intel_engine_cs *ring,
+					    unsigned int n_urb,
+					    unsigned int n_ro,
+					    unsigned int n_dc,
+					    unsigned int n_all)
+{
+	struct drm_device *dev = ring->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+
+	if (INTEL_INFO(dev)->gen >= 8) {
+		/*
+		 * The ALL partition may not be used simultaneously
+		 * with RO and DC.
+		 */
+		BUG_ON(n_all && (n_ro || n_dc));
+
+		/* Just need to set up the L3 partitioning. */
+		WA_WRITE(GEN8_L3CNTLREG,
+			 GEN8_L3CNTLREG_URB_ALLOC(n_urb) |
+			 GEN8_L3CNTLREG_RO_ALLOC(n_ro) |
+			 GEN8_L3CNTLREG_DC_ALLOC(n_dc) |
+			 GEN8_L3CNTLREG_ALL_ALLOC(n_all));
+
+	} else if (INTEL_INFO(dev)->gen >= 7) {
+		/*
+		 * Offset applied by the hardware to the number of
+		 * ways allocated to the URB, which is also the
+		 * minimum legal URB allocation.
+		 */
+		const unsigned int n0_urb = (IS_VALLEYVIEW(dev) ? 32 : 0);
+		BUG_ON(n_urb < n0_urb);
+
+		/* The ALL partition is not supported on Gen7. */
+		BUG_ON(n_all);
+
+		/*
+		 * Init the L3SQ General and high priority credit
+		 * initialization value to the hardware defaults
+		 * (except for VLV B0 which supposedly defaults to a
+		 * value different to the one we set here), and demote
+		 * the DC to LLC if it has no ways assigned.
+		 *
+		 * WaIncreaseL3CreditsForVLVB0:vlv
+		 */
+		WA_WRITE(GEN7_L3SQCREG1,
+			 (IS_HASWELL(dev) ? HSW_L3SQCREG1_SQGHPCI_DEFAULT :
+			  IS_VALLEYVIEW(dev) ? VLV_L3SQCREG1_SQGHPCI_DEFAULT :
+			  IVB_L3SQCREG1_SQGHPCI_DEFAULT) |
+			 (n_dc ? 0 : GEN7_L3SQCREG1_CONV_DC_UC));
+
+		/* Set up the L3 partitioning. */
+		WA_WRITE(GEN7_L3CNTLREG2,
+			 GEN7_L3CNTLREG2_URB_ALLOC(n_urb - n0_urb) |
+			 GEN7_L3CNTLREG2_RO_ALLOC(n_ro) |
+			 GEN7_L3CNTLREG2_DC_ALLOC(n_dc));
+
+		WA_WRITE(GEN7_L3CNTLREG3, 0);
+
+	} else {
+		/* No L3 on pre-Gen7 hardware. */
+		BUG();
+	}
+
+	return 0;
+}
+
 static int gen8_init_workarounds(struct intel_engine_cs *ring)
 {
 	struct drm_device *dev = ring->dev;
-- 
2.5.1



More information about the Intel-gfx mailing list