Conversation
099357e to
832d9bc
Compare
|
这个 PR 改动也太大了,我感觉很难 review。有没有更好的分解方式,按照子模块,或者 feature 改进分步进行 PR? 如果正如 PR 上的如下描述改动了 10 个点,这些点看上去是独立的,那也应该要有至少 10 个 PR。
另外为啥要改动,原因请详细列出来,也为我们 review 提供帮助,对于重大修改,PR 描述中至少应该包括:
最后,只验证一个 virt64 恐怕是不够的,对其他产品,这么大的改动一次合入主线能保证其他 RISC-V 产品(特别是 T-head)的 BSP 工作不受影响吗?有没有更好的规划? 总之,我建议小步快跑方式,越是大的改动,越需要谨慎。 |
|
一步步来解释。 首先这个 PR 肯定不会是直接以这样的方式申请合并,上面 更多是希望和相关人员探讨这么改(仅从技术角度讨论)是否可以接受,PR 会一直根据大家的意见进行改进,等到相关依赖都合并,相关验证、重新适配完成,以及大家意见统一为止。 WHY本次提交目的很简单:
根据对已有的操作系统和 RISC-V 目前标准来看,RT-Thread 在 RISC-V 支持上存在技术支持落后,代码维护性差,以及新平台适配没有统一标准等问题,因此根据这些问题提出的解决方案只有重写。 很遗憾,本次 PR 无法再进行拆分,否则将会陷入长期的 Kernel 跟进 BSP -> BSP 跟进 Kernel -> Kernel 跟进 BSP -> 新 BSP 插入 -> 新 BSP 重新支持 等无穷无尽的拉锯战;一次性把问题解决掉、将不积极跟进主线的 BSP 踢掉或者放弃,才是目前让 Kernel 得以快速发展的唯一解。 同时上述提到的各种新的点,仅是对改进的一个总结,并不是说代码真的可以分成这么多个模块,有的模块之间存在依赖,在已有代码基础上拆分提交,(从 AArch64 的统一经验来看)这种工作量就干脆不要搞了。 HOWISA manager interface.增加对目前 RISC-V ISA 位说明,使用位图进行管理,便于代码动态监测 ISA 状况,平台可以自行设置 ISA 支持情况(可参考 Merge 32E/32I/64I.32 位和 64 位只有访存指令,部分浮点数据位长度不一样,其他都是兼容的,因此相关差异用宏进行封装编程就可以,相关文件位于 至于 32E,仅是支持的寄存器更少,在上下文管理中使用 Cache by CBOM ISA.该 ISA 就是标准的 D-Cache 操作,只有 T-Head 平台没支持该 ISA,而且还提供了 DM 版本的 HWCache 支持,Cache 操作完全可以统一,至于 T-Head 平台,Common 中的 Cache 实现均为 weak 声明,T-Head 重新实现相关接口即可。 设备树平台将自动扫描 CPU 节点中 MMU support Sv32/Sv39/Sv48/Sv57/Sv64, SVPBMT ISA.各种页表翻译模式本身就是统一的,只有相关 PTE 位允许厂商自己修改实现,以支持 PMA,NOCACHE,IO 属性,ISA SVPBMT 中已经对前面提到的属性进行了统一,只有 T-Head 平台没支持该 ISA,直接使用 Vendor 声明的 同时对于 MMU 配置,Vendor 可以使用 为了考虑不同平台支持的 Sv 模式不同,提供了 Merge M-mode, S-mode CSR ops.重新提供统一的 CSR 寄存器描述表,其中 M-mode,S-mode 大部分寄存器仅是前缀不一样,使用 Support SMP.这块支持最大的问题就是,CPU ID 的获取。 在其他操作系统上,多任务和多核会非常早启动,其使用了进程中的 CPU 成员来获取 CPU ID,进程的信息存放在 RT-Thread 上的 M-mode 下无 MMU 不能支持 LWP,因此在该模式下, 支持 CPU 身份识别后,对于 SMP 上下文调度支持,参考架构 SMP 移植要求即可。 Support APLIC & IMSIC (AIA), CLIC, ACLINT/CLINT, INTC, PLIC.这个是刚需,这个外设 IP 就是统一的,代码也应该只有一份,对于一些平台有 quirk 的情况,代码里面已经使用 quirk bitmap 管理以支持不同特性的平台。 对于 AIA 架构,要求强制使用 DM 模式,而 CLIC, ACLINT/CLINT, INTC, PLIC 则使用与 DM 版本代码对具体硬件操作进行 API 封装,在 Support DM (only by OFW) or not DM.RISC-V 在其他较先进的 OS 中本身就支持设备树 DM 模式,只要平台支持好 DM 要求的资源管理接口即可。 由于 RISC-V 存在资源紧张的平台,代码重构早期就考虑到了部分代码与 DM 版本共享,以及相关属性使用静态配置的方式实现支持,前面的描述已经讲清楚支持方式。 Merge T-HEAD vendor.T-HEAD 本身大部分硬件特性就是固定的,没必要拆成 C906 和 C908,而且该 Vendor 遵守大部分 ISA,只要保留部分细微的差异即可,前面的描述已经讲清楚支持方式。 Kernel support boot in not CPU#0
RT-Thread 对 CPU#0 依赖的代码很明显,主要是系统 tick 管理,以及 idle 线程的主核心任务,修改相关对 CPU#0 的显示指定即可。 以上的描述可能不够清晰,如果有疑问可以进一步讨论。 |
|
我有如下想法,供大家参考:
所以如果从 kernel 的角度确定无法循序渐进地 pr(即只能一次性 merge),我觉得一种可行的办法就是需要确定与 riscv 相关的需要重点看护的 bsp,至少在 review 过程中做好充分的测试,并保证这些重点看护 bsp 可以基本正常工作后该 pr 才可以合入。 我这里目前维护的 riscv board 有两个:
其他关心这个 PR 的 bsp 有哪些,欢迎补充。 另外,我也看到 PR 说:
所以我理解这个 PR 并没有急着要合入,所以不妨在上面我提的第一个思路,即拉入更多关心此 PR 的 reviewer 基础上,我们在 review 这个 PR 的同时也考虑拆分的问题。我相信经过大家的努力,或许也是有可能拆分的(其实我大概看了一下 作者 上面的详细的描述,感觉有些功能点还是比较独立的,有很大可能性可以拆分出来先提交进 master, 我也有意愿参与这份工作)。 最后顺便提一下,我建议再找一些原先做 libcpu 下的人来一起 review,我参与 rtt 工作以来主要也是在 bsp 上多一些,有些 kenrel 公共部分还希望有更多有经验的人来一起 review。 |
1. ISA manager interface. 2. Merge 32E/32I/64I. 3. Cache by CBOM ISA. 4. MMU support Sv32/Sv39/Sv48/Sv57/Sv64, SVPBMT ISA. 5. Merge M-mode, S-mode CSR ops. 6. Support SMP. 7. Support APLIC & IMSIC (AIA), CLIC, ACLINT/CLINT, INTC, PLIC. 8. Support DM (only by OFW) or not DM. 9. Merge T-HEAD vendor. Signed-off-by: GuEe-GUI <2991707448@qq.com>
1. VirtIO DM (NET, BLK, CONSOLE, RNG, RPMSG, SCSI, GPU, INPUT, CRYPTO). 2. Serial 8250 OFW. 3. MTD-CFI. 4. RTC-Goldfish. 5. ECAM generic PCI. 6. Syscon Reboot and Poweroff. 7. QEMU FW-CFG. 8. RISC-V AIA (APLIC, IMSIC), PLIC, INTC, ACLINT/CLINT. 9. PCI device (WDT, NVME, ATA, SDHCI)... Signed-off-by: GuEe-GUI <2991707448@qq.com>
|
重点看护的 BSP 肯定是要保证正常运行的,这个 PR 显然提交之前也清楚难以一两个人就能 review 好,但是目前据我认识的相关 RISC-V 前维护者已经不在 RT-Thread 社区活跃,如果是这样的话也还有个比较好的办法,那就是先提交到开发分支,在该分支上进行长期(显然时间肯定不会太长,因为近期可能也会有新的 Vendor 和 BSP 引入)的验证和重新适配,最后再变基并一次性合并到主线也可以。 |
也可以,如果能确保你这个 pr 的关联开发分支 https://github.com/GuEe-GUI/rt-thread/tree/next_riscv 不定期 rebase 到最新的 master 就行。 Review 过程中如果发现一些可以单独摘出来的 feature 也可以随时拿出来单独提 pr 先合入 master,然后 next_riscv 继续 rebase 到最新的 master。如此循环几次就可以实现化整为零,分批次提交了。 |
|
pr里提到的功能,比如cbo指令支持、smp功能支持、M mode支持、DM支持这些确实是目前riscv 平台需要实现的,这个pr相当于是对目前riscv平台相关代码的重构。个人同意@unicornx的观点,尽可能将pr内容拆开,cbo指令支持等这些相对独立的功能可以单独merge。我在rtt 5.2.0版本上基于我们的dp1000 平台目前也实现了pr里的部分功能,后续我可以参与该pr的review。 |
|
确定需要把rv32、rv64融合起来?确定以这种方式,后续各个riscv芯片厂商间可以融合在一起,可以统一在一起? |
|
我的小pr 啥时融入 |
理论上可以,涉及到用户态和虚拟内存可能要注意下 |
RTT主线需要维护的RISCV BSP列表32位: 64位: @GuEe-GUI @unicornx @supperthomas 我这边列了一份主线上需要维护的RISCV BSP列表,看下是否还有补充? |
我没有补充,我只是一直没搞明白 |
xuantie下面的都是xuantie的qemu平台,包括xiaohui和smart-l两个BSP,架构会覆盖到C/R/E。 |
|
请对PR进行分离,其中rv32部分请维持原样。 <或者说,带MMU的arch是一类,不带MMU的arch是一类> PR拆细才容易review及合并进来。否则只能找到所有的真机进行一一测试,目前应该没那么多精力顾及到的。 |
|
这块目前还没做完整测试,社区目前对 RV 架构的组成可能还需要进一步确认,因为这个 PR 拆出来不是那么容易的,有些东西是存在耦合的,还有些东西的实现只能是 0 到 1,不能是 0.1,0.2 这样。 |
目前Zephyr上是没有区分RV32和RV64的,大部分应该使用精心设计的宏定义来实现,正好看到这个PR,如果能解决目前RISC-V,Zephyr里面也把标准的 PLIC/CLIC/PMP/TIMER做了统一的API设计,如果能够统一,这样确实对RT-Thread RISC-V支持会更好一些。 |
这个不建议。因为Zephyr并不类似RT-Thread这样有内核态,用户态,而用户态是完全POSIX模式,完全类Linux模式,独立用户态应用程序,包括静态应用程序,动态应用程序。这个时候基本上就是多级页表,用户态全进程地址空间。 |
|
|
||
| int rt_hw_cpu_id(void); | ||
|
|
||
| #ifndef rt_hw_master_cpu_id |
There was a problem hiding this comment.
这里存在问题的,必须需要有/没有这样的宏定义,而不是函数实现。
There was a problem hiding this comment.
那作为 weak 函数也行,就是默认有栈开销,或者你们看是否有其他合适的方式
全志的BSP已经出现问题了,目前build会失败 |
|
请对riscv32进行分离,或者来说,是区分mmu,nommu的情况。 |
|
在这份修改中 no-mmu 和 mmu 版本是同时支持的,也就是系统可以在早期通过动态设置 └─risc-v
├─mcu(always no-mmu)
├─common(mmu and no-mmu)
├─vendor-A
└─vendor-B |
比较好奇,mmu 和 no-mmu 感觉只是一个开关的问题,为啥要做成 mcu 和 common 两个目录,有点违反直觉啊 |
|
因为设备树支持 no-mmu 和 mmu 版本,举个例子: k210: cpus {
#address-cells = <1>;
#size-cells = <0>;
timebase-frequency = <7800000>;
cpu0: cpu@0 {
device_type = "cpu";
compatible = "canaan,k210", "riscv";
reg = <0>;
riscv,isa = "rv64imafdc";
mmu-type = "riscv,none";
i-cache-block-size = <64>;
i-cache-size = <0x8000>;
d-cache-block-size = <64>;
d-cache-size = <0x8000>;
cpu0_intc: interrupt-controller {
#interrupt-cells = <1>;
interrupt-controller;
compatible = "riscv,cpu-intc";
};
};k230: cpus {
#address-cells = <1>;
#size-cells = <0>;
timebase-frequency = <27000000>;
cpu@0 {
compatible = "thead,c908", "riscv";
device_type = "cpu";
reg = <0>;
riscv,isa = "rv64imafdcv_zba_zbb_zbc_zbs_zicbom_zicbop_zicboz_svpbmt";
riscv,isa-base = "rv64i";
riscv,isa-extensions = "i", "m", "a", "f", "d", "c", "v", "zba", "zbb",
"zbc", "zbs", "zicbom", "zicbop", "zicboz",
"zicntr", "zicsr", "zifencei", "zihpm", "svpbmt";
riscv,cbom-block-size = <64>;
riscv,cbop-block-size = <64>;
riscv,cboz-block-size = <64>;
d-cache-block-size = <64>;
d-cache-sets = <128>;
d-cache-size = <32768>;
i-cache-block-size = <64>;
i-cache-sets = <128>;
i-cache-size = <32768>;
next-level-cache = <&l2_cache>;
mmu-type = "riscv,sv39";
cpu0_intc: interrupt-controller {
compatible = "riscv,cpu-intc";
interrupt-controller;
#interrupt-cells = <1>;
};
};上面两个例子,由 |
这是在回答我的问题吗。我的问题是 ”为啥要做成 mcu 和 common 两个目录“ 如果是回答的我的问题,其实我反而更加感觉奇怪了,难道因为设备树要支持 no-mmu 和 mmu 两个版本,内核源码树就要分 mcu 和 common 两个目录?其实我理想中的源码目录 layout 就是: 至于编译出来的内核是否是带 mmu 还是不带 mmu,只是不同编译配置选项使能的结果,源码只有一份。现在是什么原因导致要多一个 mcu 目录出来,是历史原因?有没有改进的可能?我只是想问问这些。因为我直觉上感觉是否有 mmu 只是 cpu 的特性之一,为啥要专门为它搞个 mcu 目录出来? 我理解是不是有些历史原因,请原谅我可能了解的不够,我只是想和大家讨论一下,是否有更好的做法? |
|
上面 @BernardXiong 说了要把 RISC-V32 也拆分了:no-mmu 和 mmu 版本,RISC-V64 之前也是拆分 no-mmu 和 mmu 版本,那既然这样的话,那就是整体要拆分 no-mmu 和 mmu,那还要考虑 no-mmu 的一种情况,就是 MCU,可能偏 32E 的版本,也就是不打算跑 Linux 的那些 RISC-V 板子 按照 common 合并的初衷,这些板子设计的不是很离谱也可以复用 common 的代码,但是鉴于目前测试还不够充分,涉及 bsp 还比较多,代码不好 review 的状况,就先不这么极端。 |
|
@GuEe-GUI 您好,我手头有一块 Spacemit K1的开发板,正计划为它适配一个 BSP。 |
由于前面的仍留下部分疑问,因此这个 PR 的内容没有继续更新(有定期同步主线继续开发)。 |
|
@GuEe-GUI |
太好了,我也是这个 SBC,晚些我整理代码提交上来 |


拉取/合并请求描述:(PR description)
[
qemu-virt64-riscv64Plan:
Depend on:
]
当前拉取/合并请求的状态 Intent for your PR
必须选择一项 Choose one (Mandatory):
代码质量 Code Quality:
我在这个拉取/合并请求中已经考虑了 As part of this pull request, I've considered the following:
#if 0代码,不包含已经被注释了的代码 All redundant code is removed and cleaned up