1 介紹
本文主要是在ARM架構的不同異常等級上工作的軟件之間,提供一個標準的電源管理接口。這些軟件,比如Linux、Hypervisor、安全Firmware和可信OS之間必須能夠實現互相操作。而這些軟件可能由不同廠商提供,本標準就是為這些軟件的集成提供便利。
這些PSCI接口有利于電源管理代碼通用化、模塊化:
CPU核的空閑管理
CPU核的動態添加、刪除,以及輔核引導
系統關機和復位
該接口規范不會包含動態電壓頻率調節(DVFS)或設備電源管理(比如,GPU等外設的管理).
該接口規范設計用來與硬件探測技術(如ACPI和FDT)等配合使用,并不是要取代ACPI或FDT。
本文描述了PSCI版本1.1,1.0和0.2。對于0.2,還提供了一個勘誤更新。
本文包含以下內容:
第1章 提供介紹和文檔引用
第2-4章 提供背景知識,包括:
PSCI的設計目的
電源狀態術語的定義
發送PSCI請求的方法
ARM架構知識
第5章 提供PSCI功能的主要描述
第6章 提供PSCI功能的實現細節
第7-8章 提供PSCI規范的修訂歷史和術語表
1.1 ARM官方文檔
下面這些文檔包含與本文檔相關的信息:
[1] ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition (ARM DDI 0406).
[2] Embedded Trace Macrocell Architecture Specification (ARM IHI 0014).
[3] Program Flow Trace Architecture Specification (ARM IHI 0035).
[4] SMC調用約定(ARM DEN 0028).
[5] ARM Architecture Reference Manual ARMv8, for ARMv8-A architecture profile (ARM DDI 0487).
[6] ACPI規范.
[7] PSCI設備樹定義.
[8] ARM可信固件(ATF).
[9] Power Control System Architecture Specification (ARM DEN 0050).
2 背景知識
支持電源管理的操作系統,能夠動態改變CPU核的電源狀態,根據進行負載均衡,努力降低功耗。電源管理技術主要分為兩類:
空閑管理:當在某個核上,OS的內核沒有線程可以調度時,可以將該核置于clock-gated、retention、power-gated狀態。但是,該核對于OS而言還是可用的。
Hotplug熱插拔:根據對算力的需求變化,而將CPU核置于離線、在線。離線時,OS負責將所有中斷和線程從核上遷移走;當在線時,OS負責重新進行負載均衡。
盡管由單個供應商提供嵌入式系統的軟件可能更簡單,但事實并非如此。為了安全,ARM將硬件架構劃分為4個不同的異常級(EL)以及2個安全狀態,以便支持不同特權的軟件分區。
下表是基于ARM架構的硬件平臺上的軟件劃分:
AArch32 | AArch64 | 軟件和供應商 |
---|---|---|
NS_EL0 (PL0) | NS_EL0 | 非特權應用,如APP |
NS_EL1 (PL1) | NS_EL1 | 富操作系統內核,如Linux、Windows、iOS |
NS_EL2 (PL2) | NS_EL2 | Hypervisor(Citrix、VMWare、OK-Labs) |
S_EL0 (PL0) | S_EL0 | 可信OS的應用 |
S_EL3 (PL1) | S_EL1 | 可信OS的內核(Trustonic) |
S_EL3 (PL1) | S_EL3 | 安全Monitor,執行安全固件(ATF) |
AArch32是ARMv8架構的32位執行狀態,在ARMv8架構之前采用的執行狀態。在ARMv7處理器中,異常級的概念是隱含的,相關文檔也并未說明。那時候,虛擬化擴展提供EL2功能,安全擴展提供EL3功能,安全狀態由特權級(PL-Privilege Level)標識異常的層次結構。更多信息,參考第3.2節。
因為不同供應商的不同操作系統都可運行在ARM系統上,電源管理就需要一個協作的方法??紤]到運行在EL1上的類OS軟件或運行在EL2上的hypervisor軟件,一般處于非安全狀態,如果想要進入idle狀態、給一個核上電或掉電、或復位或關閉系統,更高異常級的監控軟件必須能夠響應這種電源狀態變化的請求。
同樣,如果某個wakeup事件改變了核的電源狀態,那么這些監管軟件需要執行諸如恢復上下文之類的操作。PSCI提供了不同監管軟件之間互操作和集成的標準接口定義。本文檔會詳細描述這類接口,以及在idle、hotplug、shutdown和reset情況下如何使用它們。
3 假設和建議
本文檔定義了在不同監管軟件之間協調電源管理的API。這種API允許監管軟件請求給核上電、掉電,安全上下文的核間遷移(可信OS需要)。本文中,假設EL2和EL3都已經實現。
3.1 PSCI用途
PSCI具有下面的用途:
提供給監控程序通用接口,可以在下列情況時,管理功耗:
CPU核的空閑管理;
系統中的CPU核動態添加和刪除,也稱之為hotplug熱插拔;
其它輔核的啟動;
將受信任的操作系統上下文從一個核遷移到另一個核;
系統關機和復位。
提供給監控管理程序通用接口,結合FDT和ACPI描述去支持電源管理代碼的泛化。
PSCI不包括:外設電源管理 和 動態電壓和頻率調節(DVFS)。
PSCI不提供給監控軟件電源狀態表示。但是,可以和ACPI或FDT等硬件描述技術結合使用。
3.2 異常級別、ARMv7特權級別和最高特權級別
ARMv8架構明確提出了EL的概念,也定義了安全狀態下軟件執行特權的層次結構。
ARMv7架構中,EL概念是隱含在架構體系中的:
虛擬化擴展提供了EL2的功能(只存在非安全狀態下)。
安全擴展提供了EL3功能,包含對兩種安全狀態的支持??刂剖窃贛onitor模式下完成的,該模式也只存在于安全狀態下。
ARMv7使用PL(特權級)的概念描述軟件執行的特權層級結構。因為Monitor模式的存在,ARMv7的非安全狀態和安全狀態是非對稱的,如下所述:
非安全狀態,特權層次結構是:
PL0, 非特權,適用于User模式
PL1, OS級特權,適用于System, FIQ, IRQ, Supervisor, Abort和Undefined模式
PL2, hypervisor特權,適用于Hyp模式
安全狀態,特權層次結構是:
Secure PL0, 非特權,僅適用于User模式
Secure PL1, 可信OS和Monitor級特權,適用于System, FIQ, IRQ, Supervisor, Abort, Undefined和Monitor模式
AArch32執行狀態下,異常級和之前的運行模式對應關系如下:
非安全狀態:
EL0: User 模式
EL1: System, FIQ, IRQ, Supervisor, Abort和Undefined模式
EL2: Hyp模式
安全狀態:
Secure EL0: User 模式
EL3: System, FIQ, IRQ, Supervisor, Abort, Undefined和Monitor模式
本文檔中如果不特殊聲明,則使用異常級別(EL)的術語:
通常情況下,提及的EL1和EL0就是指非安全EL1和EL0,除非有特殊說明;
3.3 ARM架構上的軟件棧
ARM設備上可能有的軟件棧,如下所示:
如圖所示,非安全空間中的擁有特權的代碼:
Rich-OS內核:比如,Linux或Windows,運行在非安全EL1。如果運行在Hypervisor之上,則Rich-OS內核作為hypervisor的一個客戶機運行。
Hypervisor:運行在EL2,只有非安全狀態(新ARMv8架構中,已經存在安全狀態的hypervisor)。
安全空間中擁有特權的代碼:
安全平臺固件(SPF):
芯片或OEM廠商提供。也是系統啟動階段,運行的第一段程序。它提供的服務有,平臺初始化、可信OS的安裝、SMC調用的調度執行。有些調用的目標可能是SPF,另一些則可能是可信OS。SPF可以運行在EL3,也可以運行在安全EL1(但是,條件是EL3運行在AArch64狀態)。ARM提供了一個開源的可信固件代碼。
可信OS:
為normal空間提供安全服務,即為安全應用提供一個運行時環境。在AArch32狀態下,可信OS運行在安全EL3,如果是AArch64狀態,運行在EL1。
PSCI規范主要關注安全、非安全世界之間的電源管理接口。它提供了發送電源管理請求的方法。所以,為了處理這些請求,SPF必須包含PSCI實現。
另外,PSCI實現也可能需要在SPF和可信OS之間建立通信。當然,它們之間的處理根據廠商不同而有所不同。
盡管,PSCI主要關注安全和非安全世界之間的電源管理請求,但是,也可以在Rich OS和hypervisor之間使用。
3.4 通道
在不同的異常級別之間提供可以傳送消息的通道(一般使用SMC異常指令實現),這樣才能提供相同的PSCI電源管理接口。具體參考SMCCC。
3.5 安全軟件和電源管理
許多可信OS不支持SMP。即使在多核平臺上,也是運行在某個指定的核上。所以,期望發起SMC調用的核與可信OS運行的核是同一個。不支持多核,可以保證可信OS小而美,容易通過功能安全認證。
基于ARM架構的系統通常會包含一個電源控制器,或者電源管理電路,以便管理CPU核的電源。它會提供許多電源管理功能,比如將核、簇或者集群轉變為低功耗狀態。在低功耗狀態,核可以完全關掉,也可以不執行代碼而處于靜默狀態。ARM 強烈推薦由安全空間控制電源狀態的變化。否則,在進入低功耗狀態之前,不能清除安全狀態(包括安全cache的清零)。其它的電源管理,比如動態電源性能管理(通過調節電壓和頻率實現)不在本接口規范的范圍內。
3.6 虛擬化和CPU核電源管理策略
虛擬機可以分為兩種類型
Type-1: 有時候稱為 native 或 bare metal。通俗理解的話,就是hypervisor代碼直接接管硬件,對上提供統一的虛擬隔離空間。所以,Guest OS看到的都是虛擬設備。
Type-2: 有時候稱為hosted,或者托管類型hypervisor。這類虛擬程序需要依賴一個主機OS,作為宿主。該Host OS看到的是真實硬件,但是Guest OS看到的是虛擬設備。
這是一個泛泛的分類,可能會有許多變種。ARMv8架構允許在EL1或EL2運行一個Type-2類型的hypervisor,這更加模糊了類型-1和類型-2的差異。但是,對于電源管理來說,不論哪種類型的hypervisor,都需要捕獲這種PSCI調用。
從電源管理和虛擬化的角度來看的話,有兩種類型的OSPM:
物理OSPM: 這個概念包含管理物理電源狀態的軟件。
虛擬OSPM: 這是存在于虛擬機的Guest OS中的OSPM,它管理的是虛擬的,而不是物理電源狀態。
對于type-2 hypervisor,物理OSPM存在于主機OS中。電源管理策略由運行在EL1的Rich OS負責管理。物理OSPM就包含在這種Rich OS中。在該層,直接擁有物理核的視角。下圖的左邊部分就是示例。
對于本文涉及的電源管理,type-2 hypervisor的行為取決于調用者。如果調用者是Host OS,hypervisor允許調用直接穿透到安全平臺固件(SPF)。在這種情況下,hypervisor只需執行必要的操作,比如保存powerdown時的狀態。然后,使用調用者傳遞過來的參數調用SPF。如果沒有特殊操作,hypervisor甚至不會捕獲來自Host OS的調用,直接將其路由給SPF。Guest OS使用虛擬OSPM,也是通過PSCI API發出電源管理請求,但是發送的目標是虛擬核和虛擬電源狀態。hypervisor會捕獲這些請求,然后將其發送到物理OSPM。然后,由物理OSPM決定是否請求真實的物理電源管理。對于虛擬機來說,電源管理到hypervisor就結束了。
對于type-1 hypervisor,電源管理策略通常是hypervisor自身管理的。如上圖右半部分所示。hypervisor實現物理OSPM模塊。這種情況下,虛擬機擁有的是虛擬核。由hypervisor決定虛擬機的虛擬電源狀態是否請求物理電源控制,如果需要,則使用PSCI API調用安全平臺固件SPF。同樣,Guest OS也使用PSCI API接口將虛擬電源管理請求發送給hypervisor。對于虛擬機來說,電源管理到hypervisor就結束了。
在某些情況下,type-1 hypervisor委托一個特權Guest OS管理電源。這種情況下,物理OSPM在特權Guest OS中實現。大概的電源管理方法與type-2 hypervisor類似。
4 PSCI使用場景和要求
4.1 空閑管理
當一個核處于idle狀態時,OSPM將其置于低功耗狀態。通常,選擇進入不同的電源狀態,會有不同的entry和exit延遲,也會有不同的功耗。想要進入哪種電源狀態,依賴于核重新工作的時間。除了核之外,電源狀態也可能依賴于SoC中的其它組件的活動。每種狀態都由一組組件的狀態共同決定,進入該狀態時,這些組件通過時鐘控制(clock-gated)或電源控制(power-gated)。這些狀態有時候也描述為淺睡眠或深度睡眠。通常,文獻描述使用X標識深度睡眠,Y標識淺睡眠:
X狀態應該是Y狀態的超集。
X狀態比Y狀態更省電。
從低功耗狀態進入運行狀態所需要的時間稱為喚醒延遲。通常,深度睡眠狀態具有更長的喚醒延遲。
盡管空閑電源管理是由核上的線程行為引起的,但是OSPM將硬件平臺設置的狀態,也可能會影響除CPU核之外的其它組件。比如,如果SoC中的最后一個核進入idle狀態,OSPM就可以考慮整個SoC的電源狀態了。此時的選擇也會受系統中的其它組件影響,所以,應該在SPF、hypervisor、OS之間協調電源管理。典型的例子是,當所有核,和其它請求者都處于空閑狀態時,將系統置于一種狀態,在這種狀態下,將上下文保存在內存中(內存不斷刷新中)。OSPM必須提供必要的電源管理軟件基礎設施,確定能夠對電源狀態作出正確的選擇。
在空閑管理中,當一個核被置于低功耗狀態,它可能隨時被喚醒事件激活,比如說中斷。
ARM架構劃分的電源狀態有四種:
Run
CPU核上電,且可以正常運行的狀態。
Standby
CPU核上電。通過WFI或WFE指令進入該狀態,由喚醒事件喚醒。此過程中,CPU核保持所有狀態。也就是說,從standby到run狀態,不會復位CPU核。CPU核的上下文都會被保持,喚醒即可訪問這些內容。處于該核所在電源域的外部調試器(debugger),能夠訪問debug寄存器。換句話說,standby狀態不會影響調試器的使用。
Retention
CPU核的狀態,包括debug設置等,保存在低功耗的保持寄存器中,這樣允許CPU核至少可以關閉部分電源。從低功耗狀態到運行態的轉變,不用復位CPU核。低功耗轉變到運行態時,原先保存的狀態數據從保持寄存器中恢復。所以,從OS的角度來說,Retention和Standby狀態沒有什么差別,除了恢復時的入口地址,延遲和使用上的一些限制之外。但是,對于外部debugger來說,就不一樣了,外部debug請求事件會被掛起,debug寄存器無法訪問。
Powerdown
該狀態下,CPU核會被掉電。軟件需要保存所有的核狀態數據。從掉電到恢復運行,需要:
上電后,需要復位CPU核
恢復之前保存的核的狀態數據
Powerdown狀態對上下文是破壞性的。不僅僅是CPU核的狀態數據,如果是更深的休眠狀態,可能包括GIC或者平臺依賴的其它一些IP核也會掉電。所以,相關數據或狀態必須保存。根據debug和trace電源域的組織架構,其上下文內容也有可能會丟失。所以,OS必須提供保存和恢復這些內容的機制。
對于OS來說,standby和retention都是一樣的,除了debugger之外。所以,后面我們使用standby代表這兩種狀態。
ARM期望在具有最高特權的異常級別上,實現管理電源控制器的代碼(通常就是ATF)。那么就必須提供接口,以便OSPM將CPU核置于低功耗狀態的消息事件,從不同的異常級層層往下傳遞(假設越往下,異常級別越高)。而PSCI就是這樣的一種機制,將OSPM的電源請求傳遞給下一個異常級EL。
對于standby狀態,直接使用WFI或WFE指令即可進入。但是,更深層的standby或retention狀態,則要求對電源控制器進行編程,而PSCI僅提供訪問電源控制器的接口,并隱藏了與平臺相關的代碼。
對于Powerdown狀態,則要求提供每一級EL下保存和恢復上下文的接口。而且,對于Powerdown狀態還要求一個return地址。這地址是被喚醒時,OS期望的開始運行的地方。對于Powerdown狀態,CPU核從reset復位向量(安全狀態)開始運行。待完成初始化,則跳轉到Powerdown之前要求的那個返回地址處開始執行。PSCI提供了傳遞返回地址和上下文的參數。
4.2 電源狀態系統拓撲
多核系統中,不同的電源域控制系統的不同部分。每一個電源域可能是一個或多個PE(CPU核、協處理器、GPU),內存(Cache、DRAM),簇內、簇間一致性部件等組成。
電源域中的每個組件的電源狀態,都可以影響電源域中的其它組件。雖然,從物理上來說,電源域不是一個必須存在的層次結構。但是,從軟件的角度來說,必須進行一個邏輯上的劃分。如果想要改變電源域的電源狀態,必須對其依賴項進行排序。比如,共享Cache的電源域,以及使用共享Cache的CPU核的電源域,它們之間的依賴關系。在這樣一個系統中,為了保證數據的一致性,必須先關閉CPU核的電源,然后再關閉共享Cache的電源。
上圖展示了一個系統級的電源域的拓撲結構的示例。它擁有兩個子電源域,每一個包含一個cluster簇,支持一組cluster電源狀態。每一個cluster電源域,又包含兩個子電源域,每一個包含一個CPU核,并額外支持一個電源狀態。
從硬件的角度來看,一個系統被劃分為多個單獨或共享的電源域。每個電源域都可以表示為電源域拓撲樹中的一個節點。兄弟電源域是互斥的。父電源域由子電源域共享。樹中的各種級別(示例中的核、cluster簇和系統)稱為電源級別。較高的級別,更接近樹的根(系統),較低的級別更接近樹葉(核)。
4.2.1 局部電源狀態和組合電源狀態
上面拓撲結構中的各個節點都有自己的電源狀態,我們稱為局部電源狀態。當處于空閑核上的OS請求電源狀態的改變時,不僅需要請求改變CPU核的局部電源狀態,還需要請求改變父節點的電源狀態。比如,上圖的示例中,假設核1是簇0內最后進入空閑狀態的,對于OS來說,就需要同時為簇0和核1請求電源狀態改變。這種組合的電源狀態我們就稱為組合電源狀態。這種組合電源狀態可不是隨意組合的,而是電源等級越高的節點上,其電源狀態越淺。換句話說,子節點進入休眠的程度應該大于等于父節點。規則如下:
電源等級高的節點掉電(Powerdown),電源等級低的節點也必須掉電;
電源等級高的節點保持(Retention),電源等級低的節點只能是保持或掉電;
電源等級高的節點待機(Standby),電源等級低的節點只能是待機、保持或掉電;
電源等級高的節點運行(Run),電源等級低的節點可以是任意狀態。
如下表所示:
系統級 | 簇級 | 核級 |
---|---|---|
Run | Run | Standby |
Run | Run | Retention |
Run | Run | Powerdown |
Run | Retention | Retention |
Run | Retention | Powerdown |
Run | Powerdown | Powerdown |
Retention | Retention | Retention |
Retention | Retention | Powerdown |
Retention | Powerdown | Powerdown |
Powerdown | Powerdown | Powerdown |
4.2.2 親和力的層次結構
ARM系統通常是多核、或多簇的處理器。本文檔使用親和力的層次結構描述CPU核和簇的架構關系。親和力層次結構往往直接對應系統的電源拓撲,但這也不是絕對的。
4.2.3 電源狀態協調
高層的節點進入某種局部電源狀態,必須與子節點的電源狀態進行協調。比如說,想要使一個簇(cluster)進入Powerdown狀態,那么該簇內所有的核也必須進入Powerdown狀態。實現方式就是,其它核都進入Powerdown狀態,最后一個核再把自己和簇置于Powerdown狀態。
對于這種對子節點的電源狀態進行協調的方式,PSCI支持兩種:平臺協調模式、OS發起模式。
平臺協調模式
這是默認的電源協調模式。在該模式下,PSCI實現者(如ATF等)負責協調電源狀態。當某個核上沒有任務時,OSPM為該核、以及所在簇請求允許范圍內的最深休眠狀態。因為該核的電源狀態改變請求,可能影響其父節點,所以,PSCI實現者得根據簇內所有節點的情況選擇最深的休眠狀態。實際上,電源狀態請求表達了兩種限制:
PSCI實現就會根據這兩個限制,為指定的節點內所有核,選擇一個最深的電源狀態。下表展示了OSPM請求不同的電源組合狀態,而PSCI最終能夠響應的狀態。假設簇1一直處于掉電狀態中。
通常情況下,電源狀態越深,喚醒延遲越長。所以,我們假設保持狀態比掉電狀態具有更短的喚醒延遲。但是,事實并非如此。根據第2個限制,PSCI實現者必須滿足每個核喚醒時間的請求。假設雙核系統,具有3層系統狀態,狀態A、B、C,電源休眠程度A < B < C,而喚醒延遲則是A < C < B。如果核0選擇狀態B,而核1選擇狀態C,系統將會進入狀態A。狀態B和C,不能同時滿足2個核的要求。
PSCI 1.0之前的版本只支持平臺協調模式。
調用者請求的電源狀態已經是最深休眠狀態了;
調用者請求的電源狀態的喚醒延遲不能比這更長了;
OS協調模式
PSCI 1.0引入,這種模式將電源協調的權利交給了OS。這種模式下,只有節點內的最后一個核進入空閑狀態,OSPM才會為該節點申請空閑狀態。
相比平臺協調方式,OS協調方式則是將怎么選擇最合適的休眠節點交給了OS,PSCI實現者只需實現,給我什么請求,我就響應什么動作即可。示例如下表所示:
如表所示,我們可以看到OS視角和PSCI實現的視角有些不同的地方(紅色標記)。這是因為OS雖然請求了,但是PSCI實現還未響應導致的。在上電的時候也會發生,因為PSCI實現會比OS更早看到CPU核。為了實現OS協調方式,必須解決競爭問題。
PSCI實現必須懷疑與自己視角不一樣的電源狀態請求;
OS必須指明哪個核是最后一個,而且還要指明該核處于哪一級電源中,如,是簇內的最后一個核,還是系統內最后的一個核。
4.3 CPU熱插拔和輔核啟動
CPU熱插拔的概念不需要再重復。但是,CPU熱插拔和空閑管理中的powerdown還是有一些差異:
當核被拔出時,監控軟件會停止在中斷和線程處理中對該核的所有使用。調用監控軟件認為核不再可用。
想要使用該核,必須發送命令將核再插入。
喚醒事件不會喚醒被拔出的核。
操作系統通常在主核上完成內核的引導過程,然后再啟動輔核。所以,對于支持熱插拔的系統來說,輔核的啟動和hotplug的操作是相同的,可以提供一套接口。
對于運行在單核上的可信OS,移除該核可能不可行,除非把可信OS遷移到其它核上。
PSCI提供具有下列屬性的接口:
監控軟件可以請求給一個核上電。監控軟件還必須提供一個啟動地址,作為它從安全固件退出時,繼續執行的地方。通過提供一個入口地址,監控軟件可以直接在自己的地址空間中干一些特殊的事情。為此,監控軟件還必須使用內部的per-CPU數據結構保存這些值。
監控軟件可以請求給一個核掉電。并且還能通知更高異常級別上的軟件。
監控軟件還能請求將可信OS遷移到另一個核上。
監控軟件,狹義上理解為操作系統的內核。
4.4 系統級的shutdown、reset和suspend
PSCI提供了接口,允許OS請求系統system shutdown、system reset和system suspend(suspend-to-RAM)。芯片供應商應該提供這些函數的統一實現,它們與監控軟件是獨立的。沒有提供suspend-to-disk,這是因為它是系統關機的一種特殊情況。
這兒,system的意思是從整臺機器的視角看待問題。也就是說,不是單一關閉某個核或者簇那么簡單。當然,運行在虛擬機中的客戶機OS,如果調用這些接口不會發生物理狀態的變化。
但是,如果沒有hypervisor,或者調用者是hypervisor,則會導致電源狀態的物理變化。即使調用者在物理機器上運行,術語系統可能也不是指整個物理機器。例如,假設一個高級服務器系統由多個單板組成,每個單板具有一個BMC (board management controller),每個單板包含多個SoC。這樣的系統可以在每個SoC上運行一個OS實例。在本例中,用于關閉系統的PSCI命令應用于單個SoC,而關閉整個單板需要通過管理接口訪問BMC,而這個管理接口是調用操作系統或PSCI實現無法訪問的。在本文檔中,術語系統僅指對操作系統可見的機器視圖。反映到本文檔中,就是指一個SOC。
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: 功能ID
uint32/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??尚臤S只能運行在一個核上??尚臤S不支持遷移功能。調用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調用流程
審核編輯:郭婷
-
ARM
+關注
關注
134文章
9164瀏覽量
368625 -
電源管理
+關注
關注
115文章
6193瀏覽量
144797 -
Linux
+關注
關注
87文章
11342瀏覽量
210150
原文標題:PSCI接口規范
文章出處:【微信號:嵌入式ARM和Linux,微信公眾號:嵌入式ARM和Linux】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
評論