<commit_before>---
layout: default
---

# RISC-V 双周简报 (2018-12-25)

要点新闻：

## RV新闻

## 技术讨论

### Spike 的 TLB 刷新

Spike (riscv-isa-sim) 在 RISC-V 的 compliance test-suite 完成之前，是 RISC-V 指令集的规范实现(Golden Model)。
一些 RISC-V 研究者必然会使用 Spike 来研究 RISC-V 指令集。 然而，Spike 毕竟只是一个指令级别的仿真器，而并非一个处理器实现，不能完全通过 Spike 来猜测实际 RISC-V 处理器的行为。
比如，最近有人问，为什么 Spike 会频繁刷新 TLB 呢，很多 TLB 的刷新都是不必要的啊？

其实，Spike 的 TLB 并不是真实的硬件 TLB，而是一个软件的地址翻译缓存，将 RISC-V 的地址直接翻译成仿真主机的虚拟内存地址，从而避免仿真过程中的内存权限检查、硬件TLB查找、页表查询等等。
实际上，Spike 的行为级缓存也只是缓存访问的统计单元，并不真实存储任何缓存数据，而不支持任何一致性操作。

由于 Spike 的 TLB 绕过了权限检查，Spike 需要在执行权限改变、 修改 MSTATUS CSR 和修改 SATP CSR 时刷新 TLB。

在执行权限修改时，由于不同优先级可使用不同的虚拟空间（甚至关闭虚拟内存），TLB 中保存的地址翻译可能失效。

在修改 MSTATUS CSR 时，对于页表特权比特的解释可能通过 MXR, MPRV+MPP 等配置组合改变，因而也需要刷新 TLB。

在修改 SATP CSR 时，虚拟地址可以在 Sv32/Sv39/Sv48/Bare 之间变化，因而也会导致 TLB 失效。

