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>
This commit is contained in:
Chris Wilson 2011-12-19 00:34:12 +00:00
parent e32ad64676
commit ae32aaf4b2
4 changed files with 34 additions and 11 deletions

View File

@ -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);

View File

@ -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);

View File

@ -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,

View File

@ -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;
}