asahi: Virt UABI update

Support timestamp extensions & fix a bunch of missing/broken things we
were dragging along.

Signed-off-by: Asahi Lina <lina@asahilina.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32759>
This commit is contained in:
Asahi Lina 2024-12-03 03:58:00 +09:00 committed by Marge Bot
parent 0d5db3238b
commit e281293508
2 changed files with 160 additions and 31 deletions

View file

@ -88,6 +88,7 @@ agx_virtio_bo_alloc(struct agx_device *dev, size_t size, size_t align,
return NULL;
}
/* Note: optional, can zero out for not mapping for sparse */
req.addr = va->addr;
req.blob_id = blob_id;
req.vm_id = dev->vm_id;
@ -123,28 +124,86 @@ agx_virtio_bo_bind(struct agx_device *dev, struct agx_bo *bo, uint64_t addr,
size_t size_B, uint64_t offset_B, uint32_t flags,
bool unbind)
{
assert(offset_B == 0 && "TODO: need to extend virtgpu");
struct asahi_ccmd_gem_bind_req req = {
.op = unbind ? ASAHI_BIND_OP_UNBIND : ASAHI_BIND_OP_BIND,
.flags = flags,
.vm_id = dev->vm_id,
.res_id = bo->vbo_res_id,
.size = size_B,
.addr = addr,
.hdr.cmd = ASAHI_CCMD_GEM_BIND,
.hdr.len = sizeof(struct asahi_ccmd_gem_bind_req),
};
.bind = {
.op = unbind ? ASAHI_BIND_OP_UNBIND : ASAHI_BIND_OP_BIND,
.flags = flags,
.vm_id = dev->vm_id,
.handle = bo->vbo_res_id,
.offset = offset_B,
.range = size_B,
.addr = addr,
}};
int ret = vdrm_send_req(dev->vdrm, &req.hdr, false);
if (ret) {
fprintf(stderr, "DRM_IOCTL_ASAHI_GEM_BIND failed: %d (handle=%d)\n", ret,
fprintf(stderr, "ASAHI_CCMD_GEM_BIND failed: %d (handle=%d)\n", ret,
bo->handle);
}
return ret;
}
static int
agx_virtio_bo_bind_object(struct agx_device *dev, struct agx_bo *bo,
uint32_t *object_handle, size_t size_B,
uint64_t offset_B, uint32_t flags)
{
struct asahi_ccmd_gem_bind_object_req req = {
.hdr.cmd = ASAHI_CCMD_GEM_BIND_OBJECT,
.hdr.len = sizeof(struct asahi_ccmd_gem_bind_object_req),
.bind = {
.op = ASAHI_BIND_OBJECT_OP_BIND,
.flags = flags,
.vm_id = 0,
.handle = bo->vbo_res_id,
.offset = offset_B,
.range = size_B,
}};
struct asahi_ccmd_gem_bind_object_rsp *rsp;
rsp = vdrm_alloc_rsp(dev->vdrm, &req.hdr,
sizeof(struct asahi_ccmd_gem_bind_object_rsp));
int ret = vdrm_send_req(dev->vdrm, &req.hdr, true);
if (ret || rsp->ret) {
fprintf(stderr,
"ASAHI_CCMD_GEM_BIND_OBJECT bind failed: %d:%d (handle=%d)\n", ret, rsp->ret,
bo->handle);
}
if (!rsp->ret)
*object_handle = rsp->object_handle;
return rsp->ret;
}
static int
agx_virtio_bo_unbind_object(struct agx_device *dev, uint32_t object_handle,
uint32_t flags)
{
struct asahi_ccmd_gem_bind_object_req req = {
.hdr.cmd = ASAHI_CCMD_GEM_BIND_OBJECT,
.hdr.len = sizeof(struct asahi_ccmd_gem_bind_object_req),
.bind = {
.op = ASAHI_BIND_OBJECT_OP_UNBIND,
.flags = flags,
.object_handle = object_handle,
}};
int ret = vdrm_send_req(dev->vdrm, &req.hdr, false);
if (ret) {
fprintf(stderr,
"ASAHI_CCMD_GEM_BIND_OBJECT unbind failed: %d (handle=%d)\n", ret,
object_handle);
}
return 0;
}
static void
agx_virtio_bo_mmap(struct agx_device *dev, struct agx_bo *bo)
{
@ -167,16 +226,22 @@ agx_virtio_get_params(struct agx_device *dev, void *buf, size_t size)
};
struct asahi_ccmd_get_params_rsp *rsp;
rsp =
vdrm_alloc_rsp(vdrm, &req.hdr, sizeof(struct asahi_ccmd_get_params_rsp));
rsp = vdrm_alloc_rsp(vdrm, &req.hdr,
sizeof(struct asahi_ccmd_get_params_rsp) + size);
int ret = vdrm_send_req(vdrm, &req.hdr, true);
if (ret)
goto out;
if (rsp->virt_uabi_version != ASAHI_PROTO_UNSTABLE_UABI_VERSION) {
fprintf(stderr, "Virt UABI mismatch: Host %d, Mesa %d\n",
rsp->virt_uabi_version, ASAHI_PROTO_UNSTABLE_UABI_VERSION);
return -1;
}
ret = rsp->ret;
if (!ret) {
memcpy(buf, &rsp->params, size);
memcpy(buf, &rsp->payload, size);
return size;
}
@ -184,6 +249,18 @@ out:
return ret;
}
static void
agx_virtio_serialize_attachments(char **ptr, uint64_t attachments,
uint32_t count)
{
if (!count)
return;
size_t attachments_size = sizeof(struct drm_asahi_attachment) * count;
memcpy(*ptr, (char *)(uintptr_t)attachments, attachments_size);
*ptr += attachments_size;
}
static int
agx_virtio_submit(struct agx_device *dev, struct drm_asahi_submit *submit,
struct agx_submit_virt *virt)
@ -199,8 +276,18 @@ agx_virtio_submit(struct agx_device *dev, struct drm_asahi_submit *submit,
for (int i = 0; i < submit->command_count; i++) {
switch (commands[i].cmd_type) {
case DRM_ASAHI_CMD_COMPUTE: {
struct drm_asahi_cmd_compute *compute =
(struct drm_asahi_cmd_compute *)(uintptr_t)commands[i].cmd_buffer;
req_len += sizeof(struct drm_asahi_command) +
sizeof(struct drm_asahi_cmd_compute);
req_len += compute->attachment_count *
sizeof(struct drm_asahi_attachment);
if (compute->extensions) {
assert(*(uint32_t *)(uintptr_t)compute->extensions ==
ASAHI_COMPUTE_EXT_TIMESTAMPS);
req_len += sizeof(struct drm_asahi_cmd_compute_user_timestamps);
}
break;
}
@ -211,6 +298,14 @@ agx_virtio_submit(struct agx_device *dev, struct drm_asahi_submit *submit,
sizeof(struct drm_asahi_cmd_render);
req_len += render->fragment_attachment_count *
sizeof(struct drm_asahi_attachment);
req_len += render->vertex_attachment_count *
sizeof(struct drm_asahi_attachment);
if (render->extensions) {
assert(*(uint32_t *)(uintptr_t)render->extensions ==
ASAHI_RENDER_EXT_TIMESTAMPS);
req_len += sizeof(struct drm_asahi_cmd_render_user_timestamps);
}
break;
}
@ -241,14 +336,39 @@ agx_virtio_submit(struct agx_device *dev, struct drm_asahi_submit *submit,
commands[i].cmd_buffer_size);
ptr += commands[i].cmd_buffer_size;
if (commands[i].cmd_type == DRM_ASAHI_CMD_RENDER) {
switch (commands[i].cmd_type) {
case DRM_ASAHI_CMD_RENDER: {
struct drm_asahi_cmd_render *render =
(struct drm_asahi_cmd_render *)(uintptr_t)commands[i].cmd_buffer;
size_t fragments_size = sizeof(struct drm_asahi_attachment) *
render->fragment_attachment_count;
memcpy(ptr, (char *)(uintptr_t)render->fragment_attachments,
fragments_size);
ptr += fragments_size;
agx_virtio_serialize_attachments(&ptr, render->vertex_attachments,
render->vertex_attachment_count);
agx_virtio_serialize_attachments(&ptr, render->fragment_attachments,
render->fragment_attachment_count);
if (render->extensions) {
struct drm_asahi_cmd_render_user_timestamps *ext =
(struct drm_asahi_cmd_render_user_timestamps *)(uintptr_t)
render->extensions;
assert(!ext->next);
memcpy(ptr, (void *)ext, sizeof(*ext));
ptr += sizeof(*ext);
}
break;
}
case DRM_ASAHI_CMD_COMPUTE: {
struct drm_asahi_cmd_compute *compute =
(struct drm_asahi_cmd_compute *)(uintptr_t)commands[i].cmd_buffer;
agx_virtio_serialize_attachments(&ptr, compute->attachments,
compute->attachment_count);
if (compute->extensions) {
struct drm_asahi_cmd_compute_user_timestamps *ext =
(struct drm_asahi_cmd_compute_user_timestamps *)(uintptr_t)
compute->extensions;
assert(!ext->next);
memcpy(ptr, (void *)ext, sizeof(*ext));
ptr += sizeof(*ext);
}
break;
}
}
}
@ -296,6 +416,8 @@ const agx_device_ops_t agx_virtio_device_ops = {
.bo_mmap = agx_virtio_bo_mmap,
.get_params = agx_virtio_get_params,
.submit = agx_virtio_submit,
.bo_bind_object = agx_virtio_bo_bind_object,
.bo_unbind_object = agx_virtio_bo_unbind_object,
};
bool

View file

@ -7,6 +7,8 @@
#ifndef ASAHI_PROTO_H_
#define ASAHI_PROTO_H_
#define ASAHI_PROTO_UNSTABLE_UABI_VERSION 1
/**
* Defines the layout of shmem buffer used for host->guest communication.
*/
@ -37,12 +39,13 @@ enum asahi_ccmd {
ASAHI_CCMD_GEM_NEW,
ASAHI_CCMD_GEM_BIND,
ASAHI_CCMD_SUBMIT,
ASAHI_CCMD_GEM_BIND_OBJECT,
};
#define ASAHI_CCMD(_cmd, _len) \
(struct vdrm_ccmd_req) \
{ \
.cmd = ASAHI_CCMD_##_cmd, .len = (_len), \
#define ASAHI_CCMD(_cmd, _len) \
(struct vdrm_ccmd_req) \
{ \
.cmd = ASAHI_CCMD_##_cmd, .len = (_len), \
}
/*
@ -90,7 +93,8 @@ DEFINE_CAST(vdrm_ccmd_req, asahi_ccmd_get_params_req)
struct asahi_ccmd_get_params_rsp {
struct vdrm_ccmd_rsp hdr;
int32_t ret;
struct drm_asahi_params_global params;
uint32_t virt_uabi_version;
uint8_t payload[];
};
struct asahi_ccmd_gem_new_req {
@ -106,18 +110,20 @@ DEFINE_CAST(vdrm_ccmd_req, asahi_ccmd_gem_new_req)
struct asahi_ccmd_gem_bind_req {
struct vdrm_ccmd_req hdr;
uint32_t op;
uint32_t flags;
uint32_t vm_id;
uint32_t res_id;
uint64_t size;
uint64_t addr;
struct drm_asahi_gem_bind bind;
};
DEFINE_CAST(vdrm_ccmd_req, asahi_ccmd_gem_bind_req)
struct asahi_ccmd_gem_bind_rsp {
struct asahi_ccmd_gem_bind_object_req {
struct vdrm_ccmd_req hdr;
struct drm_asahi_gem_bind_object bind;
};
DEFINE_CAST(vdrm_ccmd_req, asahi_ccmd_gem_bind_object_req)
struct asahi_ccmd_gem_bind_object_rsp {
struct vdrm_ccmd_rsp hdr;
int32_t ret;
uint32_t object_handle;
};
#define ASAHI_EXTRES_READ 0x01
@ -130,6 +136,7 @@ struct asahi_ccmd_submit_res {
struct asahi_ccmd_submit_req {
struct vdrm_ccmd_req hdr;
uint32_t flags;
uint32_t queue_id;
uint32_t result_res_id;
uint32_t command_count;