diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2014-09-08 12:41:06 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2014-09-08 12:50:29 +0100 |
commit | 30932a7b9d255c2037bee19e01aa3edc37b07386 (patch) | |
tree | c12036797c0dedd3aaea795a073df88cda137406 | |
parent | 692c14d405bb352697b67f36a034d4963e272b66 (diff) |
sna: Avoid u16 underflow when computing reserved batch space
If we filled the batch exactly, then subtract -1 for the reserved
BATCH_BUFFER_END, it would underflow to a large value - convincing us
that we had sufficient room to stuff many, many more commands in.
However, all the callsites should be guarded by checking already that
they had sufficient space to emit at least one operation...
References: https://bugs.freedesktop.org/show_bug.cgi?id=77074
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r-- | src/sna/kgem.h | 7 | ||||
-rw-r--r-- | src/sna/sna_accel.c | 14 | ||||
-rw-r--r-- | src/sna/sna_blt.c | 92 | ||||
-rw-r--r-- | src/sna/sna_io.c | 41 |
4 files changed, 91 insertions, 63 deletions
diff --git a/src/sna/kgem.h b/src/sna/kgem.h index c3a9b13d..8bd57156 100644 --- a/src/sna/kgem.h +++ b/src/sna/kgem.h @@ -428,6 +428,13 @@ static inline void _kgem_set_mode(struct kgem *kgem, enum kgem_mode mode) kgem->mode = mode; } +static inline int kgem_batch_space(struct kgem *kgem) +{ + int rem = kgem->surface - kgem->nbatch; + assert(rem > 0); + return rem - KGEM_BATCH_RESERVED; +} + static inline bool kgem_check_batch(struct kgem *kgem, int num_dwords) { assert(num_dwords > 0); diff --git a/src/sna/sna_accel.c b/src/sna/sna_accel.c index 7df522bd..ab2908f5 100644 --- a/src/sna/sna_accel.c +++ b/src/sna/sna_accel.c @@ -12156,7 +12156,7 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable, sna->kgem.nbatch += 6; } } else do { - int n_this_time; + int n_this_time, rem; assert(sna->kgem.mode == KGEM_BLT); b = sna->kgem.batch + sna->kgem.nbatch; @@ -12199,8 +12199,9 @@ sna_poly_fill_rect_tiled_8x8_blt(DrawablePtr drawable, } n_this_time = n; - if (3*n_this_time > sna->kgem.surface - sna->kgem.nbatch - KGEM_BATCH_RESERVED) - n_this_time = (sna->kgem.surface - sna->kgem.nbatch - KGEM_BATCH_RESERVED) / 3; + rem = kgem_batch_space(&sna->kgem); + if (3*n_this_time > rem) + n_this_time = rem / 3; assert(n_this_time); n -= n_this_time; @@ -13061,7 +13062,7 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable, sna->kgem.nbatch += 9; } } else do { - int n_this_time; + int n_this_time, rem; assert(sna->kgem.mode == KGEM_BLT); b = sna->kgem.batch + sna->kgem.nbatch; @@ -13099,8 +13100,9 @@ sna_poly_fill_rect_stippled_8x8_blt(DrawablePtr drawable, } n_this_time = n; - if (3*n_this_time > sna->kgem.surface - sna->kgem.nbatch - KGEM_BATCH_RESERVED) - n_this_time = (sna->kgem.surface - sna->kgem.nbatch - KGEM_BATCH_RESERVED) / 3; + rem = kgem_batch_space(&sna->kgem); + if (3*n_this_time > rem) + n_this_time = rem / 3; assert(n_this_time); n -= n_this_time; diff --git a/src/sna/sna_blt.c b/src/sna/sna_blt.c index 4538f98f..25b6ef55 100644 --- a/src/sna/sna_blt.c +++ b/src/sna/sna_blt.c @@ -232,6 +232,7 @@ static bool sna_blt_fill_init(struct sna *sna, sna->blt_state.fill_alu = alu; } + assert(sna->kgem.mode == KGEM_BLT); return true; } @@ -1102,12 +1103,13 @@ inline static void _sna_blt_fill_boxes(struct sna *sna, do { uint32_t *b = kgem->batch + kgem->nbatch; - int nbox_this_time; + int nbox_this_time, rem; assert(sna->kgem.mode == KGEM_BLT); nbox_this_time = nbox; - if (3*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 3; + rem = kgem_batch_space(kgem); + if (3*nbox_this_time > rem) + nbox_this_time = rem / 3; assert(nbox_this_time); nbox -= nbox_this_time; @@ -1198,12 +1200,13 @@ static void blt_composite_fill_boxes_no_offset__thread(struct sna *sna, do { uint32_t *b = kgem->batch + kgem->nbatch; - int nbox_this_time; + int nbox_this_time, rem; assert(sna->kgem.mode == KGEM_BLT); nbox_this_time = nbox; - if (3*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 3; + rem = kgem_batch_space(kgem); + if (3*nbox_this_time > rem) + nbox_this_time = rem / 3; assert(nbox_this_time); nbox -= nbox_this_time; @@ -1310,12 +1313,13 @@ static void blt_composite_fill_boxes__thread(struct sna *sna, do { uint32_t *b = kgem->batch + kgem->nbatch; - int nbox_this_time; + int nbox_this_time, rem; assert(sna->kgem.mode == KGEM_BLT); nbox_this_time = nbox; - if (3*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 3; + rem = kgem_batch_space(kgem); + if (3*nbox_this_time > rem) + nbox_this_time = rem / 3; assert(nbox_this_time); nbox -= nbox_this_time; @@ -1386,6 +1390,7 @@ static bool begin_blt(struct sna *sna, struct sna_composite_op *op) { + assert(sna->kgem.mode == KGEM_BLT); if (!kgem_check_bo_fenced(&sna->kgem, op->dst.bo)) { kgem_submit(&sna->kgem); if (!kgem_check_bo_fenced(&sna->kgem, op->dst.bo)) @@ -1603,11 +1608,12 @@ static void blt_composite_copy_boxes__thread(struct sna *sna, if ((dst_dx | dst_dy) == 0) { uint64_t hdr = (uint64_t)br13 << 32 | cmd; do { - int nbox_this_time; + int nbox_this_time, rem; nbox_this_time = nbox; - if (8*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; + rem = kgem_batch_space(kgem); + if (8*nbox_this_time > rem) + nbox_this_time = rem / 8; if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc)/2; assert(nbox_this_time); @@ -1656,11 +1662,12 @@ static void blt_composite_copy_boxes__thread(struct sna *sna, } while (1); } else { do { - int nbox_this_time; + int nbox_this_time, rem; nbox_this_time = nbox; - if (8*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; + rem = kgem_batch_space(kgem); + if (8*nbox_this_time > rem) + nbox_this_time = rem / 8; if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc)/2; assert(nbox_this_time); @@ -1733,11 +1740,12 @@ static void blt_composite_copy_boxes__thread64(struct sna *sna, if ((dst_dx | dst_dy) == 0) { uint64_t hdr = (uint64_t)br13 << 32 | cmd; do { - int nbox_this_time; + int nbox_this_time, rem; nbox_this_time = nbox; - if (10*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 10; + rem = kgem_batch_space(kgem); + if (10*nbox_this_time > rem) + nbox_this_time = rem / 10; if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc)/2; assert(nbox_this_time); @@ -1788,11 +1796,11 @@ static void blt_composite_copy_boxes__thread64(struct sna *sna, } while (1); } else { do { - int nbox_this_time; + int nbox_this_time, rem; nbox_this_time = nbox; - if (10*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 10; + if (10*nbox_this_time > rem) + nbox_this_time = rem / 10; if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc)/2; assert(nbox_this_time); @@ -3124,12 +3132,13 @@ fastcall static void sna_blt_fill_op_points(struct sna *sna, do { uint32_t *b = kgem->batch + kgem->nbatch; - int n_this_time; + int n_this_time, rem; assert(sna->kgem.mode == KGEM_BLT); n_this_time = n; - if (2*n_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - n_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 2; + rem = kgem_batch_space(kgem); + if (2*n_this_time > rem) + n_this_time = rem / 2; assert(n_this_time); n -= n_this_time; @@ -3226,6 +3235,7 @@ bool sna_blt_fill(struct sna *sna, uint8_t alu, bo, bpp, alu, pixel)) return false; + assert(sna->kgem.mode == KGEM_BLT); fill->blt = sna_blt_fill_op_blt; fill->box = sna_blt_fill_op_box; fill->boxes = sna_blt_fill_op_boxes; @@ -3543,11 +3553,11 @@ bool sna_blt_fill_boxes(struct sna *sna, uint8_t alu, } do { - int nbox_this_time; + int nbox_this_time, rem; nbox_this_time = nbox; - if (3*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 3; + if (3*nbox_this_time > rem) + nbox_this_time = rem / 3; assert(nbox_this_time); nbox -= nbox_this_time; @@ -3728,11 +3738,12 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu, if (kgem->gen >= 0100) { uint64_t hdr = (uint64_t)br13 << 32 | cmd | 8; do { - int nbox_this_time; + int nbox_this_time, rem; nbox_this_time = nbox; - if (10*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; + rem = kgem_batch_space(kgem); + if (10*nbox_this_time > rem) + nbox_this_time = rem / 8; if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc)/2; assert(nbox_this_time); @@ -3784,11 +3795,12 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu, } else { uint64_t hdr = (uint64_t)br13 << 32 | cmd | 6; do { - int nbox_this_time; + int nbox_this_time, rem; nbox_this_time = nbox; - if (8*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; + rem = kgem_batch_space(kgem); + if (8*nbox_this_time > rem) + nbox_this_time = rem / 8; if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc)/2; assert(nbox_this_time); @@ -3840,11 +3852,12 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu, if (kgem->gen >= 0100) { cmd |= 8; do { - int nbox_this_time; + int nbox_this_time, rem; nbox_this_time = nbox; - if (10*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; + rem = kgem_batch_space(kgem); + if (10*nbox_this_time > rem) + nbox_this_time = rem / 8; if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc)/2; assert(nbox_this_time); @@ -3896,11 +3909,12 @@ bool sna_blt_copy_boxes(struct sna *sna, uint8_t alu, } else { cmd |= 6; do { - int nbox_this_time; + int nbox_this_time, rem; nbox_this_time = nbox; - if (8*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; + rem = kgem_batch_space(kgem); + if (8*nbox_this_time > rem) + nbox_this_time = rem / 8; if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc)/2; assert(nbox_this_time); diff --git a/src/sna/sna_io.c b/src/sna/sna_io.c index 51d3af0e..6eede4df 100644 --- a/src/sna/sna_io.c +++ b/src/sna/sna_io.c @@ -484,11 +484,12 @@ fallback: if (sna->kgem.gen >= 0100) { cmd |= 8; do { - int nbox_this_time; + int nbox_this_time, rem; nbox_this_time = tmp_nbox; - if (10*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; + rem = kgem_batch_space(kgem); + if (10*nbox_this_time > rem) + nbox_this_time = rem / 8; if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc) / 2; assert(nbox_this_time); @@ -543,11 +544,11 @@ fallback: } else { cmd |= 6; do { - int nbox_this_time; + int nbox_this_time, rem; nbox_this_time = tmp_nbox; - if (8*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; + if (8*nbox_this_time > rem) + nbox_this_time = rem / 8; if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc) / 2; assert(nbox_this_time); @@ -1029,11 +1030,12 @@ tile: if (kgem->gen >= 0100) { cmd |= 8; do { - int nbox_this_time; + int nbox_this_time, rem; nbox_this_time = nbox; - if (10*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; + rem = kgem_batch_space(kgem); + if (10*nbox_this_time > rem) + nbox_this_time = rem / 8; if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc) / 2; assert(nbox_this_time); @@ -1122,11 +1124,12 @@ tile: } else { cmd |= 6; do { - int nbox_this_time; + int nbox_this_time, rem; nbox_this_time = nbox; - if (8*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; + rem = kgem_batch_space(kgem); + if (8*nbox_this_time > rem) + nbox_this_time = rem / 8; if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc) / 2; assert(nbox_this_time); @@ -1530,11 +1533,12 @@ tile: if (sna->kgem.gen >= 0100) { cmd |= 8; do { - int nbox_this_time; + int nbox_this_time, rem; nbox_this_time = nbox; - if (10*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; + rem = kgem_batch_space(kgem); + if (10*nbox_this_time > rem) + nbox_this_time = rem / 8; if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc) / 2; assert(nbox_this_time); @@ -1627,11 +1631,12 @@ tile: } else { cmd |= 6; do { - int nbox_this_time; + int nbox_this_time, rem; nbox_this_time = nbox; - if (8*nbox_this_time > kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) - nbox_this_time = (kgem->surface - kgem->nbatch - KGEM_BATCH_RESERVED) / 8; + rem = kgem_batch_space(kgem); + if (8*nbox_this_time > rem) + nbox_this_time = rem / 8; if (2*nbox_this_time > KGEM_RELOC_SIZE(kgem) - kgem->nreloc) nbox_this_time = (KGEM_RELOC_SIZE(kgem) - kgem->nreloc) / 2; assert(nbox_this_time); |