v3d: fix indirect BO allocation for uniforms
We were always ensuring a minimum size of 4 bytes for uniforms for the case where we don't have any, to account for hardware pre-fetching of the uniform stream, however, pre-fetching could also lead to to out of bounds reads when have read the last uniform in the stream, so we probably want to have the extra 4 bytes to prevent the kernel from observing invalid memory accesses when the uniform stream sits right at the end of a page. This seems to fix MMU exceptions reported with a Linux 5.4 kernel. Credit goes to Phil Elwell for identifying the problem and narrowing it down to memory accesses in the uniform stream. Reported-by: Phil Elwell <phil@raspberrypi.org> Tested-by: Phil Elwell <phil@raspberrypi.org> Reviewed-by: Eric Anholt <eric@anholt.net>
This commit is contained in:
parent
a24f1c8f7f
commit
18a09e788d
|
@ -215,10 +215,15 @@ v3d_write_uniforms(struct v3d_context *v3d, struct v3d_job *job,
|
|||
struct v3d_uniform_list *uinfo = &shader->prog_data.base->uniforms;
|
||||
const uint32_t *gallium_uniforms = cb->cb[0].user_buffer;
|
||||
|
||||
/* We always need to return some space for uniforms, because the HW
|
||||
* will be prefetching, even if we don't read any in the program.
|
||||
/* The hardware always pre-fetches the next uniform (also when there
|
||||
* aren't any), so we always allocate space for an extra slot. This
|
||||
* fixes MMU exceptions reported since Linux kernel 5.4 when the
|
||||
* uniforms fill up the tail bytes of a page in the indirect
|
||||
* BO. In that scenario, when the hardware pre-fetches after reading
|
||||
* the last uniform it will read beyond the end of the page and trigger
|
||||
* the MMU exception.
|
||||
*/
|
||||
v3d_cl_ensure_space(&job->indirect, MAX2(uinfo->count, 1) * 4, 4);
|
||||
v3d_cl_ensure_space(&job->indirect, (uinfo->count + 1) * 4, 4);
|
||||
|
||||
struct v3d_cl_reloc uniform_stream = cl_get_address(&job->indirect);
|
||||
v3d_bo_reference(uniform_stream.bo);
|
||||
|
|
Loading…
Reference in New Issue