5 函数接口描述
功能接口描述。这些API描述不包含底层的SMC或HVC调用。但是,这些函数却都遵守SMCCC调用规约。如果实现了EL2却没有实现EL3,则hypervisor使用HVC为运行在EL1的Guest OS提供调用支持。调用格式都是一样的。PSCI函数只能由非安全空间发起调用(EL1或EL2)。
5.1 PSCI_VERSION
- 功能描述
返回PSCI实现的版本号。 - 参数
uint32 Function ID:0x8400 0000 - 返回值
uint32:
- 位
[31:16]-主版本号; - 位
[15:0]-次版本号;
- 注意
对于没有实现的PSCI函数,返回NOT_SUPPORTED。
5.2 CPU_SUSPEND
- 功能描述
挂起CPU核或它之上的更高拓扑结构中的节点。用于空闲状态管理,期望CPU核唤醒时从之前的执行位置继续执行。 - 参数
- 对于
powerdown请求,调用者必须保存复位重新运行时所需要的状态。也就是说保存的上下文必须是调用者在发生powerdown调用之前power_state参数所指示的电源级别(power_level字段)下所有可见的状态。(就是调用者自己保存自己的状态,被调用者不管) - 对于掉电请求,调用者无需执行
Cache或一致性操作。PSCI实现者完成(PSCI实现侧负责内存一致性)。 - 调用者不能假设
powerdown请求使用指定的entry point地址返回。因为,powerdown可能不能完成,比如因为中断挂起。也有可能因为与其它核的协调,真正进入的是浅睡眠模式(相比请求的休眠模式)。因此,PSCI实现可能将请求的powerdown状态降为standby状态。如果降为standby状态,PSCI实现返回到PSCI调用之后的指令,而不是指定的entry_point入口地址。此时,返回码也是成功的。如果发生比较早的wakeup事件,实现也是返回下一条指令,返回码也是成功的,也有可能成功的在指定的entry point地址处返回。 - 正确的唤醒事件必须能够保证恢复到之前的状态。
CPU_SUSPEND调用传递的入口地址必须是调用者视角下的物理地址。- 上下文标识符只对调用者有意义。PSCI实现者保存,唤醒时在返回的异常级别下,再传递给CPU核,通过该值,恢复掉电前的上下文。
INVALID_PARAMETERS:如果发生下面的情况,就会返回该错误。INVALID_ADDRESS
如果传递的入口地址,PSCI实现者认为是非法的,就返回该值。
PSCI 1.0之前使用INVALID_PARAMETERS代替该值。
- 在
OS协调模式下,如果发生以下两种情况,就会返回DENIED:
在OS协调模式下,如果系统的状态和请求状态不一致,会返回INVALID_PARAMETERS,不同之处在于: - 为高于
核电源级别的拓扑节点请求低功耗电源状态 - 该节点中至少一个子节点与请求的电源状态不兼容(比如,一个核发起请求,将系统级节点置于
powerdown状态,但是,该系统节点中的另一个核处于retention状态时,就会返回参数错误。) - 提供的
power_state参数不正确。预期是与平台固件表(如ACPI或FDT一致) - 在OS协调模式下,发生以下两种条件时,也会返回参数错误:
- 在
DENIED情况中,不一致的核必须运行中。错误会出现在调用者和实现者两侧。 - 在
INVALID_PARAMETERS情况中,不一致的节点必须处于低功耗状态,不一致只能通过调用者(OS)的错误产生。 - 为高于
核电源级别的拓扑节点请求低功耗电源状态 - 所有与请求不一致的核必须处于运行中,而不是低功耗状态
- 原始格式
PSCI 1.0之前的版本支持的形式。当使用这种格式时,PSCI_FEATURES使用CPU_SUSPEND功能ID返回的标志字段的bit[1]位被设置为0。
各比特位的意义:
| 位域 | 描述 |
31:26 |
保留,必须是0 |
25:24 |
PowerLevel |
23:17 |
保留,必须是0 |
16 |
StateType |
15:0 |
StateID |
- 扩展
StateID:
对于一个硬件平台,支持每个核、簇或整个系统固定组合状态。这些状态产生了一组合法的power_state值。这些状态应该通过固件表(如ACPI或FDT)表示给OSPM。为此,PSCI 1.0引入了一个新的扩展StateID格式。这种格式对于PSCI的实现者来说更为灵活,方便开发者实现PSCI,可以通过ACPI或FDT电源状态的描述进行改进。这样的情况下,原先的格式有些字段就多余了。
使用这种格式的时候,PSCI_FEATURES函数的返回标志中的bit[1]会被设为1(传递CPU_SUSPEND功能ID)。
注意:一种实现中不可能混用这两种格式。
- 下表是
power_state参数的位域(扩展StateID格式)。
| 位域 | 描述 |
31 |
保留,必须是0 |
30 |
StateType |
29:28 |
保留,必须是0 |
27:0 |
StateID |
- 推荐的编码格式:参考前面。
StateID示例编码 0,表示standby或retention状态;1,表示powerdown状态。另外,还说明entry_point_address和context_id的值合法;Level 0: 核Level 1: 簇Level 2: 系统PowerLevel,定义的电源域级别,也就是表示是核,簇还是系统层电源请求。
PSCI 1.0之前的版本称为AffinityLevel。
- 但是电源域级别的命名,却是实现者定义的。一般情况下,按照如下方式命名:
StateType:状态类型StateID:状态ID
对请求的组合电源状态进行标识。一般是实现者定义的。在OS协调模式下,StateID必须能够表示哪个核是最后一个进入idle状态的。
这些信息必须体现在FDT或ACPI固件表中,以便在请求电源状态时,将这些信息添加到StateID字段中。推荐编码格式可以参考第6.5小节。
| 位域 | 描述 |
15:12 |
核是电源等级中的最后一个 • 0: Core Level • 1: Cluster Level • 2: System Level |
11:8 |
系统级局部电源状态: • 0: Run • 2: Retention • 3: Powerdown |
7:4 |
簇级局部电源状态: • 0: Run • 2: Retention • 3: Powerdown |
3:0 |
核级局部电源状态: • 0: Run • 1: standby • 2: Retention • 3: Powerdown |
0x8400 0001-SMC32版本0xC400 0001-SMC64版本uint32 Function ID:uint32 power_state
从PSCI 1.0开始,支持两种格式。entry_point_address
唤醒时,程序继续执行的起始地址。可以是PA(物理地址)或IPA(中间物理地址)。context_id
该参数只对调用者有用。PSCI实现者只需保留一下该参数的备份即可。从掉电状态唤醒时,PSCI将该值写入到R0、W0或X0通用寄存器中,进入异常的程序会通过该寄存器将保存的上下文内容恢复。- 调用者的责任
在发起CPU_SUSPEND调用之前,非安全空间必须遵守以下规则:
调用者必须处理可能的错误码: - PSCI实现者的责任:状态协调
在平台协调者模式中,调用者通过power_state参数传递的指定进入的电源状态,在语义上不是强制的。相反,它代表的是调用者容忍的最深的电源状态。此种情况下,是通过PSCI实现真正进入的电源状态。为此,如果一个核没有调用CPU_ON而上电,或者调用了CPU_OFF而关闭的情况下,假定该核进入了最深的电源状态。
而在OS协调模式中,调用者显式请求某个特定的电源状态,而不是让PSCI实现决定。实现必须遵循请求,除非与实现当前的状态不一致。 - PSCI实现者的责任:与可信OS或PF进行交互
PSCI实现必须能够与可信OS或SP进行通信。交互方法请参考ARMv8-A的Firmware Framework。
因为某些原因,可信OS或SP可能不兼容某种特殊的状态。这种情况下,ARM建议:可信OS或SP使用自定义的机制与非安全空间通信,保证它的限制可以被非安全空间的代码考虑。 - PSCI实现者的责任:Cache和内存一致性管理
Powerdown状态要求清除Cache。PSCI实现者必须在掉电一个节点之前,为该节点中所有的Cache和正在最后关闭的那个核执行清除操作。另外,PSCI实现还需要在启动阶段执行对Cache的失效操作,除非这是硬件能够自动完成的。在相关处理器和互连IP的技术参考手册中可以看到,上电或掉电应该遵守的顺序。 - PSCI实现者的责任:返回状态
当从standby状态返回时,对于调用者来说,CPU核的状态应该没有变化,除了定时器和由于唤醒中断造成的CPU interface的变化之外。对于核来说,standby状态和使用WFI指令没有什么不同。唯一的不同就是,调用SMC指令造成的寄存器变化。R0或W0返回的值是错误码。对于standby状态,成功时返回SUCCESS。对于powerdown状态,如果成功不会返回,因为唤醒时,从传递的入口地址处开始执行。如果不成功,返回错误码,表明错误原因。
- 返回值
int32:
SUCCESS;INVALID_PARAMETERS;INVALID_ADDRESS;DENIED;
- 注意
对于没有实现的PSCI函数,返回NOT_SUPPORTED。
5.3 CPU_OFF
- 功能描述
关闭核。用于hotplug。只能使用CPU_ON调用重新开启一个核。 - 参数
0x8400 0002uint32 Function ID:
- 返回值
int32:成功不会返回;否则返回DENIED。
5.4 CPU_ON
- 功能描述
启动一个核。有两种情况:(1)启动阶段时调用;(2)该核之前被CPU_OFF关闭。 - 参数
[24:31]: 必须是0[16:23]: 匹配MPIDR.Aff2位域[8:15]: 匹配MPIDR.Aff1位域[0:7]: 匹配MPIDR.Aff0位域[40:63]: 必须是0[32:39]: 匹配MPIDR.Aff3位域[24:31]: 必须是0[16:23]: 匹配MPIDR.Aff2位域[8:15]: 匹配MPIDR.Aff1位域[0:7]: 匹配MPIDR.Aff0位域0x8400 0003-SMC32版本0xC400 0003-SMC64版本uint32 Function ID: 功能IDuint32/uint64 target_cpu:目标核MPIDR寄存器的备份。如果是AArch32:
如果是AArch64:uint32/uint64 entry_point_address:入口地址
当核返回到非安全异常级时必须执行的地址。SMC64版本时,是64位的物理地址或中间物理地址;SMC32版本时,是32位的物理地址或中间物理地址;uint32/uint64 context_id:上下文地址
当核返回到非安全异常级时:SMC64版本时,该值必须保存在X0寄存器;SMC32版本时,该值必须保存在R0寄存器。需要把该地址的上下文内容恢复(堆栈、执行状态、中断状态等)。
- 返回值
int32:
SUCCESS,成功则返回该值;INVALID_PARAMETERS,描述了一个无效的MPIDR;INVALID_ADDRESS,ATF认为传递进来的入口地址非法;ALREADY_ON,ATF认为该核已经启动;ON_PENDING,已经发起了CPU_ON请求,ATF还未处理;INTERNAL_FAILURE,因为物理原因,不能启动CPU核。
5.5 AFFINITY_INFO
- 功能描述
请求某个亲和力等级上的信息。 - 参数
0:target_affinity中的所有位域都是有效的。在不支持硬件线程化的处理器系统中,target_affinity将会表示单个核。1:表示target_affinity中,忽略Aff0位域。target_affinity表示亲和力等级为1的处理单元。2:表示target_affinity中,忽略Aff0和Aff1位域。target_affinity表示亲和力等级为2的处理单元。3:表示target_affinity中,忽略Aff0、Aff1和Aff2位域。target_affinity表示亲和力等级为3的处理单元。0x8400 0004-SMC32版本0xC400 0004-SMC64版本uint32 Function ID:target_affinity
同CPU_ON的target_cpu参数格式一样。(SMC32或SMC64)lowest_affinity_level
表示target_affinity参数中有效的最低亲和力级别。该参数允许AFFINITY_INFO调用者请求大于0的亲和力等级的信息。
可能的值:
从PSCI 1.0版本开始,AFFINITY_INFO不再需要支持高于0的亲和级别。
- 返回值
int32:
2 ON_PENDING,亲和力对象正在转换为ON状态的过程中;1 OFF,亲和力对象中,所有核都关闭;0 ON,亲和力对象中,至少有一个核开启;INVALID_PARAMETERS(PSCI 1.0以上,请求亲和力值大于0的请求会返回该值);DISABLED,由于物理原因禁止。
5.6 MIGRATE
- 功能描述
(可选的)请求将可信OS迁移到另一个核上。 - 参数
0x8400 0005-SMC32版本0xC400 0005-SMC64版本uint32 Function ID:target_cpu
同CPU_ON调用的target_cpu参数一样。
- 返回值
int32:
SUCCESS,成功则返回该值;NOT_SUPPORTED,不支持该功能,或不需要迁移;INVALID_PARAMETERS,描述了一个无效的MPIDR;DENIED,可信OS启动,但是不可迁移;INTERNAL_FAILURE,因为物理原因,不能迁移;NOT_PRESENT,可信OS不在请求的核上。
5.7 MIGRATE_INFO_TYPE
- 功能描述
(可选的)请求可信OS支持多核的情况。 - 参数
0x8400 0006uint32 Function ID:
- 返回值
int32:
0支持单核迁移的可信OS。可信OS只能运行在一个核上。可信OS支持迁移功能,可以被迁移到任意一个核上。如果尝试对运行可信OS的核调用CPU_OFF,请求会被拒绝(DENIED)。1不支持单核迁移的可信OS。可信OS只能运行在一个核上。可信OS不支持迁移功能。调用MIGRATE会被拒绝。2可信OS既不存在、也不需要迁移。这类系统不要求调用者使用MIGRATE功能。如果硬要调用,返回NOT_SUPPORTED。NOT_SUPPORTED调用操作系统可以认为等价于返回值为2的情况。
5.8 MIGRATE_INFO_UP_CPU
- 功能描述
(可选的)返回单核可信OS所在的核。 - 参数
0x8400 0007-SMC32版本0xC400 0007-SMC64版本uint32 Function ID:
- 返回值
可能是32位或64位:
UNDEFINED:如果MIGRATE_INFO_TYPE调用返回2或NOT_SUPPORTED;基于MPIDR的值:格式与CPU_ON调用中的target_cpu参数一样。
5.9 SYSTEM_OFF
- 功能描述
关闭系统。SYSTEM_OFF提供了一个系统关闭的接口。在调用该接口之前,调用者必须将所有的核置于已知状态。调用也只能是由非安全空间发起。一旦发起该调用,PSCI实现将会完全关闭最高等级的电源(也就是系统电源)。
启动必须是冷启动。 - 参数
0x8400 0008uint32 Function ID:
- 返回值
不需要返回。
5.10 SYSTEM_RESET
- 功能描述
提供系统冷复位的方法。 - 参数
0x8400 0009uint32 Function ID:
- 返回值
不需要返回。
5.11 SYSTEM_RESET2
- 功能描述
(可选)对SYSTEM_RESET的扩展,PSCI 1.1引入。提供:
- 架构相关的
reset方法 - 供应商提供的
reset方法
- 参数
Bit[31],保留的话就必须为0.Bits[30:0]- 设为1,则使用供应商提供的reset方法;
- 设为0,则为架构提供的reset方法;
0x0SYSTEM_WARM_RESET.- 其它值保留.
- 对于供应商提供的reset方法,这些位的意义由供应商定义。
- 对于架构提供的reset方法,定义如下:
0x8400 0012-SMC32版本0xC400 0012-SMC64版本uint32 Function ID:reset_type
32位值,被分为两部分:cookie
32位或64位值。用来传递额外的reset信息。
- 返回值
int32:
SUCCESS,成功不返回NOT_SUPPORTED;INVALID_PARAMETERS;
5.12 MEM_PROTECT
- 功能描述
(可选)通过在将内存移交给操作系统加载程序之前,重写这段内存,来提供针对冷重启攻击的保护。PSCI 1.1引入。 - 参数
0x8400 0013uint32 Function ID:enable
32位值,非0值表示内存保护被启动。0值表示禁止保护功能。
- 返回值
int32:
- 成功,则返回之前的使能状态:0,表示之前是被禁止的;1,表示之前是使能的。
- 失败,则返回
NOT_SUPPORTED。
5.13 MEM_PROTECT_CHECK_RANGE
- 功能描述
(可选)可以检查某段内存是否被MEM_PROTECT保护。PSCI 1.1引入。 - 参数
0x8400 0014-SMC32版本0xC400 0014-SMC64版本uint32 Function ID:uint32/64 base
要检查的内存的基地址;uint32/64 length
要检查的内存的长度;
- 返回值
int32:
SUCCESSDENIEDNOT_SUPPORTED
5.14 PSCI_FEATURES
- 功能描述
查询SMCCC_VERSION或者某个PSCI功能是否被实现。PSCI 1.0引入。 - 参数
0x8400 000Auint32 Function ID:psci_func_id
功能ID:PSCI或SMCCC_VERSION
- 返回值
如果功能实现,则意义如下:
| psci_func_id | 标志位 | 描述 |
CPU_SUSPEND功能ID |
[31:2] |
保留,等于0 |
[1] |
0,power_state使用原始格式(PSCI 2.0)1,power_state新的扩展StateID格式 |
|
[0] |
0,不支持OS协调方式1,支持OS协调方式 |
|
| 其它功能ID | [31:0] |
保留都是0 |
5.15 CPU_FREEZE
- 功能描述
(可选)将核置于供应商自定义的低功耗状态中。与CPU_OFF不同,中断仍然可以传递给该核。但是,该核一直会处于低功耗状态中,直到CPU_ON调用将其启动。PSCI 1.0引入。 - 参数
0x8400 000Buint32 Function ID:
- 返回值
int32:
- 成功,不返回。
- 失败,则返回
NOT_SUPPORTED或DENIED。
5.16 CPU_DEFAULT_SUSPEND
- 功能描述
(可选)将核置于供应商自定义的低功耗状态中。与CPU_SUSPEND不同的是,不需要指定power_state参数。PSCI 1.0引入。 - 参数
0x8400 000C-SMC32版本0xC400 000C-SMC64版本uint32 Function ID:entry_point_address
参考CPU_SUSPEND;context_id
参考CPU_SUSPEND;
- 返回值
int32:
SUCCESSINVALID_ADDRESS
5.17 NODE_HW_STATE
- 功能描述
(可选)返回系统的电源域拓扑结构中一个节点的硬件状态。PSCI 1.0引入。 - 参数
0x8400 000D-SMC32版本0xC400 000D-SMC64版本uint32 Function ID:target_cpu
参考CPU_ON;power_level
表示想要请求的节点,在电源域拓扑结构的层级。这是供应商自定义的,但是0保留给CPU核。
- 返回值
int32:
2 HW_STANDBY:返回2,表示处于standby或retention电源状态;1 HW_OFF:返回1,表示处于powerdown状态;0 HW_ON:返回0,表示处于run状态;NOT_SUPPORTEDINVALID_PARAMETERS
5.18 SYSTEM_SUSPEND
- 功能描述
语义等价于CPU_SUSPEND,将系统置于最低功耗状态。该调用是实现system suspend-to-RAM的基础(ACPI规范中描述的S2和S3状态)。值得注意的是,系统进入S2或S3状态,需要几个前提条件。系统中所有设备必须与进入该系统挂起状态兼容,可能需要在调用之前,优雅地处理各个外设。这些前提条件不在本文的讨论范围内。SYSTEM_SUSPEND仅限于提供进入S2或S3状态的机制,所有必要的条件都由调用OS满足。尽管ACPI将suspend-to-RAM功能分为S2或S3两种状态,但是PSCI只提供了一个API。
同SYSTEM_SHUTDOWN和SYSTEM_RESET一样,该函数适用于调用OS的机器视角。
为了使用该函数调用,调用者必须使用CPU_OFF关闭所有的核,但保留一个核。剩下的这个核调用SYSTEM_SUSPEND,传递entry_point_address和context_id参数(唤醒时用),进入挂起状态。调用者(OS)可以在调用SYSTEM_SUSPEND之前,使用AFFINITY_INFO函数保证所有其它核都已关闭。 - 参数
0x8400 000E-SMC32版本0xC400 000E-SMC64版本uint32 Function ID:entry_point_address:参考CPU_SUSPENDcontext_id:参考CPU_SUSPEND
- 返回值
返回32位值。
NOT_SUPPORTEDINVALID_ADDRESSALREADY_ON- 成功不会返回;
- 失败则返回:
5.19 PSCI_SET_SUSPEND_MODE
- 功能描述
(可选)设置电源状态协调方式。PSCI 1.0引入。 - 参数
0: 平台协调方式1: OS协调方式0x8400 000Fuint32 Function ID:mode
- 返回值
int32
SUCCESSNOT_SUPPORTEDINVALID_PARAMETERSDENIED
5.20 PSCI_STAT_RESIDENCY
- 功能描述
(可选)返回冷启动之后,在某种状态下的度过时间。PSCI 1.0引入。 - 参数
0x8400 0010-SMC32版本0xC400 0010-SMC64版本uint32 Function ID:target_cpu
格式与CPU_ON调用相同;power_state
指定的电源状态。
- 返回值
可能是32位或64位。返回处于指定电源状态的时间。
5.21 PSCI_STAT_COUNT
- 功能描述
(可选)返回冷启动之后,进入某种状态下的次数。PSCI 1.0引入。 - 参数
0x8400 0010-SMC32版本0xC400 0010-SMC64版本uint32 Function ID:target_cpu
格式与CPU_ON调用相同;power_state
指定的电源状态。
- 返回值
可能是32位或64位。进入某种状态下的次数。
5.22 错误码
| 定义 | 值 |
| SUCCESS | 0 |
| NOT_SUPPORTED | -1 |
| INVALID_PARAMETERS | -2 |
| DENIED | -3 |
| ALREADY_ON | -4 |
| ON_PENDING | -5 |
| INTERNAL_FAILURE | -6 |
| NOT_PRESENT | -7 |
| DISABLED | -8 |
| INVALID_ADDRESS | -9 |
6 其它实现细节
6.1 PSCI调用流程
6.1.1 CPU_SUSPEND、CPU_DEFAULT_SUSPEND和SYSTEM_SUSPEND调用流程
6.1.2 CPU_OFF调用流程
6.1.3 CPU_ON调用流程



