diff --git a/articles/20220501-riscv-linux-timer.md b/articles/20220501-riscv-linux-timer.md
index e467822213aabcff972a73f5975f5cde67740657..0acf72954b20c4c8bc2af41340b749d1de2d808f 100644
--- a/articles/20220501-riscv-linux-timer.md
+++ b/articles/20220501-riscv-linux-timer.md
@@ -1,3 +1,4 @@
+> Corrector: [TinyCorrect](https://gitee.com/tinylab/tinycorrect) v0.1-rc2 - [codeinline urls pangu]
> Author: Yu Liao
> Date: 2022/05/1
> Revisor: Falcon
@@ -6,21 +7,21 @@
# RISC-V timer 在 Linux 中的实现
-## RISC-V timer 相关寄存器
+## RISC-V timer 相关寄存器
### mtime & mtimecmp 寄存器
按照 RISC-V 定义,系统需要提供两个 64 位的 M 模式寄存器 `mtime` 和 `mtimecmp`,并通过 MMIO 方式映射到地址空间。
-`mtime` 需要以固定的频率递增,并在发生溢出时回绕。当 `mtime` 大于或等于 `mtimecmp` 时,由核内中断控制器 (CLINT, Core-Local Interrupt Controller) 产生 timer 中断。中断的使能由 `mie` 寄存器中的 `MTIE` 和 `STIE` 位控制,`mip` 中的 `MPIE` 和 `SPIE` 则指示了 timer 中断是否处于 pending。在 RV32 中读取 `mtimecmp` 结果为低 32 位, `mtimecmp` 的高 32 位需要读取 `mtimecmph` 得到。
+`mtime` 需要以固定的频率递增,并在发生溢出时回绕。当 `mtime` 大于或等于 `mtimecmp` 时,由核内中断控制器 (CLINT, Core-Local Interrupt Controller) 产生 timer 中断。中断的使能由 `mie` 寄存器中的 `MTIE` 和 `STIE` 位控制,`mip` 中的 `MPIE` 和 `SPIE` 则指示了 timer 中断是否处于 pending。在 RV32 中读取 `mtimecmp` 结果为低 32 位,`mtimecmp` 的高 32 位需要读取 `mtimecmph` 得到。
-在 [RISC-V 特权 ISA 规范](https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMAFDQC/riscv-spec-20191213.pdf) 的 3.2.1 Machine Timer Registers (mtime and mtimecmp) 中详细介绍了这部分。
+在 [RISC-V 特权 ISA 规范][001] 的 3.2.1 Machine Timer Registers (mtime and mtimecmp) 中详细介绍了这部分。
### time CSR
RISC-V 还定义了一个 64 位非特权 CSR 寄存器 `time`,`time` 计数器是前面提到的 `mtime` 的只读映射。同样,在 RV32 中 `timeh` CSR 是 `mtime` 高 32 位的只读映射,对于 M 模式和 S 模式它们都是可读写的。
-在 [RISC-V 特权 ISA 规范](https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMAFDQC/riscv-spec-20191213.pdf) 的 2.2 CSR Listing 和 3.1.11 Machine Counter-Enable Register (mcounteren) 可以找到这块的规范。
+在 [RISC-V 特权 ISA 规范][001] 的 2.2 CSR Listing 和 3.1.11 Machine Counter-Enable Register (mcounteren) 可以找到这块的规范。
### htimedelta & htimedeltah 寄存器
@@ -32,7 +33,7 @@ RISC-V 还定义了一个 64 位非特权 CSR 寄存器 `time`,`time` 计数
`htimedelta` 和 `htimedeltah` 是 Hypervisor 扩展里的 CSR,在 VS/VU 模式下读取 `time` 结果是真正的 host 中的 `time` 加上 `htimedelta`。同样的,对于 RV32 `htimedelta` 保存了低 32 位,高 32 位保存在 `htimedeltah`。
-在 [RISC-V 特权 ISA 规范](https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMAFDQC/riscv-spec-20191213.pdf) 的 8.2.7 Hypervisor Time Delta Registers (htimedelta, htimedeltah) 中详细介绍了这部分。
+在 [RISC-V 特权 ISA 规范][001] 的 8.2.7 Hypervisor Time Delta Registers (htimedelta, htimedeltah) 中详细介绍了这部分。
### Sstc 扩展
@@ -40,7 +41,7 @@ RISC-V 还定义了一个 64 位非特权 CSR 寄存器 `time`,`time` 计数
Sstc 扩展为 HS 模式和 VS 模式分别新增了 `stimecmp` 和 `vstimecmp` 寄存器,当 $time >= stimecmp$ (HS)或 $time+htimedelta >= vstimecmp$ (VS)时会产生 timer 中断,不再需要通过 SBI 陷入其他模式。
-详见 [RISC-V "stimecmp / vstimecmp" 扩展](https://github.com/riscv/riscv-time-compare/releases/download/v0.5.4/Sstc.pdf) 。
+详见 [RISC-V "stimecmp / vstimecmp" 扩展][003] 。
## Linux timer 实现
@@ -48,7 +49,7 @@ Linux 将底层时钟硬件抽象为两类设备:clockevent 和 clocksource,
当前 Linux 为 RISC-V 根据内核运行模式实现了两套驱动,代码路径为 drivers/clocksource/timer-riscv.c 和 drivers/clocksource/timer-clint.c。
-本文代码基于最新的 Linux v5.18-rc4 和 OpenSBI v1.0,截止目前 Linux 对 Sstc 扩展的支持还没有合入主线内核,社区已有相关补丁:[Add Sstc extension support](https://lkml.org/lkml/2022/3/4/1175)。
+本文代码基于最新的 Linux v5.18-rc4 和 OpenSBI v1.0,截止目前 Linux 对 Sstc 扩展的支持还没有合入主线内核,社区已有相关补丁:[Add Sstc extension support][004]。
`mtime` 频率由设备树 CPU 节点中的 timebase-frequency 定义,不同平台都各不相同,如 Kendryte K210 的频率是 7.8 MHz,平头哥 C910 的频率是 3 MHz,SiFive Unmatched A00 频率为 1 MHz。
@@ -178,7 +179,7 @@ void sbi_timer_event_start(u64 next_event)
}
```
-在支持 Sstc 扩展后,可以直接访问 `stimecmp` 寄存器,避免通过 SBI 调用的方式产生的开销。社区已开展相关工作:[RISC-V: Prefer sstc extension if available](https://lore.kernel.org/all/20220426185245.281182-1-atishp@rivosinc.com/)。
+在支持 Sstc 扩展后,可以直接访问 `stimecmp` 寄存器,避免通过 SBI 调用的方式产生的开销。社区已开展相关工作:[RISC-V: Prefer sstc extension if available][005]。
### KVM vcpu_timer.c
@@ -237,12 +238,21 @@ static enum hrtimer_restart kvm_riscv_vcpu_hrtimer_expired(struct hrtimer *h)
}
```
-因此 VS 模式设置时钟事件需要通过 SBI 调用进入 HS 模式然后再进入 M 模式,会产生较大的开销。同样,在支持 Sstc 扩展后,可以直接访问 `vstimecmp` 并产生 timer 中断,社区目前已经开展了相关的工作:[RISC-V: KVM: Support sstc extension](https://lore.kernel.org/all/20220426185245.281182-4-atishp@rivosinc.com/)。
+因此 VS 模式设置时钟事件需要通过 SBI 调用进入 HS 模式然后再进入 M 模式,会产生较大的开销。同样,在支持 Sstc 扩展后,可以直接访问 `vstimecmp` 并产生 timer 中断,社区目前已经开展了相关的工作:[RISC-V: KVM: Support sstc extension][006]。
## 参考文档
-1. [RISC-V Platform](https://github.com/riscv/riscv-platform-specs/blob/main/riscv-platform-spec.adoc/)
-2. [RISC-V ISA Specification](https://riscv.org/technical/specifications/)
-3. [RISC-V "stimecmp / vstimecmp" Extension](https://github.com/riscv/riscv-time-compare/releases/download/v0.5.4/Sstc.pdf)
+1. [RISC-V Platform][002]
+2. [RISC-V ISA Specification][007]
+3. [RISC-V "stimecmp / vstimecmp" Extension][003]
4. 基于 FPGA 与 RISC-V 的嵌入式系统设计
-5. [RISC-V虚拟化扩展](https://static.sched.com/hosted_files/osseu19/4e/Xvisor_Embedded_Hypervisor_for_RISCV_v5.pdf)
\ No newline at end of file
+5. [RISC-V 虚拟化扩展][008]
+
+[001]: https://github.com/riscv/riscv-isa-manual/releases/download/Ratified-IMAFDQC/riscv-spec-20191213.pdf
+[002]: https://github.com/riscv/riscv-platform-specs/blob/main/riscv-platform-spec.adoc/
+[003]: https://github.com/riscv/riscv-time-compare/releases/download/v0.5.4/Sstc.pdf
+[004]: https://lkml.org/lkml/2022/3/4/1175
+[005]: https://lore.kernel.org/all/20220426185245.281182-1-atishp@rivosinc.com/
+[006]: https://lore.kernel.org/all/20220426185245.281182-4-atishp@rivosinc.com/
+[007]: https://riscv.org/technical/specifications/
+[008]: https://static.sched.com/hosted_files/osseu19/4e/Xvisor_Embedded_Hypervisor_for_RISCV_v5.pdf