第三周周报(6.16-6.22)
本周工作集中在两条线:StarryOS 的 K3 板级适配(目标是让 Starry 能在 K3 真板上启动到 shell)和 AI 运行时的内核驱动与用户态算子库继续推进。
本周工作概览
本周完成了五件事:
- 完成 K3 板级 UFS 驱动,对照 Linux 参考实现逐段翻译为 Rust,StarryOS 成功在 K3 真板上进入 shell。
- 确认 K3 板级其余存储/网络基础设施缺口(SD 卡驱动、GMAC 网卡驱动),验证分区表和刷写流程。
- 根据 K3 HMP 文档在内核中创建
/proc/set_ai_thread接口,实现对 AI 线程的核心亲和性控制。 - 完成用户态运行时 UABI 层的统一重构,建立
k3_aiUabi作为内核-用户态接口的唯一真源。 - 实现 AI 调度器基本框架,完成 DAG 到直链的拓扑解析,并在
k3_test中用 2x5 矩阵乘法通路做真实数据验证。
StarryOS K3 板级适配
本周板级适配的核心是让 StarryOS 摆脱纯内存文件系统的限制,能够从 UFS 存储介质加载 rootfs。
分区表与镜像制备
K3 开发板的镜像结构需要遵循官方 Yocto BSP 中定义的分区表。具体路径在官方 Yocto 源码的 partition_universal.json 中给出。由于板子上已存在原厂 UFS 镜像,本次只刷写 rootfs 分区,将 Starry 构建产物中的 rootfs-riscv64-alpine.img 写入选定分区。
- 注意! 在spacemit yocto的readme中指出,blk sd设备需使用partition_universal格式的布局,如果需要全面重刷切勿刷错
UFS 驱动实现
UFS 驱动是本周围绕 K3 板级投入最大的单项工作。K3 使用 JEDEC UFS 2.1 存储方案,驱动需要处理 UFSHCI 寄存器、UIC 层(DME_SET / DME_LINK_STARTUP)、MPHY 上电序列以及 UTP 传输请求列表的管理。
实现策略是严格对照 Linux 主线 ufs-spacemit.c 的实现逐段翻译为 Rust。
由于驱动体量较大,采用了 AI 辅助对照翻译的协作方式:以 Linux 版本为唯一参考,逐段翻译并保持寄存器定义、初始化和命令提交流程的严格对应。这样可以让我将精力集中在后续 AI 运行时本身的开发上。
当前板级状态
- UFS 驱动:已完成,StarryOS 在 K3 板上成功进入 shell。
- SD 卡驱动(SDHCI):开发中。
- GMAC 网卡驱动:开发中。
上板测试中还有一个重要发现:Starry 当前在任务上下文保存时,还没有考虑 RISC-V V 扩展的 vector 寄存器保存/恢复。而 K3 的 X100/A100 IME 扩展指令都以 V 扩展为基础,这意味着在 Starry 上使用 AI 指令之前,必须先补齐 V 扩展的上下文支持。
AI 运行时内核驱动
/proc/set_ai_thread 接口
根据 K3 HMP 说明文档,Linux 侧通过 /proc/set_ai_thread 把线程标记为 AI 类型,再由内核将其约束到 A100 核心集合上运行。这是因为 X100 和 A100 的向量宽度(VLEN)不同,线程一旦开始使用对应类型的向量状态,就不能再跨类型迁移。
本周在 Starry 内核中创建了对等的 /proc/set_ai_thread 接口。实现上与 Linux 参考有一处关键策略差异:我们没有直接死板地把线程亲和性锁在 A100 核心集合上,而是根据实际负载和程序要求动态决定亲和性。
这个决策的主要考量:
- X100 侧同样具备轻量 AI 能力(第一周已确认 X100 cluster 图中标出了 AI 模块),对于小 tensor、低提交开销任务,走 X100 local path 更高效。
- A100 侧适合重型矩阵乘法和 LLM 核心算子,但不意味着所有 AI 任务都应被排他性地路由到 A100。
- 动态策略使调度器能在了解任务规模后做路由决策,而不是在入口就把所有 AI 线程钉死在 A100 上。
注意这一层控制不只是“设置亲和性“,还需要把 X100/A100 的核心类型语义带进调度器,防止已使用某类向量/IME 状态的线程跨到另一类核心上运行。这部分与 V 扩展上下文保存是一体两面的问题,需要后续在调度路径中一并解决,目前暂且认为迁移到a100上的线程不能迁移回x100,但是当线程尝试设置自己为ai线程时会尝试将线程留在x100核心上。
参考:K3 HMP 说明
用户态 AI 运行时重构
本周用户态运行时经历了一次较大的结构调整,核心目标是建立统一的 UABI(User-ABI)层。
k3_aiUabi:统一 UABI 层
将原先分散在 k3_aiRuntime 中的 desc(tensor/kernel 描述符)、graph(计算图)、kernel(算子定义)和 kernelattr(算子属性)模块提升到独立的 k3_aiUabi crate 中。这个 crate 作为内核和用户态之间的接口定义层,两边共用同一套类型。
主要变更:
- MatMulAttr 重新设计,补全 stride 信息。之前的实现将 stride 提取逻辑放在 backend 侧,依赖 TensorView 的形状推断。新的 MatMulAttr 在构造时就携带完整的 lhs/rhs/out 的 row_stride、col_stride 和 batch_stride(以元素为单位),并加入
MAX_STRIDE_BYTE(4GB)上限常量。这样 backend 不再需要理解 tensor 布局,只管按属性执行。 - 新增
AiRuntimeErr、SchedulerErr、BackendErr三级错误类型,替换各 crate 中散落的io::Result、Result<(), ()>和i32错误码。现在错误从 backend → scheduler → runtime 有统一的类型传递路径。 k3_aiRuntime和k3_kernel_backend同步迁移到新的 UABI 类型。
k3_aiScheduler:调度器框架
调度器本周从占位骨架推进到可工作的最小原型:
- 完成
GraphScheduler的基本操作:new、take_task、push_task。 - 实现
run_graph:按节点迭代执行,带调试日志输出(op 类型、tensor 信息、形状)。 - 完成 DAG 到直链的拓扑解析(
resolve_parsed_graph)。阶段一先按稳定拓扑序把所有节点收成一条TaskLink直链:入度为 0 的节点入 ready 队列,按 node id 自然序出队,完成后减少后继入度,重复到图空。这样a→b, c→b会解析为a→c→b等满足边约束的稳定顺序。 - 定义
K3SchedulerOpstrait(copy_from_user、map_user_to_kernel等)和K3DmaAllocatortrait(alloc_dma、cache 操作),作为调度器与 OS 层的接口契约。后续在不同 OS(StarryOS / Linux)上只需要实现这些 trait。
k3_test:真实数据通路验证(在qemu上用cpu纯算)
k3_test 从上一周的共享内存保活验证升级为 2x5 矩阵乘法通路测试:
- 构造 lhs 矩阵
[[1,2,3], [4,5,6]](2x3)。 - 构造 rhs 为 3x5 单位矩阵。
- 构造完整的 MatMulAttr(含所有 stride 字段),通过调度器链路提交执行。
- 打印结果验证计算正确性。
这个测试打通了 UABI → Runtime → Scheduler → Backend 的完整调用链路,虽然 backend 的 matmul 目前还是 CPU 软件实现(IME 指令路径需要工具链支持),但数据结构、接口和调度流程已经可以在本地跑通。
后续工作
- V 扩展上下文支持:在 Starry 的任务上下文切换中补齐 vector 寄存器的保存/恢复,这是 K3 AI 指令执行的前置条件。
- K3 板级驱动补完:SD 卡驱动和 GMAC 网卡驱动。
- 调度器第二阶段:在拓扑排序的基础上加入实际的多核心路由决策,结合负载和核心类型做任务分发。
- AI thread 类型控制面:将 X100/A100 核心类型语义完整带入 Starry 调度路径。