目录

  • 前言
    • 使用场景概述
  • WFE、SEV 与 WFI 的作用与工作原理
    • SEV
    • WFE
    • WFI
    • The Event Register
    • WFE伪代码
    • WFE wake-up events
    • WFI伪代码

前言

WFI和WFE都是Cortex内核进入低功耗的指令,WFI(wait for interrupt)和WFE(wait for event),如果仅仅从字面去理解,一个是中断(int)唤醒,一个是事件(event)唤醒,完美!

但是,中断是什么,好理解,那事件是什么?中断算一个事件吗?WFE等待的事件是从哪里来的?内核为啥要分WFI和WFE?是不是有点懵!

  • 相同点:
    WFE和WFI都是用来让内核进入低功耗的,中断和事件都可以唤醒内核。

  • 不同点0:
    WFE还会受控于一个1bit event register,此寄存器软件不可访问。此功能时为多核而准备的。WFEevent register为0,或为1时,其功能是不一样的。WFE的E就是指这个事件寄存器。
    进一步描述:假设两个核,分别为core1core2
    A、core1可以执行SEV指令更改event register,同时它可以通过TXEV硬连接到core2RXEV更改core2event register
    B、core1在执行WFE时,如果发现event register=1,它是不会进低功耗的,这里就是区别。
    基于以上描述WFE是多核低功耗用的,举个例子:当core1core2抢同一个资源A时,core1占据A,那core2WFE进低功耗,等待core1SEV发过来。

  • 不同点1:
    WFE因为可以等待事件,因此在某些不能WFI的场合可以采用WFE。那什么场合不能WFI呢,比如唤醒后,系统需要做一些恢复操作,才能响应中断,那采用WFE先唤醒系统,完成芯片所需的恢复操作。

所谓的SEV指令,就是一个用来改变Event Register的指令,有两个:SEV会修改所有PE上的寄存器;SEVL只修改本PE的寄存器值。

使用场景概述

1)WFI

WFI一般用于cpuidle。

2)WFE

WFE的一个典型使用场景,是用在spinlock中(可参考arch_spin_lock,对arm64来说,位于arm64/include/asm/spinlock.h中)。spinlock的功能,是在不同CPU core之间,保护共享资源。使用WFE的流程是:

 1. 资源空闲2. Core1访问资源,acquire lock,获得资源3. Core2访问资源,此时资源不空闲,执行WFE指令,让core进入low-power state4. Core1释放资源,release lock,释放资源,同时执行SEV指令,唤醒Core25. Core2获得资源

以往的spinlock,在获得不到资源时,让Core进入busy loop,而通过插入WFE指令,可以节省功耗,也算是因祸(损失了性能)得福(降低了功耗)吧。

static __always_inline void spin_lock(spinlock_t *lock)
{raw_spin_lock(&lock->rlock);
}
#define raw_spin_lock(lock) _raw_spin_lock(lock)
#ifndef CONFIG_INLINE_SPIN_LOCK
void __lockfunc _raw_spin_lock(raw_spinlock_t *lock)
{__raw_spin_lock(lock);
}
EXPORT_SYMBOL(_raw_spin_lock);
#endif
static inline void __raw_spin_lock(raw_spinlock_t *lock)
{preempt_disable();spin_acquire(&lock->dep_map, 0, 0, _RET_IP_);LOCK_CONTENDED(lock, do_raw_spin_trylock, do_raw_spin_lock);
}
/*
* We are now relying on the NMI watchdog to detect lockup instead of doing
* the detection here with an unfair lock which can cause problem of its own.
*/
void do_raw_spin_lock(raw_spinlock_t *lock)
{debug_spin_lock_before(lock);arch_spin_lock(&lock->raw_lock);mmiowb_spin_lock();debug_spin_lock_after(lock);
}
/*
* ARMv6 ticket-based spin-locking.
*
* A memory barrier is required after we get a lock, and before we
* release it, because V6 CPUs are assumed to have weakly ordered
* memory.
*/
static inline void arch_spin_lock(arch_spinlock_t *lock)
{unsigned long tmp;u32 newval;arch_spinlock_t lockval;prefetchw(&lock->slock);__asm__ __volatile__(
"1: ldrex %0, [%3]\n"
" add %1, %0, %4\n"
" strex %2, %1, [%3]\n"
" teq %2, #0\n"
" bne 1b": "=&r" (lockval), "=&r" (newval), "=&r" (tmp): "r" (&lock->slock), "I" (1 << TICKET_SHIFT): "cc");while (lockval.tickets.next != lockval.tickets.owner) {wfe();lockval.tickets.owner = READ_ONCE(lock->tickets.owner);}smp_mb();
}
#define sev()        asm volatile("sev" : : : "memory")
#define wfe()       asm volatile("wfe" : : : "memory")
#define wfi()       asm volatile("wfi" : : : "memory")
static inline void arch_spin_unlock(arch_spinlock_t *lock)
{smp_mb();lock->tickets.owner++;dsb_sev();
}
#define SEV     __ALT_SMP_ASM(WASM(sev), WASM(nop))
static inline void dsb_sev(void)
{dsb(ishst);__asm__(SEV);
}
#ifdef CONFIG_SMP
#define __ALT_SMP_ASM(smp, up)                      \"9998: " smp "\n"                      \" .pushsection \".alt.smp.init\", \"a\"\n"       \" .long 9998b\n"                 \" " up "\n"                        \" .popsection\n"
#else
#define __ALT_SMP_ASM(smp, up)  up
#endif

