|东京大学版一生一芯:自制CPU,成功运行类Unix系统( 三 )


另外 , 在一月中旬 , 我们也开始努力通过注释掉各个部分来编译 Xv6 的整体代码 。 结果是在我们自制架构的模拟器上 , Xv6 在引导顺序中显示出了第一条消息:
xv6...cpu0: starting...与此同时 , 这意味着这时候 Ucc 已经成长到足以编译大部分 Xv6 代码了 。 真是太棒了!
二月:我们的 CPU GAIA 诞生!
在 MIPS 移植过程中 , 我完成了 PIC 的初始化 , 这个过程很痛苦 。 另外 , 我还完成了实现中断处理程序的任务 。 结果 , Xv6 向 MIPS 的移植工作刚完成 , 第一个用户程序就开始开发了 。
在这一经历的基础上 , 我为我们的自制 CPU 编写了中断和虚拟地址转译的规范草稿 。 为了简单 , 我们决定忽略 Ring 保护等硬件特权机制 。 至于虚拟地址转译 , 我们决定使用 x86 那样的硬件页面游走法(hardware page-walking method) 。 看起来可能很难在硬件中实现这个功能 , 但我们认为如果我们牺牲掉速度并忽视 TLB 实现 , 可能就不会那么难 。 毕竟 Yuichi 后来做了一个很棒的 CPU 内核 , 不过它一开始就安装了 TLB 。
Yuichi 完成了我们的 CPU 的 ISA(指令集架构)的整体设计 。 他将我们的 CPU 命名为 GAIA 。 在典型的 CPU 实验项目中 , 我们既不会实现中断 , 也不会实现 MMU 。 但是 , Yuichi 开始为 Xv6 实现它们 , 他是基于第 3 组的 CPU 的重构版本开发的 。
接下来 , 进度加快了 , 所以我将开始按周进行说明 。
第一周
Masayoshi 开始为我们的 CPU 实现真正的初始化 , 而不只是将引导顺序注释掉;而 Shohei 将 Xv6 的 x86 汇编重写进了我们自制的架构中 。 我为我们的模拟器添加了中断模拟 , 而这个模拟器是 Wataru 在 CPU 实验的核心任务部分开发的;另外我还完成了对虚拟地址转译的支持 。 这能让模拟器有足够的功能来运行 OS 。
第二周
我为我们的架构构建了一个原语链接器 , 以集成 Xv6 及其 binary blobs 。 Shohei 正在实现中断处理程序 , 这部分很难 。 中断很难理解 , 难以弄清流程、难以调试、难以开发 。
当我将 Xv6 移植到 MIPS 时 , 我有 GDB , 所以还能应付 , 但我们自己的模拟器没有任何调试功能 , 所以调试起来肯定非常难 。
Shohei 也顶不住这样的难度 , 所以他为模拟器添加了一个反汇编器和调试 dump 函数 。 之后 , OS 团队又对这个模拟器的调试功能进行了快速升级 , 最后得到的模拟器看起来是这样 。
|东京大学版一生一芯:自制CPU,成功运行类Unix系统
本文插图
第三周
克服了许多困难之后 , Xv6 的移植工作有所进展 , 但 Xv6 还是无法工作 。
尤其是 Ucc 的规范为 char 和 int 都是 32 位 , 这带来了许多问题 。 这不是 Ucc 的错 。 事实上 , C 规范仅要求 sizeof(char) == 1 且 sizeof(char) <= sizeof(int) , 因此这是符合规范的 。
但是 , Xv6 是为 x86 编写的 , 所以它假设 sizeof(int) == 4 并会将常量添加到指针的值 , 这会导致大量不一致 。 由这个问题带来的漏洞很难查找 , 而且数量也很多 , 所以最后我们决定将 Ucc 的 char 规范改为 8 位 。
在将 char 32 位问题委托给 Ucc 团队之后 , 我为首次进入阶段写了初始化页面 , 并尝试通过试错方法让中断能够有效工作 。
最重要的是 , 我们努力解决了第 4 个难题:Xv6 的可移植性差 。
2 月 27-28 日
当我回头看 Slack 时 , 我发现这一天我们进展颇丰 。 在 Ucc 团队很快完成将 char 改为 8 位的工作之后 , 我们进行了大量调试 。 最后 , 我们的第一个用户程序 init 可以工作了!
之后 , 我们在移植用户过程应用方面的成果越来越多 , 这是我在移植到 MIPS 时没有做过的事情 。 在这个过程中 , 很多漏洞都很难重现 , 中断规范之中的不足之处也显现了出来 , 但我们最终克服了困难 , 找到并修复了这些漏洞 。