[Mesa-dev] [PATCH] winsys/radeon: add command stream replay dump for faulty lockup v2
From: Jerome Glisse Build time option, set RADEON_CS_DUMP_ON_LOCKUP to 1 in radeon_drm_cs.h to enable it. When enabled after each cs submission the code will try to detect lockup by waiting on one of the buffer of the cs to become idle, after a timeout it will consider that the cs triggered a lockup and will write a radeon_lockup.c file in current directory that have all information for replaying the cs. To build this file : gcc -O0 -g radeon_lockup.c -ldrm -o radeon_lockup -I/usr/include/libdrm v2: Add radeon_ctx.h file to mesa git tree Signed-off-by: Jerome Glisse --- src/gallium/winsys/radeon/drm/Makefile.sources | 1 + src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 80 +++ src/gallium/winsys/radeon/drm/radeon_drm_bo.h | 2 + src/gallium/winsys/radeon/drm/radeon_drm_cs.c | 4 + src/gallium/winsys/radeon/drm/radeon_drm_cs.h | 6 + src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c | 141 src/gallium/winsys/radeon/tools/radeon_ctx.h | 237 + 7 files changed, 434 insertions(+), 37 deletions(-) create mode 100644 src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c create mode 100644 src/gallium/winsys/radeon/tools/radeon_ctx.h diff --git a/src/gallium/winsys/radeon/drm/Makefile.sources b/src/gallium/winsys/radeon/drm/Makefile.sources index 1d18d61..4ca5ebb 100644 --- a/src/gallium/winsys/radeon/drm/Makefile.sources +++ b/src/gallium/winsys/radeon/drm/Makefile.sources @@ -1,4 +1,5 @@ C_SOURCES := \ radeon_drm_bo.c \ radeon_drm_cs.c \ + radeon_drm_cs_dump.c \ radeon_drm_winsys.c diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c index f4ac526..5a9493a 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -391,14 +391,54 @@ static void radeon_bo_destroy(struct pb_buffer *_buf) FREE(bo); } +void *radeon_bo_do_map(struct radeon_bo *bo) +{ +struct drm_radeon_gem_mmap args = {0}; +void *ptr; + +/* Return the pointer if it's already mapped. */ +if (bo->ptr) +return bo->ptr; + +/* Map the buffer. */ +pipe_mutex_lock(bo->map_mutex); +/* Return the pointer if it's already mapped (in case of a race). */ +if (bo->ptr) { +pipe_mutex_unlock(bo->map_mutex); +return bo->ptr; +} +args.handle = bo->handle; +args.offset = 0; +args.size = (uint64_t)bo->base.size; +if (drmCommandWriteRead(bo->rws->fd, +DRM_RADEON_GEM_MMAP, +&args, +sizeof(args))) { +pipe_mutex_unlock(bo->map_mutex); +fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n", +bo, bo->handle); +return NULL; +} + +ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, + bo->rws->fd, args.addr_ptr); +if (ptr == MAP_FAILED) { +pipe_mutex_unlock(bo->map_mutex); +fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno); +return NULL; +} +bo->ptr = ptr; +pipe_mutex_unlock(bo->map_mutex); + +return bo->ptr; +} + static void *radeon_bo_map(struct radeon_winsys_cs_handle *buf, struct radeon_winsys_cs *rcs, enum pipe_transfer_usage usage) { struct radeon_bo *bo = (struct radeon_bo*)buf; struct radeon_drm_cs *cs = (struct radeon_drm_cs*)rcs; -struct drm_radeon_gem_mmap args = {0}; -void *ptr; /* If it's not unsynchronized bo_map, flush CS if needed and then wait. */ if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { @@ -461,41 +501,7 @@ static void *radeon_bo_map(struct radeon_winsys_cs_handle *buf, } } -/* Return the pointer if it's already mapped. */ -if (bo->ptr) -return bo->ptr; - -/* Map the buffer. */ -pipe_mutex_lock(bo->map_mutex); -/* Return the pointer if it's already mapped (in case of a race). */ -if (bo->ptr) { -pipe_mutex_unlock(bo->map_mutex); -return bo->ptr; -} -args.handle = bo->handle; -args.offset = 0; -args.size = (uint64_t)bo->base.size; -if (drmCommandWriteRead(bo->rws->fd, -DRM_RADEON_GEM_MMAP, -&args, -sizeof(args))) { -pipe_mutex_unlock(bo->map_mutex); -fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n", -bo, bo->handle); -return NULL; -} - -ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, - bo->rws->fd, args.addr_ptr); -if (ptr == MAP_FAILED) { -pipe_mutex_unlock(bo->map_mutex); -fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno); -return NULL; -} -bo->ptr = ptr; -pipe_mutex_unlock(bo->map_mutex); - -return bo->ptr; +return radeon_bo_do_map(bo); } static vo
Re: [Mesa-dev] [PATCH] winsys/radeon: add command stream replay dump for faulty lockup
On Wed, Mar 27, 2013 at 4:38 PM, Jerome Glisse wrote: > On Wed, Mar 27, 2013 at 11:27 AM, wrote: >> From: Jerome Glisse >> >> Build time option, set RADEON_CS_DUMP_ON_LOCKUP to 1 in radeon_drm_cs.h to >> enable it. >> >> When enabled after each cs submission the code will try to detect lockup by >> waiting on one of the buffer of the cs to become idle, after a timeout it >> will consider that the cs triggered a lockup and will write a radeon_lockup.c >> file in current directory that have all information for replaying the cs. >> >> To build this file : >> gcc -O0 -g radeon_lockup.c -ldrm -o radeon_lockup -I/usr/include/libdrm >> >> Signed-off-by: Jerome Glisse > > Maybe i should add the radeon_ctx.h file to winsys dir as you need it > to build the radeon_lockup.c i did not wanted to printf the whole > helper. For example you can check radeon_lockup.c and radeon_ctx.h > here : > http://people.freedesktop.org/~glisse/rlockup/ It would be better to put the file in a separate directory (maybe a subdirectory in the winsys) and add a note that it's supposed to be used by out-of-tree code. Otherwise it looks good. Marek > > Note this is a radeon si verde capture for a 2d tiling that lockup > (can be hard lockup sometimes so be careful). > > Cheers, > Jerome > >> --- >> src/gallium/winsys/radeon/drm/Makefile.sources | 1 + >> src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 80 ++-- >> src/gallium/winsys/radeon/drm/radeon_drm_bo.h | 2 + >> src/gallium/winsys/radeon/drm/radeon_drm_cs.c | 4 + >> src/gallium/winsys/radeon/drm/radeon_drm_cs.h | 6 + >> src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c | 135 >> + >> 6 files changed, 191 insertions(+), 37 deletions(-) >> create mode 100644 src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c >> >> diff --git a/src/gallium/winsys/radeon/drm/Makefile.sources >> b/src/gallium/winsys/radeon/drm/Makefile.sources >> index 1d18d61..4ca5ebb 100644 >> --- a/src/gallium/winsys/radeon/drm/Makefile.sources >> +++ b/src/gallium/winsys/radeon/drm/Makefile.sources >> @@ -1,4 +1,5 @@ >> C_SOURCES := \ >> radeon_drm_bo.c \ >> radeon_drm_cs.c \ >> + radeon_drm_cs_dump.c \ >> radeon_drm_winsys.c >> diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c >> b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c >> index f4ac526..5a9493a 100644 >> --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c >> +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c >> @@ -391,14 +391,54 @@ static void radeon_bo_destroy(struct pb_buffer *_buf) >> FREE(bo); >> } >> >> +void *radeon_bo_do_map(struct radeon_bo *bo) >> +{ >> +struct drm_radeon_gem_mmap args = {0}; >> +void *ptr; >> + >> +/* Return the pointer if it's already mapped. */ >> +if (bo->ptr) >> +return bo->ptr; >> + >> +/* Map the buffer. */ >> +pipe_mutex_lock(bo->map_mutex); >> +/* Return the pointer if it's already mapped (in case of a race). */ >> +if (bo->ptr) { >> +pipe_mutex_unlock(bo->map_mutex); >> +return bo->ptr; >> +} >> +args.handle = bo->handle; >> +args.offset = 0; >> +args.size = (uint64_t)bo->base.size; >> +if (drmCommandWriteRead(bo->rws->fd, >> +DRM_RADEON_GEM_MMAP, >> +&args, >> +sizeof(args))) { >> +pipe_mutex_unlock(bo->map_mutex); >> +fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n", >> +bo, bo->handle); >> +return NULL; >> +} >> + >> +ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, >> + bo->rws->fd, args.addr_ptr); >> +if (ptr == MAP_FAILED) { >> +pipe_mutex_unlock(bo->map_mutex); >> +fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno); >> +return NULL; >> +} >> +bo->ptr = ptr; >> +pipe_mutex_unlock(bo->map_mutex); >> + >> +return bo->ptr; >> +} >> + >> static void *radeon_bo_map(struct radeon_winsys_cs_handle *buf, >> struct radeon_winsys_cs *rcs, >> enum pipe_transfer_usage usage) >> { >> struct radeon_bo *bo = (struct radeon_bo*)buf; >> struct radeon_drm_cs *cs = (struct radeon_drm_cs*)rcs; >> -struct drm_radeon_gem_mmap args = {0}; >> -void *ptr; >> >> /* If it's not unsynchronized bo_map, flush CS if needed and then wait. >> */ >> if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { >> @@ -461,41 +501,7 @@ static void *radeon_bo_map(struct >> radeon_winsys_cs_handle *buf, >> } >> } >> >> -/* Return the pointer if it's already mapped. */ >> -if (bo->ptr) >> -return bo->ptr; >> - >> -/* Map the buffer. */ >> -pipe_mutex_lock(bo->map_mutex); >> -/* Return the pointer if it's already mapped (in case of a race). */ >> -if (bo->ptr) { >> -pipe_mutex_unlock(bo->map_mutex); >> -return bo->pt
Re: [Mesa-dev] [PATCH] winsys/radeon: add command stream replay dump for faulty lockup
On Wed, Mar 27, 2013 at 11:27 AM, wrote: > From: Jerome Glisse > > Build time option, set RADEON_CS_DUMP_ON_LOCKUP to 1 in radeon_drm_cs.h to > enable it. > > When enabled after each cs submission the code will try to detect lockup by > waiting on one of the buffer of the cs to become idle, after a timeout it > will consider that the cs triggered a lockup and will write a radeon_lockup.c > file in current directory that have all information for replaying the cs. > > To build this file : > gcc -O0 -g radeon_lockup.c -ldrm -o radeon_lockup -I/usr/include/libdrm > > Signed-off-by: Jerome Glisse Maybe i should add the radeon_ctx.h file to winsys dir as you need it to build the radeon_lockup.c i did not wanted to printf the whole helper. For example you can check radeon_lockup.c and radeon_ctx.h here : http://people.freedesktop.org/~glisse/rlockup/ Note this is a radeon si verde capture for a 2d tiling that lockup (can be hard lockup sometimes so be careful). Cheers, Jerome > --- > src/gallium/winsys/radeon/drm/Makefile.sources | 1 + > src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 80 ++-- > src/gallium/winsys/radeon/drm/radeon_drm_bo.h | 2 + > src/gallium/winsys/radeon/drm/radeon_drm_cs.c | 4 + > src/gallium/winsys/radeon/drm/radeon_drm_cs.h | 6 + > src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c | 135 > + > 6 files changed, 191 insertions(+), 37 deletions(-) > create mode 100644 src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c > > diff --git a/src/gallium/winsys/radeon/drm/Makefile.sources > b/src/gallium/winsys/radeon/drm/Makefile.sources > index 1d18d61..4ca5ebb 100644 > --- a/src/gallium/winsys/radeon/drm/Makefile.sources > +++ b/src/gallium/winsys/radeon/drm/Makefile.sources > @@ -1,4 +1,5 @@ > C_SOURCES := \ > radeon_drm_bo.c \ > radeon_drm_cs.c \ > + radeon_drm_cs_dump.c \ > radeon_drm_winsys.c > diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c > b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c > index f4ac526..5a9493a 100644 > --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c > +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c > @@ -391,14 +391,54 @@ static void radeon_bo_destroy(struct pb_buffer *_buf) > FREE(bo); > } > > +void *radeon_bo_do_map(struct radeon_bo *bo) > +{ > +struct drm_radeon_gem_mmap args = {0}; > +void *ptr; > + > +/* Return the pointer if it's already mapped. */ > +if (bo->ptr) > +return bo->ptr; > + > +/* Map the buffer. */ > +pipe_mutex_lock(bo->map_mutex); > +/* Return the pointer if it's already mapped (in case of a race). */ > +if (bo->ptr) { > +pipe_mutex_unlock(bo->map_mutex); > +return bo->ptr; > +} > +args.handle = bo->handle; > +args.offset = 0; > +args.size = (uint64_t)bo->base.size; > +if (drmCommandWriteRead(bo->rws->fd, > +DRM_RADEON_GEM_MMAP, > +&args, > +sizeof(args))) { > +pipe_mutex_unlock(bo->map_mutex); > +fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n", > +bo, bo->handle); > +return NULL; > +} > + > +ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, > + bo->rws->fd, args.addr_ptr); > +if (ptr == MAP_FAILED) { > +pipe_mutex_unlock(bo->map_mutex); > +fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno); > +return NULL; > +} > +bo->ptr = ptr; > +pipe_mutex_unlock(bo->map_mutex); > + > +return bo->ptr; > +} > + > static void *radeon_bo_map(struct radeon_winsys_cs_handle *buf, > struct radeon_winsys_cs *rcs, > enum pipe_transfer_usage usage) > { > struct radeon_bo *bo = (struct radeon_bo*)buf; > struct radeon_drm_cs *cs = (struct radeon_drm_cs*)rcs; > -struct drm_radeon_gem_mmap args = {0}; > -void *ptr; > > /* If it's not unsynchronized bo_map, flush CS if needed and then wait. > */ > if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { > @@ -461,41 +501,7 @@ static void *radeon_bo_map(struct > radeon_winsys_cs_handle *buf, > } > } > > -/* Return the pointer if it's already mapped. */ > -if (bo->ptr) > -return bo->ptr; > - > -/* Map the buffer. */ > -pipe_mutex_lock(bo->map_mutex); > -/* Return the pointer if it's already mapped (in case of a race). */ > -if (bo->ptr) { > -pipe_mutex_unlock(bo->map_mutex); > -return bo->ptr; > -} > -args.handle = bo->handle; > -args.offset = 0; > -args.size = (uint64_t)bo->base.size; > -if (drmCommandWriteRead(bo->rws->fd, > -DRM_RADEON_GEM_MMAP, > -&args, > -sizeof(args))) { > -pipe_mutex_unlock(bo->map_mutex); > -fprintf(stderr, "radeon: gem_mmap faile
[Mesa-dev] [PATCH] winsys/radeon: add command stream replay dump for faulty lockup
From: Jerome Glisse Build time option, set RADEON_CS_DUMP_ON_LOCKUP to 1 in radeon_drm_cs.h to enable it. When enabled after each cs submission the code will try to detect lockup by waiting on one of the buffer of the cs to become idle, after a timeout it will consider that the cs triggered a lockup and will write a radeon_lockup.c file in current directory that have all information for replaying the cs. To build this file : gcc -O0 -g radeon_lockup.c -ldrm -o radeon_lockup -I/usr/include/libdrm Signed-off-by: Jerome Glisse --- src/gallium/winsys/radeon/drm/Makefile.sources | 1 + src/gallium/winsys/radeon/drm/radeon_drm_bo.c | 80 ++-- src/gallium/winsys/radeon/drm/radeon_drm_bo.h | 2 + src/gallium/winsys/radeon/drm/radeon_drm_cs.c | 4 + src/gallium/winsys/radeon/drm/radeon_drm_cs.h | 6 + src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c | 135 + 6 files changed, 191 insertions(+), 37 deletions(-) create mode 100644 src/gallium/winsys/radeon/drm/radeon_drm_cs_dump.c diff --git a/src/gallium/winsys/radeon/drm/Makefile.sources b/src/gallium/winsys/radeon/drm/Makefile.sources index 1d18d61..4ca5ebb 100644 --- a/src/gallium/winsys/radeon/drm/Makefile.sources +++ b/src/gallium/winsys/radeon/drm/Makefile.sources @@ -1,4 +1,5 @@ C_SOURCES := \ radeon_drm_bo.c \ radeon_drm_cs.c \ + radeon_drm_cs_dump.c \ radeon_drm_winsys.c diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c index f4ac526..5a9493a 100644 --- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c +++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c @@ -391,14 +391,54 @@ static void radeon_bo_destroy(struct pb_buffer *_buf) FREE(bo); } +void *radeon_bo_do_map(struct radeon_bo *bo) +{ +struct drm_radeon_gem_mmap args = {0}; +void *ptr; + +/* Return the pointer if it's already mapped. */ +if (bo->ptr) +return bo->ptr; + +/* Map the buffer. */ +pipe_mutex_lock(bo->map_mutex); +/* Return the pointer if it's already mapped (in case of a race). */ +if (bo->ptr) { +pipe_mutex_unlock(bo->map_mutex); +return bo->ptr; +} +args.handle = bo->handle; +args.offset = 0; +args.size = (uint64_t)bo->base.size; +if (drmCommandWriteRead(bo->rws->fd, +DRM_RADEON_GEM_MMAP, +&args, +sizeof(args))) { +pipe_mutex_unlock(bo->map_mutex); +fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n", +bo, bo->handle); +return NULL; +} + +ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, + bo->rws->fd, args.addr_ptr); +if (ptr == MAP_FAILED) { +pipe_mutex_unlock(bo->map_mutex); +fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno); +return NULL; +} +bo->ptr = ptr; +pipe_mutex_unlock(bo->map_mutex); + +return bo->ptr; +} + static void *radeon_bo_map(struct radeon_winsys_cs_handle *buf, struct radeon_winsys_cs *rcs, enum pipe_transfer_usage usage) { struct radeon_bo *bo = (struct radeon_bo*)buf; struct radeon_drm_cs *cs = (struct radeon_drm_cs*)rcs; -struct drm_radeon_gem_mmap args = {0}; -void *ptr; /* If it's not unsynchronized bo_map, flush CS if needed and then wait. */ if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { @@ -461,41 +501,7 @@ static void *radeon_bo_map(struct radeon_winsys_cs_handle *buf, } } -/* Return the pointer if it's already mapped. */ -if (bo->ptr) -return bo->ptr; - -/* Map the buffer. */ -pipe_mutex_lock(bo->map_mutex); -/* Return the pointer if it's already mapped (in case of a race). */ -if (bo->ptr) { -pipe_mutex_unlock(bo->map_mutex); -return bo->ptr; -} -args.handle = bo->handle; -args.offset = 0; -args.size = (uint64_t)bo->base.size; -if (drmCommandWriteRead(bo->rws->fd, -DRM_RADEON_GEM_MMAP, -&args, -sizeof(args))) { -pipe_mutex_unlock(bo->map_mutex); -fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n", -bo, bo->handle); -return NULL; -} - -ptr = os_mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, - bo->rws->fd, args.addr_ptr); -if (ptr == MAP_FAILED) { -pipe_mutex_unlock(bo->map_mutex); -fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno); -return NULL; -} -bo->ptr = ptr; -pipe_mutex_unlock(bo->map_mutex); - -return bo->ptr; +return radeon_bo_do_map(bo); } static void radeon_bo_unmap(struct radeon_winsys_cs_handle *_buf) diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.h b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h index 82ea