以上我们可以看出,在 lock 的时候使用 WFE,在 unlock 的时候使用 SEV,这个必须要成对使用,原因我下面会说。

WFE、SEV 与 WFI 的作用与工作原理

那这条指令的作用是什么呢?我们可以上 arm 官网去查看这条指令的描述:ARM Software development tools

SEV

SEV causes an event to be signaled to all cores within a
multiprocessor system. If SEV is implemented, WFE must also be
implemented.

SEV 指令可以产生事件信号,发送给全部的 cpu,让他们唤醒。如果 SEV 实现了,那么 WFE 也必须被实现。这里的事件信号其实会表现为 Event register,这是个一 bit 的 register,如果有事件,那么此 bit 为真。

WFE

If the Event Register is not set, WFE suspends execution until
one ofthe following events occurs:1、an IRQ interrupt, unless masked by the CPSR I-bit
2、an FIQ interrupt, unless masked by the CPSR F-bit
3、an Imprecise Data abort, unless masked by the CPSR A-bit
4、a Debug Entry request, if Debug is enabled
5、an Event signaled by another processor using the SEV instruction.
If the Event Register is set, WFE clears it and returns immediately.
If WFE is implemented, SEV must also be implemented.

对于 WFE,如果 Event Register 没有设置,WFE 会让 cpu 进入 low-power state,直到上述列举的五个 events 产生,比如说中断等等都会唤醒当前因为 WFE 而 suspend 的cpu。

如果 Event Register 被设置了,那么 WFE 会直接返回,不让 cpu 进入low-power state,目的是因为既然有事件产生了,说明当前 cpu 需要干活,不能 suspend,所以才这样设计。

这里我很好奇 Event Register 到底是怎么理解的。因此需要阅读手册《ARM Architecture Reference Manual.pdf》,下面我会做说明。

WFI

WFI suspends execution until one of the following events occurs:1、an IRQ interrupt, regardless of the CPSR I-bit
2、an FIQ interrupt, regardless of the CPSR F-bit
3、an Imprecise Data abort, unless masked by the CPSR A-bit
4、a Debug Entry request, regardless of whether Debug is enabled.

而对于 WFI 这种,不会判断 Event register,暴力的直接让 cpu 进入 low-power state,直到有上述四个 events 产生才会唤醒 cpu。

注意,这里 WFE 比 WFI 多了一个唤醒特性:

an Event signaled by another processor using the SEV instruction.

也就是说 SEV 是不会唤醒 WFI 指令休眠的 cpu 的。这点需要特别注意。

接下来我谈下这个 Event Register 是怎么回事了。看这个文档《ARM Architecture Reference Manual.pdf》

The Event Register

The Event Register is a single bit register for each processor. When set, an event register indicates that an event has occurred, since the register was last cleared, that might require some action by the processor. Therefore, the processor must not suspend operation on issuing a WFE instruction.

