馮軍波
(中航工業西安航空計算技術研究所,陜西西安,710068)
NVMe(Non-Volatile Memory express,非易失存儲器協議)是一種面向PCIe固態硬盤(SDD)的接口協議。最早于在2011年3月推出,由NVMe規范組織成員公司(如Intel、戴爾、三星、鎂光等)合作開發,用于主控軟件通過PCIe 鏈路與SSD進行高速數據傳輸。在最新的1.3版本中又增加了設備自檢、引導分區、虛擬化、主機操控散熱管理等新特點,改進了SSD的性能。在NVMe推出之前,傳統的SATA硬盤大都使用AHCI協議,讀寫速度在500M/s以下。AHCI協議具有較強的兼容性,可支持SATA總線與PCIe總線,但是當硬盤通過PCIe總線與處理器連接時,AHCI協議無法為PCIe SDD提供最佳的性能。而NVMe的規劃充分利用了PCIe SSD的低延遲與并行性,兼顧處理器平臺架構,最大程度的發揮了SDD的高性能,讀寫速度可超過1GB/s。本文描述了一種嵌入式飛騰4核CPU平臺下的NVMe固態硬盤驅動設計和固態硬盤硬件實現。實驗表明,該設計相較于之前的SATA固態硬盤極大的提高了數據的讀寫速度,增強了存儲系統的性能。
本系統的硬件環境主要包含兩部分,一個處理器模塊加一塊SSD,硬件設計的示意如圖1所示。其中的處理器模塊采用飛騰公司的FT2000-4,該處理器集成4個64位高性能核,最高主頻3.0GHz,設計中的工作主頻為1.0GHz,處理能力為16GIPS/Core@1GHz。

圖1 存儲系統邏輯結構示意圖
該系統中的SSD是一種典型的SOC(System on Chip)單機系統,模塊之間通過AXI高速和APB低速總線互聯互通,完成信息和數據的通信。SSD中還有固件(Firmware),用于調度各個硬件模塊,完成SSD產品所需要的功能,也包括數據從主機端到閃存端的寫入和讀取。SSD內部由PCIe GS9203主控制器芯片和Nand Flash陣列組成。PCIe主控芯片為28nm工藝,主控CPU具有兩個 ARM Cortex R4 CP內核,支持PCIe Gen3 x4和NVMe 1.3c協議標準,有8個Flash通道, Flash芯片采用國產長江存儲科技有限責任公司的TLC X1-9050 NAND FLASH,是中國首款64層3D NAND閃存。
NVMe驅動依據功能的不同,可劃分為驅動接口模塊,初始化模塊和命令執行模塊。其中命令執行模塊為核心,設備初始化模塊涉及控制器初始化、數據存儲鏈表創建、命令隊列的設置,驅動接口模塊用于處理上層文件系統對設備的訪問。驅動的架構如圖2所示。

圖2 NVMe驅動架構圖
本系統中,主機端在上電后首先運行天脈3嵌入式實時操作系統,運行過程中調用NVMe驅動的初始化模塊,完成硬件和軟件的準備工作。隨后在啟動文件系統時將驅動接口注冊到文件系統的IO函數中,最后應用軟件調用文件操作函數時會調用到驅動讀寫接口。
NVMe控制器初始化的主要內容是找到控制器,通過配置其內部的寄存器使其就緒,并在主機端的內存上創建命令隊列,創建數據緩沖鏈表,并完成MSI中斷的初始化和注冊。
2.1.1 NVMe寄存器配置
NVMe作為一種寄存器級別的接口連接到PCIe接口上,其寄存器配置包括PCIe寄存器配置和NVMe控制器寄存器配置。
PCIe寄存器配置主要是PCI header、和PCI Capabilities的配置。PCI header類型分為兩種,type0表示設備,type1表示橋。NVMe控制器屬于設備則定義為type0類型。當系統完成PCIe的初始化且設備被掛到總線上時,PCI header中的設備ID與廠商ID會有固定的值,該值是設備的唯一標識。基地址寄存器會寫有地址值,該值作為訪問設備其他寄存器的基址。設備各項功能的設置是通過功能指針寄存器來完成的。功能指針寄存器所指向的是位置是配置寄存器組鏈表的第一個條目[1]。常用的能力設置包括對NVMe控制器的電源管理、中斷管理(包括MSI、MSI-X)的設置,設置完之后再配置命令寄存器使能設備。
NVMe控制器寄存器的設置主要是對表1中所列舉的寄存器進行賦值,寄存器描述見表1。

