summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-12-19 00:34:12 +0000
committerChris Wilson <chris@chris-wilson.co.uk>2011-12-19 00:37:43 +0000
commitae32aaf4b20dafef138dc9c28dbddbfe49f24b83 (patch)
tree8c57160aef5d89c8164a166b5394883535a00888
parente32ad646762ccc7f22f938454e222d43abfb38ed (diff)
sna/gen[23]: We need to check the batch before doing an inline flush
A missing check before emitting a dword into the batch opened up the possibility of overflowing the batch and corrupting our state. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--src/sna/gen2_render.c17
-rw-r--r--src/sna/gen3_render.c17
-rw-r--r--src/sna/kgem.h9
-rw-r--r--src/sna/sna_render_inline.h2
4 files changed, 34 insertions, 11 deletions
diff --git a/src/sna/gen2_render.c b/src/sna/gen2_render.c
index c8d093b2..373866b9 100644
--- a/src/sna/gen2_render.c
+++ b/src/sna/gen2_render.c
@@ -499,14 +499,22 @@ static void gen2_emit_invariant(struct sna *sna)
sna->render_state.gen2.need_invariant = FALSE;
}
+static bool
+gen2_check_batch(struct sna *sna)
+{
+ return (kgem_check_batch(&sna->kgem, 30+40) &&
+ kgem_check_reloc(&sna->kgem, 3) &&
+ kgem_check_exec(&sna->kgem, 3));
+}
+
static void
gen2_get_batch(struct sna *sna)
{
kgem_set_mode(&sna->kgem, KGEM_RENDER);
- if (!kgem_check_batch(&sna->kgem, 28+40)) {
+ if (!kgem_check_batch(&sna->kgem, 30+40)) {
DBG(("%s: flushing batch: size %d > %d\n",
- __FUNCTION__, 28+40,
+ __FUNCTION__, 30+40,
sna->kgem.surface-sna->kgem.nbatch));
kgem_submit(&sna->kgem);
}
@@ -1537,12 +1545,13 @@ gen2_render_composite(struct sna *sna,
if (kgem_bo_is_dirty(tmp->src.bo) || kgem_bo_is_dirty(tmp->mask.bo)) {
if (tmp->src.bo == tmp->dst.bo || tmp->mask.bo == tmp->dst.bo) {
kgem_emit_flush(&sna->kgem);
- } else {
+ } else if (gen2_check_batch(sna)) {
BATCH(_3DSTATE_MODES_5_CMD |
PIPELINE_FLUSH_RENDER_CACHE |
PIPELINE_FLUSH_TEXTURE_CACHE);
kgem_clear_dirty(&sna->kgem);
- }
+ } else
+ kgem_submit(&sna->kgem);
}
gen2_emit_composite_state(sna, tmp);
diff --git a/src/sna/gen3_render.c b/src/sna/gen3_render.c
index 96c0d9b1..fe3a359c 100644
--- a/src/sna/gen3_render.c
+++ b/src/sna/gen3_render.c
@@ -1198,11 +1198,19 @@ static void gen3_emit_invariant(struct sna *sna)
sna->render_state.gen3.need_invariant = FALSE;
}
+#define MAX_OBJECTS 3 /* worst case: dst + src + mask */
+
+static bool
+gen3_check_batch(struct sna *sna)
+{
+ return (kgem_check_batch(&sna->kgem, 200) &&
+ kgem_check_reloc(&sna->kgem, MAX_OBJECTS) &&
+ kgem_check_exec(&sna->kgem, MAX_OBJECTS));
+}
+
static void
gen3_get_batch(struct sna *sna)
{
-#define MAX_OBJECTS 3 /* worst case: dst + src + mask */
-
kgem_set_mode(&sna->kgem, KGEM_RENDER);
if (!kgem_check_batch(&sna->kgem, 200)) {
@@ -2619,12 +2627,13 @@ gen3_render_composite(struct sna *sna,
if (kgem_bo_is_dirty(tmp->src.bo) || kgem_bo_is_dirty(tmp->mask.bo)) {
if (tmp->src.bo == tmp->dst.bo || tmp->mask.bo == tmp->dst.bo) {
kgem_emit_flush(&sna->kgem);
- } else {
+ } else if (gen3_check_batch(sna)) {
OUT_BATCH(_3DSTATE_MODES_5_CMD |
PIPELINE_FLUSH_RENDER_CACHE |
PIPELINE_FLUSH_TEXTURE_CACHE);
kgem_clear_dirty(&sna->kgem);
- }
+ } else
+ kgem_submit(&sna->kgem);
}
gen3_emit_composite_state(sna, tmp);
diff --git a/src/sna/kgem.h b/src/sna/kgem.h
index 4e30d58b..efc4e807 100644
--- a/src/sna/kgem.h
+++ b/src/sna/kgem.h
@@ -277,9 +277,14 @@ static inline bool kgem_check_batch(struct kgem *kgem, int num_dwords)
return likely(kgem->nbatch + num_dwords + KGEM_BATCH_RESERVED <= kgem->surface);
}
-static inline bool kgem_check_reloc(struct kgem *kgem, int num_reloc)
+static inline bool kgem_check_reloc(struct kgem *kgem, int n)
{
- return likely(kgem->nreloc + num_reloc <= KGEM_RELOC_SIZE(kgem));
+ return likely(kgem->nreloc + n <= KGEM_RELOC_SIZE(kgem));
+}
+
+static inline bool kgem_check_exec(struct kgem *kgem, int n)
+{
+ return likely(kgem->nexec + n <= KGEM_EXEC_SIZE(kgem));
}
static inline bool kgem_check_batch_with_surfaces(struct kgem *kgem,
diff --git a/src/sna/sna_render_inline.h b/src/sna/sna_render_inline.h
index daa8f6fe..758833ed 100644
--- a/src/sna/sna_render_inline.h
+++ b/src/sna/sna_render_inline.h
@@ -52,7 +52,7 @@ static inline int batch_space(struct sna *sna)
static inline void batch_emit(struct sna *sna, uint32_t dword)
{
- assert(sna->kgem.nbatch < sna->kgem.surface);
+ assert(sna->kgem.nbatch + KGEM_BATCH_RESERVED < sna->kgem.surface);
sna->kgem.batch[sna->kgem.nbatch++] = dword;
}