The reset value of the Event Register is UNKNOWN.

The Event Register is set by:

  • an SEV instruction
  • an event sent by some IMPLEMENTATION DEFINED mechanism
  • a debug event that causes entry into Debug state
  • an exception return.

As shown in this list, the Event Register might be set by IMPLEMENTATION DEFINED mechanisms.
The Event Register is cleared only by a Wait For Event instruction.
Software cannot read or write the value of the Event Register directly.

以上就是 Event Register 的表述,上述已经说的很明白了,Event Register 只有一个 bit,可以被 set 的情况总有四种大类型。当任意一个条件满足的时候,Event Register 都可以被 set,那么当 WFE 进入的时候会进行 Event Register 的判断,如果为真,就直接返回。

WFE伪代码

再来看看 WFE 的介绍:

Wait For Event is a hint instruction that permits the processor to enter a low-power state until one of a number of events occurs, including events signaled by executing the SEV instruction on any processor in the multiprocessor system. For more information, see Wait For Event and Send Event on page B1-1197.

In an implementation that includes the Virtualization Extensions, if HCR.TWE is set to 1, execution of a WFE instruction in a Non-secure mode other than Hyp mode generates a Hyp Trap exception if, ignoring the value of the HCR.TWE bit, conditions permit the processor to suspend execution. For more information see Trapping use of the WFI and WFE instructions on page B1-1249.

接下来上 WFE 这条指令的伪代码流程:

Assembler syntax
WFE{<c>}{<q>}
where:
<c>, <q> See Standard assembler syntax fields on page A8-285.
Operation
if ConditionPassed() thenEncodingSpecificOperations();if EventRegistered() thenClearEventRegister();elseif HaveVirtExt() && !IsSecure() && !CurrentModeIsHyp() && HCR.TWE == '1' thenHSRString = Zeros(25);HSRString<0> = '1';WriteHSR('000001', HSRString);TakeHypTrapException();elseWaitForEvent();
Exceptions
Hyp Trap.

看了上面这段 WFE 的伪代码,一目了然,首先判断 ConditionPassed(),这些函数大家可以在 arm 手册中查看其详细含义,如果 EventResigerted() 函数为真,也就是这个 1 bit 的寄存器为真,那么就清除此 bit,然后退出返回,不会让 cpu 进入 low power state

如果不是异常处理,TakeHypTrapException(),那么就 WaitForEvent(),等待唤醒事件到来,到来了,就唤醒当前 cpu。

为什么有事件来了就直接返回呢,因为 WFE 的设计认为,如果此时有 event 事件,那么说明当前 cpu 要干活,那就没必要进入 low power state 模式。

如果没有事件产生,那么就可以进入 low power state 模式,因为 cpu 反正也是在等待锁,此时也干不了别的事情,还不如休眠还可以降低功耗。

当然,irq,fiq 等很多中断都可以让 WFE 休眠的 cpu 唤醒,那么这样做还有什么意义呢?比如说时钟中断是一直产生的,那么 cpu 很快就醒了啊,都不用等到发 SEV,那么既然是用 spin_lock,也可以在中断上半部使用,也可以在进程上下文,既然是自旋锁,就意味着保护的这段代码是要足够精简,不希望被其他东西打断,那么如果你保护的这部分代码非常长,这时候整个系统响应很可能会变慢,因为如果这时候有人也要使用这个锁的话,那么是否保护的这段代码设计上是有问题的。因此用 spin_lock 保护的函数尽可能要短,如果长的话可能需要换其他锁,或者考虑下是否真的要这么长的保护措施。

TakeHypTrapException(),是进入异常处理

Pseudocode description of taking the Hyp Trap exception
The TakeHypTrapException() pseudocode procedure describes how the processor takes the exception:
// TakeHypTrapException()
// ======================
TakeHypTrapException()// HypTrapException is caused by executing an instruction that is trapped to Hyp mode as a// result of a trap set by a bit in the HCR, HCPTR, HSTR or HDCR. By definition, it can only// be generated in a Non-secure mode other than Hyp mode.// Note that, when a Supervisor Call exception is taken to Hyp mode because HCR.TGE==1, this// is not a trap of the SVC instruction. See the TakeSVCException() pseudocode for this case.preferred_exceptn_return = if CPSR.T == '1' then PC-4 else PC-8;new_spsr_value = CPSR;EnterHypMode(new_spsr_value, preferred_exceptn_return, 20);
Additional pseudocode functions for exception handling on page B1-1221 defines the EnterHypMode() pseudocode
procedure.

