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);