› 論壇總覽 › BeagleV-beta RISC-V 開源單板電腦 › OpenSBI 簡介與說明
- This topic has 2 則回覆, 1 個參與人, and was last updated 3 years, 4 months ago by johnson.
-
作者文章
-
2021 年 4 月 29 日 下午 2:13 #631
零、參考資料
適用於BeagleV的OpenSBI github專案連結:
https://github.com/starfive-tech/opensbi
WD的SBI說明投影片(OpenSBI最主要由Western Digital Corporation貢獻):
https://riscv.org/wp-content/uploads/2019/12/Summit_bootflow.pdf
RISC-V官方OpenSBI
https://github.com/riscv/opensbi
壹、前言
OpenSBI是一個介於M-Mode與S-Mode之間的應用界面,引述官方github說明:
The RISC-V Supervisor Binary Interface (SBI) is the recommended interface between:
A platform-specific firmware running in M-mode and a bootloader, a hypervisor or a general-purpose OS executing in S-mode or HS-mode.
A hypervisor running in HS-mode and a bootloader or a general-purpose OS executing in VS-mode.RISC-V二進制介面(SBI)主要針對以下情況:
1. 在M-mode下運行的特定於平台的韌體,以及在S-mode 或HS-mode 下執行的引導程式,管理程式或通用OS。
2. 在HS-mode下運行的管理程式以及在VS-mode下執行的引導加載程式或通用OS。其中,M-mode是指Machine Mode,Hypervisor是一個搭載不同作業系統的小程式,HS-mode 或 S-mode是指作業系統Operation System。
但上述說明似乎還是不淺顯易懂,依據筆者的理解,OpsnSBI是SBI規範下的一個實作軟體,他負責調度使用者或作業系統的命令給底層硬體。除此之外,還將各家廠商的平台進行整合,讓OpenSBI不會碎片化。
在更簡單的表示就是作業系統與硬體系統的媒介。
貳、簡介
上圖是傳統x86架構中的Privilege Ring。
在傳統的x86架構系統中,CPU為了更高的安全性以及避免系統硬體被惡意程式控制,創造一種中文名為”分級保護域” Privilege Level的架構,依據維基百科節錄:
電腦作業系統提供不同的資源訪問級別。在計算機體系結構中,Rings是由兩個或更多的特權態組成。在一些硬體或者微代碼級別上提供不同特權態模式的CPU架構上,保護環通常都是硬體強制的。Rings是從最高特權級(通常被叫作0級)到最低特權級(通常對應最大的數字) 依序排列。在大多數作業系統中,Ring 0擁有最高特權,並且可以和最多的硬體直接互動(比如CPU,快取記憶體)。
這種架構被證實是可行且有效的,因此如ARM、RISC-V也都採用這種方式來保護電腦的CPU與其他硬體設備。
在RISC-V架構中,由最低優先權到最高優先權分別是
User mode (U-mode)
Supervisor mode(S-mode)
Hypervisor mode(H-mode/HS-mode)
Firmware(M-mode)
RISC-V的系統優先層級對應到ARM架構如下圖所示:
除此之外,在電腦的作業系統架構中,Hypervisor又稱為虛擬機器監視器,是用來建立與執行虛擬機器的軟體、韌體或硬體。
上圖是Hypervisor Type1與Tpye2 在系統中的腳色。
在我們這個層級,由於還沒有OS在執行,因此我們的Hypervisor是Type1的型態,介於上層作業系統與下層硬體的中介。
RISC-V是一個將過去指令集去蕪存菁的新架構,其泛用性被各家廠商欽賴。然而這將無法避免整個RISC-V架構碎片化的問題(Fragmentation)。為了避免最終RISC-V變成各家廠商坐擁獨立標準的混亂指令集架構,由RISC-V Foundation統一出一個Supervisor規範名為SBI,即”Supervisor Binary Interface”。
參、RISC-V 系統啟動流程
在系統啟動之前,有些開發板會提供啟動模式的選項,可以透過指撥開關或電阻等等方式來實現0與1的硬體訊號。
在BeagleV中,電路圖就有提供BootMode的選擇
傳統的系統開機流程如下:
首先是圖中ROM方塊,又稱作Zero Stage Bootloader
CPU內部的ROM中會存放引導啟動程式,當開發版上電後,系統時脈開始震盪,CPU收到時賣訊號後,便會從這個ROM的位址(如0x08000000)開始讀取啟動程式碼。
這部分的啟動程式包含硬體中斷向量、SRAM的設定參數等等。
接著是LOADER部分,又稱作First Stage Bootloader
當SRAM被設定完成,CPU會把要執行的程式碼由外部的EEPROM或其他儲存媒介載入到SRAM中執行。由於CPU內部的ROM非常珍貴,因此比較主要的開機程序會在SRAM中執行。
這裡會再把板子上的DDRAM做初始化設定,並且載入下一階段的啟動程式。
下一步是RUNTIME程式,其全名是Runtime envoiroment,執行時系統
可以理解成所有應用程式會呼叫到共同程式碼,也就是標準Library。
在Linux系統中可以是glibc等等。
他是一種把半編譯的執行碼在目標機器上執行的環境,其包含SOC的安全設定以及Bootloader的設定等等。在RISC-V架構中,Runtime系統是由OpenSBI實作的。
最後在進入系統之前,要先載入Bootloader。
常見的Bootloader有U-Boot, GRUB, LinuxBoot等等。這層Bootloader做的事情是建立核心的檔案系統、網路設定、以及開機的選項設定等,有些也會加入顯示器設定等周邊裝置的參數。
最後,我們就能夠進入Operation System(OS)來做任何我們想要的操作。
RISC-V與傳統開機流程有些許不同,其中最大的差異是第二階段啟動
RISC-V的開機流程如下
:
將傳統系統動流程與RISC-V啟動流程互相比對後,會發現兩者其實大同小異,主要是中間OpenSBI是RISC-V特有的。
雖然ARM架構的系統在啟動時也有專屬的ATF(ARM Trusted Firmware) 做為RUNTIME的腳色,但在這邊OpenSBI還包含整合家廠商不同的韌體,並且規範統一的指令名稱。
肆、OpenSBI特色
OpenSBI 最主要的特色有以下幾點:
1. 分層結構設計使整體通用於各種結構
– 包含描述平台(platform)抽象概念(abstraction)的通用SBI函式庫,大部分被外部韌體或開機引導程序使用,如EDK2等。
– 特定平台函式庫 ,與核心函式庫相當但多了特定平台所需之驅動程式。
– 特定平台韌體參考,提供三種不同型態的RUNTIME韌體。
2.超廣泛的硬體支援
-支援32位元(RV32)與64位元(RV64)
-支援Hypervisor模式
-支援未對齊的加載/儲存處理(Misaligned load/store handling )
(因為未對齊的記憶體或資料位址會造成整體性能下降)
-支援丟失的CSR模擬
-支援使用PMP保護韌體(PMP: Physical Memory Protection)
那為什麼RISC-V架構的OpenSBI要這麼講求開發板 (Platform) 的概念呢?
因為RISC-V是一個開源的硬體架構,大家可以不用支付權利金使用指令集以及核心,但這一定會造成各家廠商擁有一定的能力開發後,導致碎片化發生,就是大家擁有各自的客製化指令集,或客製化的IC Layout,最後成為一盤散沙。Android作業系統在開發初期就經歷過類似的事件,一直到後期才逐漸統一。所以要避免碎片化,他們想出一套方法,讓每一個產品自己需要的平台專屬部分獨立出來,共用的部分則保留在主要SPI函式庫中。OpenSBI的資料庫架構如下圖所示:
圖中,最基本的SBI函式庫是libsbi.a,這是每個RISC-V平台都會用到的通用函式庫。
接著,廠商自己的平台會有自己的libplatsbi.a函式庫,最後,再將整個硬體客製化(platform specific)的韌體打包好使用。
伍、OpenSBI韌體型態
OpenSBI最後包好的韌體可以有三種型態,這三種型態的韌體都是基於開發板的,其分別是:
1. FW_PAYLOAD
-連結下一啟動階段的韌體
2.FW_JUMP
-可以跳躍到下一啟動階段的靜態位址的韌體
3.FW_DYNAMIC
-可以跳躍到下一啟動階段的動態位址的韌體
接下來會對三種型態的韌體作介紹。
FW_PAYLOAD
FW_PAYLOAD如同其名,是一個韌體載體。
他把RUNTIME(運行時系統,也就是library)與下一階段BootLoader包在一起。這麼做的好處可以直接覆蓋裝置樹(Device tree blob)設定,讓開機速度更快。
但缺點是當OpenSBI或BootLoader有更動,我們就要重新建構一個PAYLOAD,且沒有溝通機制讓LOADER與PAYLOAd做通訊。
而FW_PAYLOAD的啟動流程如上圖所示,會照順序從ROM>LOADER>FW_PAYLOAD>OS 進行啟動。
FW_JUMP
FW_JUMP型態的韌體與FW_PAYLOAD最大的差異除了沒有把OpenSBI與BootLoader包在一起之外,JUMP型態的韌體在啟動過程進行到LOADER階段,會同時載入RUNTIME以及BootLoader,這在使用QEMU進行模擬的情況非常好用。
但這種方法缺點是LOADER階段載入BootLoader的位址是寫死的,且與FW_PAYLOAD相同,這種型態的韌體也沒有與前一個開機階段互相溝通的機制。
FW_DYNAMIC
FW_DYNAMIC改善上述FW_JUMP的缺點,讓OpenSBI可以動態載入下一啟動階段。透過使用fw_dynamic_info結構的參數,包含版本、下一啟動階段位址、模式等等參數設定下一階段的流程。可以注意到struct fw_dynamic_info中第一項”magic”參數,它的功能是讓使用這個struct的程式可以利用magic與version參數來檢查引用的資料型態是否正確。
由於OpenSBI是在kernel之前的韌體,還沒有載入glibc或標準C/C++語言函式庫,因此像是class等宣告無法作用,只能用struct來撰寫相同功能。
但衍生出一個缺點,就是前一階段的啟動器需要注意fw_dynamic_info的資料內容與型態。
前言中有提到,RISC-V把整個電腦系統分成M-mode、S-mode以及U-mode,每個層級不能直接存取更底層的資源,需要透過ABI或library進行呼叫。但在OpenSBI中,沒有ABI也沒有library,只能夠過LOADER在M-mode存放資料存在暫存器,RUNTIME(OpenSBI)在S-mode中讀取暫存器的資料這種方法來傳遞資料。
FW_DYNAMIC利用”a2″暫存器把struct fw_dynamic_info 放進去,讓OpenSBI讀取。但雖然都是資料,卻又衍生出”Big ending/ Little ending” 也就是”位元組順序“的問題。所以在這底層階段,位元組的順序也需要考慮進去,可以說是非常仔細且嚴謹的。
陸、OpenSBI作為函式庫使用
OpenSBI 除了可以包裝成各種不同功能的韌體之外,也可以當作UEFI (Unified Extensible Firmware Interface) 的一環。EDK2(EDKII)是EFI的Development Kit,也就是EFI的開發環境,此開發環境把OpenSBI中的函式庫與LOADER連結在一起,讓擴充韌體可以完整使用OpenSBI中的所有函式庫,如libsbi.a、libsbiutils.a、libplatsbi.a等等。(OpenSBI Librery usage)
目前RISC-V實作的範例是由HPE(Hewlett Packard Enterprise)主導的開源EDK2,並且整合OpenSBI,其專案在Github上開源。
柒、結論
OpenSBI 是SBI的實作,但只提供執行時程式的韌體與函式庫。
得力於OpenSBI以開發平台為主的特性,可以容易的移植到新的SoC上。
此外,OpenSBI所引用的韌體是非強制性的,任何晶片提供廠可以實作自己專屬的,同時也不會強制執行任何開機引導程序。
2021 年 6 月 3 日 下午 12:05 #657關於”未對齊記憶體存取”的相關討論,可以參考RISC-V基金會中的google論壇討論:
https://groups.google.com/a/groups.riscv.org/g/hw-dev/c/F8tWQ2A-vd0?pli=1
文中提到,若有一個資料是12位元,對於4位元記憶體來說是有對齊的 (12%4 = 0)
但對於8位元記憶體來說,是沒有對齊的。
而任何位元對於單一位元記憶體來說都是有對齊的,因為任何數都整除1。
2021 年 6 月 27 日 下午 9:58 #678關於OpenSBI firmware的補充:https://github.com/riscv/opensbi/blob/master/docs/firmware/fw.md
-
作者文章
- 需要以回覆此篇主題...