ClearEventRegister()

Clear the Event Register of the current processor
清除Event Register的bit

EventRegistered()

Determine whether the Event Register of the current processor
is set Event Register bit为真,即被设置过

WaitForEvent()

Wait until WFE instruction completes

等待 Events 事件,有任何一个 Event 事件来临,都会唤醒当前被 WFE suspend 下去的 cpu, 如果是 SEV,会唤醒全部被 WFE suspend 下去的cpu。

如下是关于 WFE 的 wake up events 事件描述和列举:

WFE wake-up events

The following events are WFE wake-up events:

  • the execution of an SEV instruction on any processor in the multiprocessor system
  • a physical IRQ interrupt, unless masked by the CPSR.I bit
  • a physical FIQ interrupt, unless masked by the CPSR.F bit
  • a physical asynchronous abort, unless masked by the CPSR.A bit
  • in Non-secure state in any mode other than Hyp mode:
    — when HCR.IMO is set to 1, a virtual IRQ interrupt, unless masked by the CPSR.I bit
    — when HCR.FMO is set to 1, a virtual FIQ interrupt, unless masked by the CPSR.F bit
    — when HCR.AMO is set to 1, a virtual asynchronous abort, unless masked by the CPSR.A bit
  • an asynchronous debug event, if invasive debug is enabled and the debug event is permitted
  • an event sent by the timer event stream, see Event streams on page B8-1934
  • an event sent by some IMPLEMENTATION DEFINED mechanism.

In addition to the possible masking of WFE wake-up events shown in
this list, when invasive debug is enabled and DBGDSCR[15:14] is not
set to 0b00, DBGDSCR.INTdis can mask interrupts, including masking
them acting as WFE wake-up events. For more information, see DBGDSCR,
Debug Status and Control Register on page C11-2206. As shown in the
list of wake-up events, an implementation can include IMPLEMENTATION
DEFINED hardware mechanisms to generate wake-up events. NoteFor more
information about CPSR masking see Asynchronous exception masking on
page B1-1181. If the configuration of the masking controls provided by
the Security Extensions, or Virtualization Extensions, mean that a
CPSR mask bit cannot mask the corresponding exception, then the
physical exception is a WFE wake-up event, regardless of the value of
the CPSR mask bit.

WFI伪代码

接下来我们看下 WFI 的伪代码:

相关解释:

WFI

Wait For Interrupt is a hint instruction that permits the processor to
enter a low-power state until one of a number of asynchronous events
occurs. For more information, see Wait For Interrupt on page B1-1200.
In an implementation that includes the Virtualization Extensions, if
HCR.TWI is set to 1, execution of a WFE instruction in a Non-secure
mode other than Hyp mode generates a Hyp Trap exception if, ignoring
the value of the HCR.TWI bit, conditions permit the processor to
suspend execution. For more information see Trapping use of the WFI
and WFE instructions on page B1-1249.

以上我们可以看出,WFI 并没有去判断 event register,因此看伪代码可以很直观的看出 WFI 与 WFE 的区别。

参考文献:
ARM WFI和WFE指令

