Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

第三周周报(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 等满足边约束的稳定顺序。
  • 定义 K3SchedulerOps trait(copy_from_user、map_user_to_kernel 等)和 K3DmaAllocator trait(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 指令路径需要工具链支持),但数据结构、接口和调度流程已经可以在本地跑通。

后续工作

  1. V 扩展上下文支持:在 Starry 的任务上下文切换中补齐 vector 寄存器的保存/恢复,这是 K3 AI 指令执行的前置条件。
  2. K3 板级驱动补完:SD 卡驱动和 GMAC 网卡驱动。
  3. 调度器第二阶段:在拓扑排序的基础上加入实际的多核心路由决策,结合负载和核心类型做任务分发。
  4. AI thread 类型控制面:将 X100/A100 核心类型语义完整带入 Starry 调度路径。