From e28129350862c972ccab920deb9a4ad0201a1e36 Mon Sep 17 00:00:00 2001 From: Asahi Lina Date: Tue, 3 Dec 2024 03:58:00 +0900 Subject: [PATCH] asahi: Virt UABI update Support timestamp extensions & fix a bunch of missing/broken things we were dragging along. Signed-off-by: Asahi Lina Part-of: --- src/asahi/lib/agx_device_virtio.c | 160 ++++++++++++++++++++++++++---- src/asahi/lib/asahi_proto.h | 31 +++--- 2 files changed, 160 insertions(+), 31 deletions(-) diff --git a/src/asahi/lib/agx_device_virtio.c b/src/asahi/lib/agx_device_virtio.c index 9d785eafd55..a0f06a4ce3f 100644 --- a/src/asahi/lib/agx_device_virtio.c +++ b/src/asahi/lib/agx_device_virtio.c @@ -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 diff --git a/src/asahi/lib/asahi_proto.h b/src/asahi/lib/asahi_proto.h index 577f701395e..36000d79eb5 100644 --- a/src/asahi/lib/asahi_proto.h +++ b/src/asahi/lib/asahi_proto.h @@ -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;