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:
Karol Herbst
2022-06-15 01:23:17 +02:00
committed by Marge Bot
parent ee50fe7d85
commit 008e9768ad
3 changed files with 65 additions and 0 deletions
+1
View File
@@ -1,6 +1,7 @@
#ifndef NOUVEAU_PRIVATE
#define NOUVEAU_PRIVATE 1
#include <assert.h>
#include <stdint.h>
#include "util/u_memory.h"
+42
View File
@@ -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;
+22
View File
@@ -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);
}