nouveau/ws: make sure we don't submit nonsense
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24326>
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
#ifndef NOUVEAU_PRIVATE
|
||||
#define NOUVEAU_PRIVATE 1
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "util/u_memory.h"
|
||||
|
||||
@@ -55,6 +55,42 @@ nouveau_ws_push_destroy(struct nouveau_ws_push *push)
|
||||
nouveau_ws_bo_destroy(push->bo);
|
||||
}
|
||||
|
||||
static void
|
||||
nouveau_ws_push_valid(struct nouveau_ws_push *push) {
|
||||
uint32_t *cur = push->orig_map;
|
||||
|
||||
/* submitting empty push buffers is probably a bug */
|
||||
assert(push->map != push->orig_map);
|
||||
|
||||
/* make sure we don't overrun the bo */
|
||||
assert(push->map <= push->end);
|
||||
|
||||
/* parse all the headers to see if we get to push->map */
|
||||
while (cur < push->map) {
|
||||
uint32_t hdr = *cur;
|
||||
uint32_t mthd = hdr >> 29;
|
||||
|
||||
switch (mthd) {
|
||||
/* immd */
|
||||
case 4:
|
||||
break;
|
||||
case 1:
|
||||
case 3:
|
||||
case 5: {
|
||||
uint32_t count = (hdr >> 16) & 0x1fff;
|
||||
assert(count);
|
||||
cur += count;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(!"unknown method found");
|
||||
}
|
||||
|
||||
cur++;
|
||||
assert(cur <= push->map);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
nouveau_ws_push_submit(
|
||||
struct nouveau_ws_push *push,
|
||||
@@ -68,6 +104,12 @@ nouveau_ws_push_submit(
|
||||
struct drm_nouveau_gem_pushbuf req = {};
|
||||
struct drm_nouveau_gem_pushbuf_push req_push = {};
|
||||
|
||||
if (push->map == push->orig_map)
|
||||
return 0;
|
||||
|
||||
/* make sure we don't submit nonsense */
|
||||
nouveau_ws_push_valid(push);
|
||||
|
||||
int i = 0;
|
||||
util_dynarray_foreach(&push->bos, struct nouveau_ws_push_bo, push_bo) {
|
||||
struct nouveau_ws_bo *bo = push_bo->bo;
|
||||
|
||||
@@ -46,9 +46,27 @@ NVC0_FIFO_PKHDR_SQ(int subc, int mthd, unsigned size)
|
||||
return 0x20000000 | (size << 16) | (subc << 13) | (mthd >> 2);
|
||||
}
|
||||
|
||||
static inline void
|
||||
__push_verify(struct nouveau_ws_push *push)
|
||||
{
|
||||
if (!push->last_size)
|
||||
return;
|
||||
|
||||
/* make sure we don't add a new method if the last one wasn't used */
|
||||
uint32_t last_hdr = *push->last_size;
|
||||
|
||||
/* check for immd */
|
||||
if (last_hdr >> 29 == 4)
|
||||
return;
|
||||
|
||||
UNUSED uint32_t last_count = (last_hdr & 0x1fff0000);
|
||||
assert(last_count);
|
||||
}
|
||||
|
||||
static inline void
|
||||
__push_mthd(struct nouveau_ws_push *push, int subc, uint32_t mthd)
|
||||
{
|
||||
__push_verify(push);
|
||||
push->last_size = push->map;
|
||||
*push->map = NVC0_FIFO_PKHDR_SQ(subc, mthd, 0);
|
||||
push->map++;
|
||||
@@ -66,6 +84,7 @@ NVC0_FIFO_PKHDR_IL(int subc, int mthd, uint16_t data)
|
||||
static inline void
|
||||
__push_immd(struct nouveau_ws_push *push, int subc, uint32_t mthd, uint32_t val)
|
||||
{
|
||||
__push_verify(push);
|
||||
push->last_size = push->map;
|
||||
*push->map = NVC0_FIFO_PKHDR_IL(subc, mthd, val);
|
||||
push->map++;
|
||||
@@ -86,6 +105,7 @@ NVC0_FIFO_PKHDR_1I(int subc, int mthd, unsigned size)
|
||||
static inline void
|
||||
__push_1inc(struct nouveau_ws_push *push, int subc, uint32_t mthd)
|
||||
{
|
||||
__push_verify(push);
|
||||
push->last_size = push->map;
|
||||
*push->map = NVC0_FIFO_PKHDR_1I(subc, mthd, 0);
|
||||
push->map++;
|
||||
@@ -102,6 +122,7 @@ NVC0_FIFO_PKHDR_0I(int subc, int mthd, unsigned size)
|
||||
static inline void
|
||||
__push_0inc(struct nouveau_ws_push *push, int subc, uint32_t mthd)
|
||||
{
|
||||
__push_verify(push);
|
||||
push->last_size = push->map;
|
||||
*push->map = NVC0_FIFO_PKHDR_0I(subc, mthd, 0);
|
||||
push->map++;
|
||||
@@ -173,6 +194,7 @@ nvk_push_val(struct nouveau_ws_push *push, uint32_t idx, uint32_t val)
|
||||
assert(last_hdr_val);
|
||||
assert(!is_immd);
|
||||
assert(last_method == idx);
|
||||
assert(push->map < push->end);
|
||||
|
||||
P_INLINE_DATA(push, val);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user