表1 NVMe控制器寄存器功能描述表
2.1.2 NVMe隊列創建
NVMe命令隊列按照類型可以分為Admin命令隊列與I/O命令隊列,讀寫電子盤通常使用IO隊列。NVMe協議針支持多達65535個IO命令隊列,每一個隊列可容納64K 條命令。IO命令隊列按照用途不同可分為命令提交隊列SQ和命令完成隊列CQ。SQ隊列中一條命令的內容包括操作碼、ID、要操作盤的起始塊號、塊數量、數據所在的緩沖等。CQ隊列中的一條命令包括下一條命令位置、下一條命令ID當前命令ID、當前命令狀態等。一個隊列即是主機端內存上的一段連續的環形緩沖,在初始化NVMe時向系統申請內存空間,然后將空間的基地址控制器的ASQ寄存器與ACQ寄存器。每一個隊列都有對應QID、虛擬地址、物理地址、長度、頭指針、尾指針和相應的門鈴寄存器。本驅動定義了隊列信息結構如下:


命令隊列在多核處理器上可采用兩種設計方法,一種是一個核上安排一個SQ與一個CQ。另一種為一個核上安排一個CQ多個SQ。本驅動運行在一個核上,采用第一種方式。隊列通過對應的門鈴寄存器,在host與控制器間傳遞消息。
2.1.3 創建數據緩沖表
NVMe的數據尋址方式包括物理頁表(PRP)和分散聚合表(SGL),本驅動設計采用PRP方式。PRP表中的每一項是一個64位指針,格式為頁地址+頁內偏移,每一項指向一個內存頁,頁的大小在CC寄存器中定義,通常一頁的大小為4KB,因此在進行數據傳輸時,有時會要求數據緩沖的起始地址須4KB對齊。
命令的Dword6~Dword9定義了PRP1、PRP2兩個指針,通過PRP2可以指向PRP List。PRP算法根據數據的長度有三種模式,如圖3所示。

圖3 數據緩沖PRP示意圖
當數據小于等于4KB時只需將PRP1指向數據所在的地址即可;若數據大于4KB小于等于8KB則須將PRP1指向數據所在的地址,PRP2指向數據所在地址加上4K位置;若數據大于8K,則需將PRP1指向數據所在地址,PRP2指向PRP List。
NVMe命令按照類型可以分為Admin命令與I/O命令。Admin命令主要負責管理NVMe控制器,IO命令負責操作固態硬盤,常用的Admin命令包括identify、創建SQCQ、刪除SQCQ。常用的IO命令包括Read 、Write、Flush。
圖4為NVMe 命令執行過程。主機寫命令道SQ隊列,通過TailDoorbell通知NVMe控制器,控制器獲得命令并執行,將命令寫入CQ隊列(無論命令是否執行成功),產生中斷提醒主機命令已完成。主機處理CQ中的命令信息,最后更新HeadDoorbell告知控制器命令已處理。

圖4 NVMe命令執行過程示意圖[3]
為解決多任務對共享資源的互斥訪問,在寫命令到SQ后,提交命令的任務應先等待資源可用的信號量,待控制器執行完一條命令后會向主機發出MSI中斷,主機在MSI中斷服務函數中處理完成隊列,最終釋放資源信號量。
本驅動應用于某軍用飛機的數據共享系統,為其中的數據庫管理軟件提供存儲服務。操作系統為國產自主可控的天脈3多分區RTOS,使用場景如圖5所示。

圖5 NVMe驅動應用場景示意圖
在天脈3核心OS啟動過程中完成NVMe控制器的初始化、命令隊列以及數據緩沖PRP表的創建工作,隨后將驅動接口注冊到文件系統中。當分區應用數據庫管理軟件中的任務使用標準IO進行文件操作時,由文件系統調用驅動的接口模塊實現對NVMe電子盤的讀寫訪問。本設計中NVMe驅動最大支持單次DMA傳輸512KB數據,當數據大于512KB時,驅動會將數據以512KB為單位分割,進行多次傳輸。在PCIe3.0接口4x下進行讀寫速度測試,測量數據如圖6所示。

圖6 NVMe驅動讀寫電子速度圖
從實驗結果可知,當數據量很小時,讀寫速度也較慢,在數據量接近或大于設備支持的單次最大處理的字節數512KB時,讀寫速度穩定在1000MB/s上下,驅動表現出良好的性能。
NVMe協議定義了基于PCIe的SSD的寄存器接口、命令集合與功能集合,通過PCIe接口將I/O命令和響應映射到主機中的共享內存。相較于SATA或AHCI協議,NVMe接口支持與多核處理器的并行I/O,實現高吞吐量,緩解了CPU瓶頸。NVMe電子盤帶來高速的讀寫能力時,相比SAS和SATA電子盤在價格上就更昂貴一些,而且消耗的功率可能也會增加,同時在容量方面不及普通硬盤最大只有4TB,不過在很多高性能領成為好的選擇。本文實現的國產嵌入式實時操作系統天脈3下的NVMe驅動,提升了航空裝備在存儲系統中的性能,對于嵌入式機載領域的數據存儲有著很高的應用價值。