)
从 C 到 RustGDEV GPU 运行时移植纪实在 QEMU 环境中进行测试背景前四阶段的翻译工作已全部完成31 文件10,300 行 Rust196 个纯软件测试通过并在开发机上成功编译出libgdev_layer4.so。但开发机glibc 2.33与目标 QEMU 环境CentOS 7glibc 2.17的 ABI 差异在第一次部署时暴露了一系列链接与运行时错误在此期间由于测试环境不方便我将模拟器放到了本机上整理方便agent能理解的仅用于编译测试的环境用的时间比较多目前是nfs挂载源码到qemu上实现同步改动然后qemu上进行编译环境和测试题并测试最后让agent理解该测试流程之后开始正式调试launch。glibc 版本将开发机上编译的.so替换进 QEMU 后编译 C 测试程序时立即报错undefined reference tofstat64GLIBC_2.33 undefined reference topthread_key_createGLIBC_2.34原因是 Rust 标准库在编译时锁定了宿主 glibc 的高版本符号。尝试用.symver汇编技巧创建兼容库libglibc_compat.so虽然在链接阶段通过了但运行时动态链接器ld.so直接拒绝加载—— ELF 头部DT_VERNEED字段明确要求GLIBC_2.34版本检查失败进程直接终止。最终解在 QEMU 虚拟机CentOS 7内安装 Rust 1.72将整个gdev-rust工程上传本地cargo build --release。产出的.so天然链接 glibc 2.17彻底消除了所有版本兼容问题。设备计数编译通过后运行./user_test立刻段错误[rootqemu-ai-ep launch2]# ./user_testsize0x10000, dev_num0fil[1013.290821]user_test[1741]: segfault at 7ffdf92ff000ip00007f15e0165c9b sp 00007ffdf92fe578 error 4e size211762inlibc-2.17.so[7f15e00d10001c3000]dev count0--- -----cubin0x7f15e110a010------- Segmentation faultQEMU 里明明有四个 aicard 设备节点/dev/aicard0~aicard3但sdInit()内部调用gdev_count()始终返回 0。根因原翻译的gdev_count()只统计了“已调用gopen()的槽位”而系统启动时还没有任何进程打开设备槽位全空自然返回 0。修复将gdev_count()的实现改为用stat()系统调用直接探测/dev/aicard0、aicard1等设备文件是否存在。与原始 C 代码中gdev_getinfo_device_count()的行为保持一致。改动仅一行逻辑dev count立刻正确输出 4。[rootqemu-ai-ep launch2]# ./user_test -s 0x10000 -d 0size0x10000, dev_num0filesize211762dev count4--------cubin0x7f915e5c2010-------缺少设备句柄导致内存分配失败设备计数正确后接着报错Sdaa runtime errorinline104offilelaunch.c:sdaaErrorOutOfMemory错误链sdaaMalloc→sd_mem_alloc→sd_ctx_get_current()找不到上下文 → 句柄为 0 →gmalloc(0, size)必然失败。根因enumerate_devices()只做了设备计数stat但从没有调用gopen()真正打开设备并获取内核句柄。没有句柄任何内存分配都无法和内核通信。短期方案为加快调试节奏暂时采用纯软件模拟——实现一个软件后备路径将设备内存操作全部重定向到 Rust 的HashMapu64, Vecu8中。这样一来所有memcpy HtoD/DtoH/DtoD都在软件层完成launch也直接在 CPU 上解析参数块并执行向量加法。测试结果[rootqemu-ai-ep launch2]# ./user_testsize0x10000, dev_num0filesize211762[DEBUG]enumerate_devices: entering[DEBUG]enumerate_devices: calling sd_init(0)[DEBUG]enumerate_devices: rawcount4[DEBUG]enumerate_devices:minor0gopen→handle0x1[DEBUG]enumerate_devices:minor1gopen→handle0x2[DEBUG]enumerate_devices:minor2gopen→handle0x3[DEBUG]enumerate_devices:minor3gopen→handle0x4[DEBUG]enumerate_devices: opened4handles[DEBUG]enumerate_devices: sd_ctx_create(0,0)→11[DEBUG]enumerate_devices: done,count4dev count4--------cubin0x7f2934e2c010-------[DEBUG]register_fat_binary:ptr0x7ffd06c389e0nameunnamed[DEBUG]register_fat_binary: about to lock_runtime[DEBUG]register_fat_binary: locked[DEBUG]register_fat_binary: handleassigned0[DEBUG]register_fat_binary: about toread4096bytes from ptr[DEBUG]register_fat_binary:cubin_data.len4096[DEBUG]register_fat_binary:handle0x0[DEBUG]register_function:handle0x0nameadd_test[DEBUG]register_function: registered,kernels.len1[DEBUG]malloc:size0x10000,device_count4,handles.len4[DEBUG]malloc: usinghandle0x1[DEBUG]malloc: gmalloc→addr0x61000100c000[DEBUG]malloc:size0x10000,device_count4,handles.len4[DEBUG]malloc: usinghandle0x1[DEBUG]malloc: gmalloc→addr0x61000101c000[DEBUG]malloc:size0x10000,device_count4,handles.len4[DEBUG]malloc: usinghandle0x1[DEBUG]malloc: gmalloc→addr0x61000102c000[DEBUG]memcpy:dst0x61000100c000src0x2517010count65536kindHostToDevice[DEBUG]memcpy: usinghandle0x1[DEBUG]memcpy:oktrue[DEBUG]memcpy:dst0x61000101c000src0x2527020count65536kindHostToDevice[DEBUG]memcpy: usinghandle0x1[DEBUG]memcpy:oktrue[DEBUG]launch:entryadd_test[DEBUG]launch:kernel_registeredtrue[DEBUG]launch:handle0x1param_size32[DEBUG]launch: glaunch→oktruekid0[DEBUG]launch SW:A0x61000100c000B0x61000101c000C0x61000102c000n16384[DEBUG]launch SW: wrote65536bytes toC0x61000102c000 launch_sync time:0.292000[DEBUG]memcpy:dst0x2537030src0x61000102c000count65536kindDeviceToHost[DEBUG]memcpy: usinghandle0x1[DEBUG]memcpy:oktrue[DEBUG]free:ptr0x61000102c000[DEBUG]free: gfree→Ok(65536)[DEBUG]free:ptr0x61000101c000[DEBUG]free: gfree→Ok(65536)[DEBUG]free:ptr0x61000100c000[DEBUG]free: gfree→Ok(65536)Test passed: size0x10000, dev_num0全链路在无硬件的纯软件模拟下跑通——证明四层翻译的调度、内存管理、参数打包、错误传播逻辑都是正确的。未完成的工作软件测试虽然通过但数据根本没有进入 aicard 硬件。真正驱动 GPU 需要将 C 源码gdev_aidev.c297 行中的 19 个硬件后端函数翻译为 Rust 并注册到GdevCompute的函数指针表里。同时部分对外 API 在翻译中为了快速闭环被临时设为 stub返回“未实现”。现将未完成部分统计如下1. 公开 API 层的 stub16 个这些函数在外部调用时会得到SDAA_ERROR_NOT_YET_IMPLEMENTED不影响核心 launch/memcpy 流程#所属阶段函数原因1-3Layer2gipc_get_mem_handle, gipc_open_mem_handle, gipc_close_mem_handle跨进程共享内存4Layer3sd_func_get_attributeC 代码原就是 weak stub5-7Layer4device_synchronize, thread_synchronize, set_device_limit全局同步 / 平台特定8-9Layer4host_register, host_unregistermmap 固定页10-12Layer4ipc_get/open/close_mem_handle跨进程句柄13Layer4print_info设备 print buffer14-16Layer4trans_encode, trans_decode, transformerTransformer 推理占比365 个总 API 函数中16 个 stub4.4%全部位于非核心路径。2. GdevCompute 函数指针11 个未实现这 19 个函数指针是“硬件会话”的真正执行者。每次glaunch、gmemcpy最终都要通过它们操作 ring buffer 和 ioctl。目前状态状态函数说明✅ 已实现 (8)launch, fence_read, fence_write, fence_reset, memcpy, memcpy_async, init, load核心启动、DMA、fence❌ 未实现 (11)event_read, event_read_timestamp, event_write, event_reset, swait_event, printbuffer, transencode, transdecode, transformer, membar, notify_intr, memset事件、调试、Transformer 等已实现的 8 个覆盖了最小可用集launch memcpy fence 同步但要完整运行 QEMU 中的 C 测试样例还需要补全事件event相关的 5 个函数目前这8个还有待考证需要在qemu环境下进一步测试。