@@ -45,6 +45,44 @@ render_state_get_rodata(struct drm_device *dev, const int gen)
return NULL;
}
+/**
+ * Alternate batch buffer end offsets defined in intel_renderstate_genx.c
+ * are locations in the golden context batch buffer where MI_BATCH_BUFFER_END
+ * commands can be optionally inserted. BB end commands can be added to
+ * terminate the GC BB early and thus customize the BB for product variations
+ * in a given GEN family.
+ */
+static int insert_alternate_bbend(struct drm_device *dev,
+ const struct intel_renderstate_rodata *rodata,
+ u32 *d)
+{
+ int index = -1; /* Default to no alternate bbend index */
+
+ /* For GEN9, exit golden context BB before executing all commands */
+ if (IS_GEN9(dev))
+ index = 0;
+
+ /* Write MI_BATCH_BUFFER_END at valid location */
+ if (index >= 0) {
+ if (index < rodata->alternate_bbend_items) {
+ int bbend_offset;
+
+ bbend_offset = rodata->alternate_bbend_offsets[index];
+
+ /* Check for DWORD aligned address, et al */
+ if ((bbend_offset <= 0) ||
+ (bbend_offset > PAGE_SIZE - sizeof(u32)) ||
+ ((bbend_offset & (sizeof(u32) - 1)) != 0))
+ return -EINVAL;
+
+ d[bbend_offset/sizeof(u32)] = MI_BATCH_BUFFER_END;
+ } else
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int render_state_init(struct render_state *so, struct drm_device *dev)
{
int ret;
@@ -73,7 +111,7 @@ free_gem:
return ret;
}
-static int render_state_setup(struct render_state *so)
+static int render_state_setup(struct render_state *so, struct drm_device *dev)
{
const struct intel_renderstate_rodata *rodata = so->rodata;
unsigned int i = 0, reloc_index = 0;
@@ -89,10 +127,11 @@ static int render_state_setup(struct render_state *so)
d = kmap(page);
while (i < rodata->batch_items) {
- u32 s = rodata->batch[i];
+ u32 s = rodata->batch[i]; /* DWORD from R/O batch */
if (i * 4 == rodata->reloc[reloc_index]) {
- u64 r = s + so->ggtt_offset;
+ u64 r = s + /* Object offset stored in reloc DWORD */
+ so->ggtt_offset; /* Batch buffer gfx offset */
s = lower_32_bits(r);
if (so->gen >= 8) {
if (i + 1 >= rodata->batch_items ||
@@ -108,8 +147,20 @@ static int render_state_setup(struct render_state *so)
d[i++] = s;
}
+
+ /* Any alternate BB end entries? */
+ if (rodata->alternate_bbend_offsets[0] != -1)
+ ret = insert_alternate_bbend(dev, rodata, d);
+ else
+ ret = 0;
+
kunmap(page);
+ if (ret) {
+ DRM_ERROR("invalid alternate batch buffer end\n");
+ return ret;
+ }
+
ret = i915_gem_object_set_to_gtt_domain(so->obj, false);
if (ret)
return ret;
@@ -143,7 +194,7 @@ int i915_gem_render_state_prepare(struct intel_engine_cs *ring,
if (so->rodata == NULL)
return 0;
- ret = render_state_setup(so);
+ ret = render_state_setup(so, ring->dev);
if (ret) {
i915_gem_render_state_fini(so);
return ret;
@@ -28,6 +28,8 @@
struct intel_renderstate_rodata {
const u32 *reloc;
+ const u32 *alternate_bbend_offsets;
+ const u32 alternate_bbend_items;
const u32 *batch;
const u32 batch_items;
};
@@ -31,11 +31,17 @@ extern const struct intel_renderstate_rodata gen7_null_state;
extern const struct intel_renderstate_rodata gen8_null_state;
extern const struct intel_renderstate_rodata gen9_null_state;
-#define RO_RENDERSTATE(_g) \
+#define RO_RENDERSTATE(_g) \
const struct intel_renderstate_rodata gen ## _g ## _null_state = { \
- .reloc = gen ## _g ## _null_state_relocs, \
- .batch = gen ## _g ## _null_state_batch, \
- .batch_items = sizeof(gen ## _g ## _null_state_batch)/4, \
+ .reloc = gen ## _g ## _null_state_relocs, \
+ .alternate_bbend_offsets = \
+ gen ## _g ## _alternate_bbend_offsets, \
+ .alternate_bbend_items = \
+ sizeof(gen ## _g ## _alternate_bbend_offsets) / \
+ sizeof(u32), \
+ .batch = gen ## _g ## _null_state_batch, \
+ .batch_items = sizeof(gen ## _g ## _null_state_batch) / \
+ sizeof(u32) \
}
#endif /* INTEL_RENDERSTATE_H */
@@ -29,7 +29,11 @@ static const u32 gen6_null_state_relocs[] = {
0x0000002c,
0x000001e0,
0x000001e4,
- -1,
+ -1
+};
+
+static const u32 gen6_alternate_bbend_offsets[] = {
+ -1
};
static const u32 gen6_null_state_batch[] = {
@@ -28,7 +28,11 @@ static const u32 gen7_null_state_relocs[] = {
0x00000010,
0x00000018,
0x000001ec,
- -1,
+ -1
+};
+
+static const u32 gen7_alternate_bbend_offsets[] = {
+ -1
};
static const u32 gen7_null_state_batch[] = {
@@ -31,6 +31,10 @@ static const u32 gen8_null_state_relocs[] = {
-1,
};
+static const u32 gen8_alternate_bbend_offsets[] = {
+ -1
+};
+
static const u32 gen8_null_state_batch[] = {
0x7a000004,
0x01000000,
@@ -31,6 +31,11 @@ static const u32 gen9_null_state_relocs[] = {
-1,
};
+static const u32 gen9_alternate_bbend_offsets[] = {
+ 0x00000dac,
+ -1
+};
+
static const u32 gen9_null_state_batch[] = {
0x7a000004,
0x01000000,
@@ -867,9 +872,9 @@ static const u32 gen9_null_state_batch[] = {
0x00000000,
0x680b0001,
0x780e0000,
- 0x00000dc1,
- 0x78240000,
0x00000e01,
+ 0x78240000,
+ 0x00000e41,
0x784f0000,
0x80000100,
0x784d0000,
@@ -887,9 +892,9 @@ static const u32 gen9_null_state_batch[] = {
0x780f0000,
0x00000000,
0x78230000,
- 0x00000e60,
+ 0x00000ea0,
0x78210000,
- 0x00000e80,
+ 0x00000ec0,
0x78260000,
0x00000000,
0x78270000,
@@ -907,11 +912,27 @@ static const u32 gen9_null_state_batch[] = {
0x00000001,
0x00000000,
0x00000000,
+ 0x00000000, /* alternate bbend */
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
0x05000000, /* cmds end */
0x00000000,
0x00000000,
0x00000000,
0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
0x00000000, /* state start */
0x00000000,
0x3f800000,