--- a/sys/dev/video/bktr/bktr_reg.h +++ b/sys/dev/video/bktr/bktr_reg.h @@ -454,6 +454,8 @@ vm_offset_t vbibuffer; /* Circular buffer holding VBI data for the user */ vm_offset_t dma_prog; /* RISC prog for single and/or even field capture*/ vm_offset_t odd_dma_prog;/* RISC program for Odd field capture */ + vm_offset_t dma_prog_limit; /* one dword past the usable end + of the RISC program buffer being built (DF-3783) */ /* the following definitions are common over all platforms */ int alloc_pages; /* number of pages in bigbuf */ --- a/sys/dev/video/bktr/bktr_core.c +++ b/sys/dev/video/bktr/bktr_core.c @@ -2538,6 +2538,10 @@ volatile u_char ** target_buffer, int cols ) { u_long flag, flag2; + + /* DF-3783: never emit past the fixed-size program buffer */ + if (*dma_prog + 4 > (volatile uint32_t *)bktr->dma_prog_limit) + return FALSE; struct meteor_pixfmt *pf = &pixfmt_table[ bktr->pixfmt ].public; u_int skip, start_skip; @@ -2664,6 +2668,11 @@ bktr->capcontrol = 3 << 2 | 3; dma_prog = (uint32_t *) bktr->dma_prog; + bktr->dma_prog_limit = bktr->dma_prog + DMA_PROG_ALLOC - 16; + bktr->dma_prog_limit = bktr->dma_prog + DMA_PROG_ALLOC - 16; + bktr->dma_prog_limit = bktr->dma_prog + DMA_PROG_ALLOC - 16; + bktr->dma_prog_limit = bktr->dma_prog + DMA_PROG_ALLOC - 16; + bktr->dma_prog_limit = bktr->dma_prog + DMA_PROG_ALLOC - 16; /* Construct Write */ @@ -2703,6 +2712,8 @@ *dma_prog++ = 0; /* NULL WORD */ width = cols; for (i = 0; i < (rows/interlace); i++) { + if (dma_prog + 5 > (volatile uint32_t *)bktr->dma_prog_limit) + break; /* DF-3783: program buffer full */ target = target_buffer; if ( notclipped(bktr, i, width)) { split(bktr, &dma_prog, bktr->y2 - bktr->y, OP_WRITE, @@ -2915,6 +2926,10 @@ target_buffer = buffer + pitch; dma_prog = (uint32_t *) bktr->odd_dma_prog; + bktr->dma_prog_limit = bktr->odd_dma_prog + DMA_PROG_ALLOC - 16; + bktr->dma_prog_limit = bktr->odd_dma_prog + DMA_PROG_ALLOC - 16; + bktr->dma_prog_limit = bktr->odd_dma_prog + DMA_PROG_ALLOC - 16; + bktr->dma_prog_limit = bktr->odd_dma_prog + DMA_PROG_ALLOC - 16; /* sync vre IRQ bit */ *dma_prog++ = OP_SYNC | BKTR_RESYNC | BKTR_FM1; @@ -3052,6 +3067,8 @@ *dma_prog++ = 0; /* NULL WORD */ for (i = 0; i < (rows/interlace) ; i++) { + if (dma_prog + 5 > (volatile uint32_t *)bktr->dma_prog_limit) + break; /* DF-3783: program buffer full */ *dma_prog++ = inst; *dma_prog++ = target_buffer; *dma_prog++ = inst3; @@ -3088,6 +3105,7 @@ OUTB(bktr, BKTR_COLOR_FMT, pf_int->color_fmt); dma_prog = (uint32_t*) bktr->dma_prog; + bktr->dma_prog_limit = bktr->dma_prog + DMA_PROG_ALLOC - 16; bktr->capcontrol = 1 << 6 | 1 << 4 | 3; @@ -3124,6 +3142,10 @@ *dma_prog++ = 0; /* NULL WORD */ for (i = 0; i < (rows/interlace ) ; i++) { + if (dma_prog + 6 > (volatile uint32_t *)bktr->dma_prog_limit) + break; /* DF-3783: program buffer full */ + if (dma_prog + 6 > (volatile uint32_t *)bktr->dma_prog_limit) + break; /* DF-3783: program buffer full */ *dma_prog++ = inst; *dma_prog++ = cols/2 | cols/2 << 16; *dma_prog++ = target_buffer; @@ -3223,6 +3245,8 @@ *dma_prog++ = 0; /* NULL WORD */ for (i = 0; i < (rows/interlace )/2 ; i++) { + if (dma_prog + 8 > (volatile uint32_t *)bktr->dma_prog_limit) + break; /* DF-3783: program buffer full */ *dma_prog++ = inst; *dma_prog++ = cols/2 | (cols/2 << 16); *dma_prog++ = target_buffer; @@ -3271,6 +3295,8 @@ *dma_prog++ = 0; /* NULL WORD */ for (i = 0; i < ((rows/interlace )/2 ) ; i++) { + if (dma_prog + 8 > (volatile uint32_t *)bktr->dma_prog_limit) + break; /* DF-3783: program buffer full */ *dma_prog++ = inst; *dma_prog++ = cols/2 | (cols/2 << 16); *dma_prog++ = target_buffer;