请阅读【ARMv8/v9 ARM64 System Exception】
文章目录
-
- [WFI 与 WFE](#WFI 与 WFE)
-
- 等待事件(WFE)
- 发送事件(SEV)
- 本地发送事件(SEVL)
- [WFE 唤醒事件](#WFE 唤醒事件)
- [WFE 使用场景举例与代码实现](#WFE 使用场景举例与代码实现)
WFI 与 WFE
ARMv8架构提供了几个与事件相关的指令,包括等待事件(WFE)、发送事件(SEV)和本地发送事件(SEVL),这些指令有助于减少因处理器元素(PE,Processor Element)反复尝试获取自旋锁(spin-lock)而导致的功耗和总线竞争。这些指令在应用层面上是可用的,但要完全理解它们的行为,需要系统级别的异常处理知识。下面详细介绍这三个指令的功能及其对系统性能优化的影响。
等待事件(WFE)
WFE指令使得一个处理器元素可以进入低功耗状态,直到发生以下情况之一:
- 发生了一个异常。
- 接收到一个事件信号。
- 如果存在外部中断,处理器也可能被唤醒,即使这个中断最终被处理器的状态所屏蔽。
WFE指令通常用于自旋锁等待循环中,允许处理器在等待锁释放的时候降低功耗。
发送事件(SEV)
SEV指令用于在同一系统中的一个或多个处理器元素之间发送事件信号。当一个处理器执行SEV指令时,它将触发系统中所有正在执行WFE指令等待事件的处理器元素退出等待状态。 在自旋锁释放后使用SEV指令可以唤醒等待该锁的其他处理器元素,这有助于减少等待时间和功耗。
关于spin_lock与独占访问的关系推荐阅读 :
【ARM AMBA AXI 入门 7 - AXI 协议中的独占访问 使用背景介绍】
【ARM AMBA AXI 入门 6 - AXI3 协议中的锁定访问之AxLOCK信号】
本地发送事件(SEVL)
SEVL指令与SEV类似,但它只确保发出事件信号的处理器元素本身在下一次执行WFE指令时立即返回,而不进入等待状态。这有助于优化特定的同步模式,其中处理器元素可能需要在检查某个条件后立即继续执行,而不是等待。
WFE 唤醒事件
WFE
(Wait For Event)指令让处理器进入等待状态,直到发生特定的唤醒事件(Wake-up Events)。这些事件可以来自多种不同的源,以下介绍了在AArch64状态下可以触发WFE
指令唤醒处理器的事件:
- 执行SEV指令 :在多处理器系统中,任何处理器元素(PE)执行
SEV
(Send Event)指令都可以作为一个唤醒事件。SEV
指令用于在PE之间发送全局事件信号。 - 物理SError中断、IRQ中断或FIQ中断:如果PE收到物理SError中断、IRQ(Interrupt Request)中断或FIQ(Fast Interrupt Request)中断,并且该中断没有被EDSCR.INTDIS(一个调试寄存器的一部分,用于禁用中断)禁用,那么这个中断会作为一个唤醒事件。
- 异步外部调试请求:如果允许暂停执行(Halting),那么一个异步外部调试请求也可以作为一个唤醒事件。这种情况通常与调试过程有关。
- 由处理器元素的定时器事件流发送的事件:处理器元素的定时器可以配置为在特定时间点发送事件,这些事件也能唤醒处于WFE等待状态的PE。
- 全局监视器清除造成的事件:当PE的全局监视器从独占访问状态变为开放访问状态时,会生成一个事件,这也可以唤醒等待的PE。
- 由某些实现定义机制发送的事件:特定的硬件实现可能提供了其他机制来生成唤醒事件,这些机制依赖于具体的硬件设计和配置。
- 实现FEAT_WFXT特性时的本地超时事件 :当实现了FEAT_WFXT特性,并且使用
WFET
指令时,如果虚拟计数器阈值(在CNTVCT_EL0
寄存器中表示)被等于或超过,就会产生本地超时事件作为唤醒事件。
WFE 使用场景举例与代码实现
这里以 多核系统中主核 core0 启动后去唤醒处于睡眠状态的从核 core1 为例 并测试。
首先使用汇编代码实现 sev
和wfe
的调用函数:
wfe睡眠函数
c
func enter_wfe
wfe
ret
endfunc enter_wfe
sev 事件唤醒函数
c
func arm_sev
sev
ret
endfunc arm_sev
从核启动函数(截取部分)
c
...
log_debug("\rcore%d run wfe then goto sleep\n", coreid_get());
enter_wfe ();
log_debug("\rcore%d wakeup from wfe\n", coreid_get());
enter_wfe ();
- 场景是主核core0先启动,然后使用命令手动去启动从核core1, core1 启动后后面执行到
enter_wfe
之后就会睡眠, - 然后主核执行
sev
指令来唤醒从核,然后从核醒后执行一句打印,然后再去执行enter_wfe
继续睡眠。
全局监视器和自旋锁
ARMv8架构中引入了全局监视器的概念,当处理器元素(PE)的全局监视器从独占访问状态变为开放访问状态时,会自动生成一个事件。这相当于在PE上执行了SEVL指令。因此,当一个PE释放自旋锁时,不再需要在代码中显式包含SEV指令来唤醒等待锁的其他PE,系统会自动生成相应的事件,
这简化了编程模型并有助于提高效率。 这种机制特别适用于多核处理器环境中的同步问题,可以减少因PE反复尝试获取自旋锁而导致的功耗和总线竞争,进而提升系统性能和能效。