From 37de5fd8f92565285ec25cdcde599b0cf7ad5354 Mon Sep 17 00:00:00 2001 From: "Arslan R." Date: Sun, 8 Nov 2026 02:10:54 -0300 Subject: [PATCH] asahi: translate the retained G15 wire under virtio The retained G15 kernel speaks the Mesa-751 wire. On the native path, agx_open_device normalizes its feature word and agx_submit repacks every command buffer with agx_g15_wire_pack, but both are skipped under virtio. virglrenderer forwards GET_PARAMS (group 0) and SUBMIT to the same G15 kernel unchanged, so a guest on an M3 sees the raw 0x3e features, fails agx_params_native_kernel_abi_supported, and enumerates no GPU inside muvm. Apply the same normalization under virtio, and translate the command buffer directly into the ccmd payload in agx_virtio_submit; the retained wire is never larger than the canonical input. Mask VM_STATUS and VM_STATUS_MIRROR for virtio guests: virglrenderer rejects param groups other than 0, and hk_check_status and hk_init_vm_status_mirror issue raw GET_PARAMS on the guest fd, which would turn every wait into a device loss. Also check the calloc result in agx_virtio_submit. Tested on a 16" M3 Pro (Mac15,7, G15S) inside muvm 0.7.0 with virglrenderer 1.3.0: aarch64 and x86_64 (via FEX) vulkaninfo now report Apple M3 Pro (G15S B1), and headless vkmark at 1080p passes 13/13 scenes. The native host path is unchanged. Refs: omacom/omarchy#18111 Co-Authored-By: Claude Opus 5.5 --- src/asahi/lib/agx_device.c | 11 +++++++++-- src/asahi/lib/agx_device_virtio.c | 23 ++++++++++++++++++++++- 2 files changed, 31 insertions(+), 3 deletions(-) diff --git a/src/asahi/lib/agx_device.c b/src/asahi/lib/agx_device.c index 1d55f45f4cb7..9757329517be 100644 --- a/src/asahi/lib/agx_device.c +++ b/src/asahi/lib/agx_device.c @@ -933,8 +933,15 @@ agx_open_device(void *memctx, struct agx_device *dev) uint64_t normalized_features; dev->g15_legacy_wire = false; - if (!dev->is_virtio && - agx_g15_wire_features(&dev->params, &normalized_features)) { + if (agx_g15_wire_features(&dev->params, &normalized_features)) { + /* Under virtio the host renderer forwards GET_PARAMS and SUBMIT to the + * same retained G15 kernel, so the guest needs the same feature + * normalization and packet translation. virglrenderer only forwards + * param group 0, and the VM status paths issue raw asahi ioctls on the + * guest fd, so the guest must not advertise them. */ + if (dev->is_virtio) + normalized_features &= ~(uint64_t)(DRM_ASAHI_FEATURE_VM_STATUS | + DRM_ASAHI_FEATURE_VM_STATUS_MIRROR); dev->g15_legacy_wire = true; dev->params.features = normalized_features; } diff --git a/src/asahi/lib/agx_device_virtio.c b/src/asahi/lib/agx_device_virtio.c index 0072120b7010..6c6b44afb7ff 100644 --- a/src/asahi/lib/agx_device_virtio.c +++ b/src/asahi/lib/agx_device_virtio.c @@ -4,7 +4,9 @@ */ #include "agx_device_virtio.h" +#include "agx_g15_wire.h" +#include #include #include @@ -240,6 +242,10 @@ agx_virtio_submit(struct agx_device *dev, struct drm_asahi_submit *submit, struct asahi_ccmd_submit_req *req = (struct asahi_ccmd_submit_req *)calloc(1, req_len); + if (!req) { + errno = ENOMEM; + return -1; + } req->queue_id = submit->queue_id; req->extres_count = virt->extres_count; @@ -247,7 +253,22 @@ agx_virtio_submit(struct agx_device *dev, struct drm_asahi_submit *submit, char *ptr = (char *)&req->payload; - memcpy(ptr, (void *)(uintptr_t)submit->cmdbuf, req->cmdbuf_size); + if (dev->g15_legacy_wire) { + /* The retained G15 wire is never larger than the canonical input, so + * translate straight into the request and shrink it to fit. */ + size_t packed; + if (!agx_g15_wire_pack((void *)(uintptr_t)submit->cmdbuf, + submit->cmdbuf_size, ptr, submit->cmdbuf_size, + &packed)) { + free(req); + errno = EINVAL; + return -1; + } + req->cmdbuf_size = packed; + req_len = sizeof(struct asahi_ccmd_submit_req) + packed + extres_size; + } else { + memcpy(ptr, (void *)(uintptr_t)submit->cmdbuf, req->cmdbuf_size); + } ptr += req->cmdbuf_size; memcpy(ptr, virt->extres, extres_size);