ethosu: map BOs at creation time and unmap at destruction

Map DRM buffer objects once at resource_create and unmap at
resource_destroy, instead of mapping them in buffer_map where they
were never unmapped. This fixes a virtual memory leak that caused
SIGBUS under heavy workloads by exhausting CMA.

Also remove unused phys_addr and obj_addr fields from ethosu_resource,
and add asserts on pipe_buffer_create return values.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/39611>
This commit is contained in:
Tomeu Vizoso 2026-03-22 16:36:03 +01:00 committed by Marge Bot
parent f9cd399eb0
commit 818e1835d7
3 changed files with 21 additions and 15 deletions

View file

@ -51,7 +51,6 @@ ethosu_buffer_map(struct pipe_context *pctx,
struct ethosu_screen *screen = ethosu_screen(pctx->screen);
struct ethosu_resource *rsc = ethosu_resource(prsc);
struct drm_ethosu_bo_wait bo_wait = {0};
struct drm_ethosu_bo_mmap_offset bo_mmap_offset = {0};
int ret;
assert(level == 0);
@ -75,20 +74,9 @@ ethosu_buffer_map(struct pipe_context *pctx,
if (ret == -1)
goto free_transfer;
bo_mmap_offset.handle = rsc->handle;
ret = drmIoctl(screen->fd, DRM_IOCTL_ETHOSU_BO_MMAP_OFFSET, &bo_mmap_offset);
if (ret == -1)
goto free_transfer;
uint8_t *map = os_mmap(NULL, prsc->width0, PROT_READ | PROT_WRITE, MAP_SHARED,
screen->fd, bo_mmap_offset.offset);
assert(map != MAP_FAILED);
if (map == MAP_FAILED)
goto free_transfer;
*out_transfer = transfer;
return map + box->x;
return (uint8_t *)rsc->map + box->x;
free_transfer:
pipe_resource_reference(&transfer->resource, NULL);
@ -167,8 +155,23 @@ ethosu_resource_create(struct pipe_screen *pscreen,
rsc->handle = arg.handle;
struct drm_ethosu_bo_mmap_offset bo_mmap_offset = {0};
bo_mmap_offset.handle = rsc->handle;
ret = drmIoctl(screen->fd, DRM_IOCTL_ETHOSU_BO_MMAP_OFFSET, &bo_mmap_offset);
if (ret < 0)
goto close_bo;
rsc->map = os_mmap(NULL, rsc->bo_size, PROT_READ | PROT_WRITE, MAP_SHARED,
screen->fd, bo_mmap_offset.offset);
if (rsc->map == MAP_FAILED)
goto close_bo;
return &rsc->base;
close_bo: {
struct drm_gem_close close_arg = { .handle = rsc->handle };
drmIoctl(screen->fd, DRM_IOCTL_GEM_CLOSE, &close_arg);
}
free_rsc:
ralloc_free(rsc);
return NULL;
@ -183,6 +186,8 @@ ethosu_resource_destroy(struct pipe_screen *pscreen,
struct drm_gem_close arg = {0};
int ret;
os_munmap(rsc->map, rsc->bo_size);
arg.handle = rsc->handle;
ret = drmIoctl(screen->fd, DRM_IOCTL_GEM_CLOSE, &arg);

View file

@ -79,9 +79,8 @@ struct ethosu_resource {
struct pipe_resource base;
uint32_t handle;
uint64_t phys_addr;
uint64_t obj_addr;
uint64_t bo_size;
void *map;
};
static inline struct ethosu_resource *

View file

@ -233,6 +233,7 @@ ethosu_ml_subgraph_create(struct pipe_context *pcontext,
if (subgraph->coefs_used > 0) {
subgraph->coefs_rsrc = pipe_buffer_create(pscreen, 0, PIPE_USAGE_DEFAULT, subgraph->coefs_used);
assert(subgraph->coefs_rsrc != NULL);
pipe_buffer_write(subgraph->base.context, subgraph->coefs_rsrc, 0, subgraph->coefs_used, subgraph->coefs);
free(subgraph->coefs);
@ -248,6 +249,7 @@ ethosu_ml_subgraph_create(struct pipe_context *pcontext,
}
subgraph->io_rsrc = pipe_buffer_create(pscreen, 0, PIPE_USAGE_DEFAULT, subgraph->io_used);
assert(subgraph->io_rsrc != NULL);
return &subgraph->base;
}