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 0002
uint32 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 0006
uint32 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 0008
uint32 Function ID
:
- 返回值
不需要返回。
5.10 SYSTEM_RESET
- 功能描述
提供系统冷复位的方法。 - 参数
0x8400 0009
uint32 Function ID
:
- 返回值
不需要返回。
5.11 SYSTEM_RESET2
- 功能描述
(可选)对SYSTEM_RESET
的扩展,PSCI 1.1
引入。提供:
- 架构相关的
reset
方法 - 供应商提供的
reset
方法
- 参数
Bit[31]
,保留的话就必须为0.Bits[30:0]
- 设为1,则使用供应商提供的reset方法;
- 设为0,则为架构提供的reset方法;
0x0
SYSTEM_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 0013
uint32 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
:
SUCCESS
DENIED
NOT_SUPPORTED
5.14 PSCI_FEATURES
- 功能描述
查询SMCCC_VERSION
或者某个PSCI
功能是否被实现。PSCI 1.0
引入。 - 参数
0x8400 000A
uint32 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 000B
uint32 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
:
SUCCESS
INVALID_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_SUPPORTED
INVALID_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_SUSPEND
context_id
:参考CPU_SUSPEND
- 返回值
返回32位值。
NOT_SUPPORTED
INVALID_ADDRESS
ALREADY_ON
- 成功不会返回;
- 失败则返回:
5.19 PSCI_SET_SUSPEND_MODE
- 功能描述
(可选)设置电源状态协调方式。PSCI 1.0
引入。 - 参数
0
: 平台协调方式1
: OS协调方式0x8400 000F
uint32 Function ID
:mode
- 返回值
int32
SUCCESS
NOT_SUPPORTED
INVALID_PARAMETERS
DENIED
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调用流程