diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2011-12-19 00:34:12 +0000 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2011-12-19 00:37:43 +0000 |
commit | ae32aaf4b20dafef138dc9c28dbddbfe49f24b83 (patch) | |
tree | 8c57160aef5d89c8164a166b5394883535a00888 | |
parent | e32ad646762ccc7f22f938454e222d43abfb38ed (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.c | 17 | ||||
-rw-r--r-- | src/sna/gen3_render.c | 17 | ||||
-rw-r--r-- | src/sna/kgem.h | 9 | ||||
-rw-r--r-- | src/sna/sna_render_inline.h | 2 |
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; } |