* 具体参见 Andrew 的回复 [[hw-dev](https://groups.google.com/a/groups.riscv.org/d/msg/hw-dev/VCvfFVD87ls/axlzznzUBgAJ)]。

## 代码更新

## 安全点评

## 微群热点

## 实用资料

## 行业视角

## 市场相关

## CNRV社区活动

## CNRV网站更新

## 会议征稿

## 暴走事件<commit_msg>Add unprivileged WFI<commit_after>---
layout: default
---

# RISC-V 双周简报 (2018-12-25)

要点新闻：

## RV新闻

## 技术讨论

### Spike 的 TLB 刷新

Spike (riscv-isa-sim) 在 RISC-V 的 compliance test-suite 完成之前，是 RISC-V 指令集的规范实现(Golden Model)。
一些 RISC-V 研究者必然会使用 Spike 来研究 RISC-V 指令集。 然而，Spike 毕竟只是一个指令级别的仿真器，而并非一个处理器实现，不能完全通过 Spike 来猜测实际 RISC-V 处理器的行为。
比如，最近有人问，为什么 Spike 会频繁刷新 TLB 呢，很多 TLB 的刷新都是不必要的啊？

其实，Spike 的 TLB 并不是真实的硬件 TLB，而是一个软件的地址翻译缓存，将 RISC-V 的地址直接翻译成仿真主机的虚拟内存地址，从而避免仿真过程中的内存权限检查、硬件TLB查找、页表查询等等。
实际上，Spike 的行为级缓存也只是缓存访问的统计单元，并不真实存储任何缓存数据，而不支持任何一致性操作。

由于 Spike 的 TLB 绕过了权限检查，Spike 需要在执行权限改变、 修改 MSTATUS CSR 和修改 SATP CSR 时刷新 TLB。

在执行权限修改时，由于不同优先级可使用不同的虚拟空间（甚至关闭虚拟内存），TLB 中保存的地址翻译可能失效。

在修改 MSTATUS CSR 时，对于页表特权比特的解释可能通过 MXR, MPRV+MPP 等配置组合改变，因而也需要刷新 TLB。

在修改 SATP CSR 时，虚拟地址可以在 Sv32/Sv39/Sv48/Bare 之间变化，因而也会导致 TLB 失效。

* 具体参见 Andrew 的回复 [[hw-dev](https://groups.google.com/a/groups.riscv.org/d/msg/hw-dev/VCvfFVD87ls/axlzznzUBgAJ)]。

### 无特权的 WFI 指令

<NAME> 在 `RISC-V ISA Dev` 邮件列表里表示，期望有用户模式下（User mode）的 WFI（Wait For Interrupt）指令。他认为有些情况下（尤其是微控制器 microcontrollers）只存在一个任务（或当前活跃 active 的任务只有一个），此时确切地需要执行 WFI 指令，即使没有支持用户模式（User Mode）中断 的 N-扩展（ N-extension）。

Liviu lonescu 也提议把从特权规范（privileged specs） WFI 分离出来放到基本的用户 ISA 里 https://github.com/riscv/riscv-isa-manual/issues/275 。

Waterman 回应说，也有人请求有一条示意暂停（“PAUSE” hint）的指令。不像 WFI，PAUSE 确保不会延迟执行超过一个短的、有限制范围的时间（a short, bounded time）。这样对于用户模式（U-mode）是安全的，适合于例如等待自旋锁（busy-waiting on a spinlock）的情形。PAUSE 和用户模式（U-mode）的 WFI 部分重叠，WFI 也只有在该中断事件正好是你正在等待的时候用才合适。

<NAME> 表示，类似于 CSRs 里面的计数器使能寄存器（counter CSR enables），可以把特定的指令在用户模式下屏蔽掉（即用户模式不能使用该指令），也可以允许使用越过特权范围的指令。（译者注，通过配置该寄存器，可以让低权限模式下，比如用户模式 U-mode，可以执行更高模式下的指令，比如管理员模式 S-mode）。 FENCE_I 就属于这种类型的指令。如果算上 cache 控制指令的话它们也在这个范畴，也就是那些由操作系统的策略决定使用权限的指令。在 iOS 里，FENCE_I 是被禁止使用的，因为苹果在获取指令和数据的权限之间要维持哈佛类型（Harvard-Style，即把指令和数据隔开）的界限。这通过页表（page tables）来强制执行。例如，MAP_JIT 被保留用于 Apple 的代码里。FENCE_I 打破了它们的界限（violated their boundary），但不是那些将可读和可执行（R^X）策略约束添加到 mmap/mprotect 里的操作系统。

<NAME> 从系统内核的角度考虑，认为用户层的 WFx 类指令没有实质意义，只会徒增编写内核的复杂性。对于多任务内核来说，把用来等待的指令放在用户层会使得事件密集（event-bound）进程或线程变成 CPU 密集（CPU-bound，即大量占用 CPU 资源）的进程/线程。如果大量的用户层线程开始等待事件，CPU 将会一直运转。举个例子，当 WFE （Wait for event 等待事件）造成阻塞（blocked）时，硬件可以调度另一个硬件线程（hart，hardware thread）来使用该总线。但随后该线程（译注：即前面说的另一个线程）的时间片到期，发生抢占（译注：轮到第一个 hart）。当第一个硬件线程（hart）正在执行其他软件线程时，最初的 WFE 线程等待的事件发生了。这种情况怎么处理呢？如果它调用了中断（it involves interrupts），你所做的已经妨碍了内核，让它不能准确地计算该线程真正的 CPU 使用率（all you've done is prevented the kernel from accurately accounting for that thread's true CPU utilization），导致错误地抬高了 CPU 使用率的报告。在（性能）开销方面（In terms of overhead），你没能节省什么。在只有一个硬件线程的系统里，大部分情况下跑的微控制器的应用程序，你不仅仅是从统计的立场（from an accounting stand-point）把 IO 密集（IO-bound）的进程变成 CPU 密集（CPU-bound）的进程，在代码执行方面也是如此（因为只用一个硬件线程，没有其他的硬件线程可供软件线程使用）。如果该事件被忽略，随后当最初的线程被重新调度执行时，还是会重新执行 WFE 指令，错过了最初的事件，然后该线程的 process 被降低或是在极端情况下被禁止（the thread progress is reduced or inhibited in extreme cases）。你可能有一个类似  VMS-/AmigaOS 的事件掩码寄存器被 WFE 用来追踪事件，但这个非常类似中断被禁用（对，WFI 仍能适用这种情况），所以现在你只是在奢侈的 CSRs 和指令上浪费硬件资源。在每个情况下，我没看到收益而是损耗。

<NAME> 又再次强调，现在的标准定义 TW 位来允许 monitor 有选择地把 WFI/WFE 当成有权限的对待。同样地扩展成让 supervisor (译者注：即 S-mode）选择是否让用户模式有权限执行这些指令，也给操作系统这个选择权（译者注：操作系统属于 S-mode）。如果不支持 S-mode 的实现，现在（已经定义）的 TW 位可以用来选择是否在用户模式下有权限执行这些指令。

Waterman 对此表示部分赞同。对于只支持的 Machine 和 User mode 的情况， mstatus CSR 寄存器的 TW 位确实是一种有效机制决定是否允许 WFI 在用户模式下执行。他会提议修改标准这么做，同时保持向后兼容。但对于支持 Machine、Supervisor 和 User 模式的情况，是否为此多花在 sstatus CSR 寄存器上多花一个位来做此事还得在三考虑。如果此事很重要，之后作为扩展再添加进来也很容易。对于目前的情况， U 模式调用 S 模式的i指令，请用 ECALL。

* 具体参见邮件列表的讨论 [[isa-dev](https://groups.google.com/a/groups.riscv.org/forum/#!searchin/isa-dev/unprivileged$20WFI%7Csort:date/isa-dev/QWSJo83Fh8Q/NHxtXpkQBgAJ)]。

## 代码更新

## 安全点评

## 微群热点

## 实用资料

## 行业视角

## 市场相关

## CNRV社区活动

## CNRV网站更新

## 会议征稿

## 暴走事件
{'fraction_non_alphanumeric': 0.10733983877810777, 'fraction_numerical': 0.008697496817988969, 'mean_word_length': 6.964527027027027, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '783554', 'n_tokens_mistral': 3511, 'n_tokens_neox': 3989, 'n_words': 383}