ARM系列之ARM多核指令WFE、WFI、SEV原理相关推荐

  1. ARM系列之ARM Trustzone 技术浅析(二)——— ARMv7-A Processor modes registers 的安全扩展

    ARM系列之ARM Trustzone 技术浅析(二) Processor modes Registers ARM 引入 Trustzone 技术,最重要的改动就是 CPU 架构的调整.ARM tru ...

  2. ARM系列之ARM 平台安全架构PSA和Trustzone区别 浅析

    ARM系列之ARM 平台安全架构PSA和Trustzone区别 浅析 PSA要求是什么? C1.1 硬件级别的隔离环境 C1.2 安全启动 C1.3 生命周期管理 C1.4 密钥管理 差异总结 熟悉A ...

  3. ARM系列之ARM 平台安全架构PSA 浅析

    ARM系列之RM 平台安全架构PSA 浅析 1.背景 2.PSA安全认证 2.1 什么是PSA? 2.2 功能性 API 认证 2.3 PSA安全认证(待完善) 3.专用的开源安全固件代码 1.背景 ...

  4. Armv8-R系列之ARM Cortex-R52 由来

    ARM系列之ARM Cortex-R52 由来 Cortex-R52的工作原理 Cortex-R52 是 Cortex-R 系列中最先进的处理器,可提供实时功能安全性能. 作为第一款 Armv8-R ...

  5. 片上总线协议学习(1)——SiFive的TileLink与ARM系列总线的概述与对比

    link 片上总线协议学习(1)--SiFive的TileLink与ARM系列总线的概述与对比 finally 27 人赞同了该文章 一.背景介绍 随着超大规模集成电路的迅速发展,半导体工业进入深亚微 ...

  6. ARM系列处理器和架构

    从一只ARM到另一只ARM! ARM处理器和架构 当前可用的处理器 ARM1 ARM2 ARM3 ARM4和5 ARM6 ARM7 ARM8 强壮有力的ARM ARM9 ARM10 ARM架构 v1 ...

  7. ARM系列处理器的分类

    1.ARM ARM即以英国ARM(Advanced RISC Machines)公司的内核芯片作为CPU,同时附加其他外围功能的嵌入式开发板,用以评估内核芯片的功能和研发各科技类企业的产品. ARM ...

  8. CPU处理器的分类(ARM系列中央处理器)

    嵌入式系统的5部分: 中央处理器CPU.存储器.I/O接口与设备.数据总线.软件. 其中,CPU处理器的组成:控制器.运算器.高速缓冲存储器.寄存器. 处理器的分类,如下图所示. 处理器中的寄存器,见 ...

  9. IAR for ARM系列教程(四)_菜单(Ⅱ)

    推荐 分享一个大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!http://www.captainbed.net/strongerhuang Ⅰ.写在前面 ...

最新文章

  1. 变量、中文-「译」javascript 的 12 个怪癖(quirks)-by小雨
  2. ecshop的商品列表输出中多出一条空记录
  3. gitlab在centons环境下的安装及使用
  4. java多张图片上传安卓,Android Rxjava+Retrofit2 多图片+文字上传
  5. python socket udp并发_Python进阶----UDP协议使用socket通信,socketserver模块实现并发
  6. 14个jQuery图片放大编辑插件汇总
  7. linux进行显卡配置修改什么游戏,配置好Linux显卡驱动 爽快玩游戏
  8. win7下hosts文件位置
  9. 2010年的最后一天,我又辞工(日记)
  10. Android项目持续集成之Jenkins的使用
  11. [2018.10.31 T3] 玩
  12. 萤石摄像头实现抓拍短视频
  13. matlab教程易,Matlab经典教程—从入门到精通 中文PDF
  14. 线性代数拾遗(4)—— 非齐次线性方程组通解的结构
  15. 编译icedTea-web报错填坑之旅
  16. android 播放器封装,Android 播放器二次封装与实现
  17. python统计元音字母个数_Quzh[python]统计元音字母——输入一个字符串,统计处其中元音字母的数量。...
  18. 曙光服务器bios开启vt虚拟化,VT开启教程 BIOS开启VT方法
  19. PLC PLSY 指令
  20. latex 矩阵分块(block matrix)

热门文章

  1. intel I7平台Win7 x64 下wpf、silverlight 与aero特效动画缓慢故障排除一则
  2. dp的定义原理和dpi ppi px pt sp之间的区别
  3. Spring Factories机制
  4. 快来看看三甲医院的外科主任医师正在使用的安全箱
  5. scratch教程 03
  6. php域名301设置,PHP网站域名301重定向跳转代码设置,PHP网站如何做301跳转
  7. JS根据浏览器32/64平台动态加载32/64位OCX控件
  8. obs多推流地址_还在为拿不到推流地址而烦恼吗?三分钟让你用上OBS进行高清直播...
  9. 北大青鸟培训第二天:HTML初级代码和相关知识 (持续更新)
  10. springcloud毕设选题