<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          NVMe技術基礎知識

          共 9094字,需瀏覽 19分鐘

           ·

          2021-10-21 23:40


          內容提要:NVM Express(NVMe),或稱非易失性內存主機控制器接口規(guī)范(英語:Non Volatile Memory Host Controller Interface Specification,縮寫:NVMHCIS),是一個邏輯設備接口規(guī)范。它是與AHCI類似的、基于設備邏輯接口的總線傳輸協(xié)議規(guī)范(相當于通訊協(xié)議中的應用層),用于訪問通過PCI Express(PCIe)總線附加的非易失性存儲器介質(例如采用閃存的固態(tài)硬盤驅動器),雖然理論上不一定要求 PCIe 總線協(xié)議。


          1. 綜述

          NVMe over PCIe協(xié)議,定義了NVMe協(xié)議的使用范圍、指令集、寄存器配置規(guī)范等。

          1.1 名詞解釋


          1.1.1 Namespace

          Namespace是一定數量邏輯塊(LB)的集合,屬性在Identify Controller中的數據結構中定義。

          1.1.2 Fused Operations

          Fused Operations可以理解為聚合操作,只能聚合兩條命令,并且這兩條命令在隊列中應保持相鄰順序。協(xié)議中只有NVM指令才有聚合操作。還需要保證聚合操作的兩條命令讀寫的原子性,參考Compare and Write例子。

          1.1.3 指令執(zhí)行順序

          除了聚合操作(Fused Operations),每一條SQ中的命令都是獨立的,不必考慮RAW等數據相關問題,即使考慮,也是host應該解決的問題。

          1.1.4 寫單元的原子性

          控制器需要支持寫單元的原子性。但有時也能通過host配置Write Atomicity feature,減小原子性單元的大小,提高性能。

          1.1.5 元數據

          數據的額外信息,相當于提供校驗功能??蛇x的方式。

          1.1.6 仲裁機制

          用來選擇下一次執(zhí)行的命令的SQ的機制,三種仲裁方式:

          • RR(每個隊列優(yōu)先級相同,輪轉調度)

          • 帶權重的RR(隊列有4種優(yōu)先級,根據優(yōu)先級調度)

          • 自定義實現

          1.1.7 邏輯塊(LB)

          NVMe定義的最小的讀寫單元,2KB、4KB……,用LBA來標識塊地址,LBA range則表示物理上連續(xù)的邏輯塊集合。

          1.1.8 Queue Pair

          由SQ(提交隊列)與CQ(完成隊列)組成,host通過SQ提交命令,NVMe Controller通過CQ提交完成命令。

          1.1.9 NVM 子系統(tǒng)

          NVM子系統(tǒng)包括控制器、NVM存儲介質以及控制器與NVM之間的接口。

          1.2 NVMe SSD

          1.2.1基本架構

          整體來看,NVMe SSD可以分為三部分,host端的驅動(NVMe官網以及l(fā)inux、Windows已經集成了相應的驅動)、PCIe+NVMe實現的控制器以及FTL+NAND Flash的存儲介質。



          1.2.2 NVMe控制器

          NVMe控制器實質上為DMA + multi Queue,DMA負責數據搬運(指令+用戶數據),多隊列負責發(fā)揮閃存的并行能力。



          2. PCIe寄存器配置

          NVMe over PCIe,通過利用PCIe總線實現數據交互的功能,實現對物理層的抽象功能。

          2.1 PCIe總線的基本結構

          PCIe總線分為三層,物理層,數據鏈路層,處理層(類似于計算機網絡的分層結構),通過包來轉發(fā)數據。NVMe協(xié)議定義的內容相當于PCIe的上一層應用層,處于應用層。PCIe給NVMe提供了底層的抽象。

          NVMe SSD相當于一個PCIe的端設備(EP)。



          2.2 寄存器配置

          在協(xié)議中主要定義了PC header、PCI Capabilities和PCI Express Extended Capabilities三部分內容。

          具體在host內存中會占有4KB,結構如下:



          2.2.1 PCI header

          PCI header有兩種類型,type0表示設備,type1表示橋。NVMe 控制器屬于EP,所以定義為type0的類型。共64KB,如下圖:



          2.2.2 PCI Capabilities

          這里配置了PCI Capbilities,包括電源管理、中斷管理(MSI、MSI-X)、PCIe Capbilities。

          2.2.3 PCI Express Extended Capabilities

          這里配置有關錯誤恢復等高級功能。

          3. NVMe寄存器配置

          3.1 寄存器定義

          NVMe寄存器主要分為兩部分,一部分定義了Controller整體屬性,一部分用來存放每組隊列的頭尾DB寄存器。

          1. CAP——控制器能力,定義了內存頁大小的最大最小值、支持的I/O指令集、DB寄存器步長、等待時間界限、仲裁機制、隊列是否物理上連續(xù)、隊列大小;

          2. VS——版本號,定義了控制器實現NVMe協(xié)議的版本號;

          3. INTMS——中斷掩碼,每個bit對應一個中斷向量,使用MSI-X中斷時,此寄存器無效;

          4. INTMC——中斷有效,每個bit對應一個中斷向量,使用MSI-X中斷時,此寄存器無效;

          5. CC——控制器配置,定義了I/O SQ和CQ隊列元素大小、關機狀態(tài)提醒、仲裁機制、內存頁大小、支持的I/O指令集、使能;

          6. CSTS——控制器狀態(tài),包括關機狀態(tài)、控制器致命錯誤、就緒狀態(tài);

          7. AQA——Admin 隊列屬性,包括SQ大小和CQ大??;

          8. ASQ——Admin SQ基地址;

          9. ACQ——Admin CQ基地址;

          10. 1000h之后的寄存器定義了隊列的頭、尾DB寄存器。

          3.2 寄存器理解

          1. CAP寄存器標識的是Controller具有多少能力,而CC寄存器則是指當前Controller選擇了哪些能力,可以理解為CC是CAP的一個子集;如果重啟(reset)的話,可以更換CC配置;

          2. CC.EN置一,表示Controller已經可以開始處理NVM命令,從1到0表示Controller重啟;

          3. CC.EN與CSTS.RDY關系密切,CSTS.RDY總是在CC.EN之后由Controller改變,其他不符合執(zhí)行順序的操作都將產生未定義的行為;

          4. Admin隊列有host直接創(chuàng)建,AQA、ASQ、ACQ三個寄存器標識了Admin隊列,而其他I/O隊列則有Admin命令創(chuàng)建(eg,創(chuàng)建I/O CQ命令);

          5. Admin隊列的頭、尾DB寄存器標識為0,其他I/O隊列標識由host按照一定規(guī)則分配;只有16bit的有效位,是因為隊列深度最大64K。

          4. 內存數據結構

          4.1 SQ與CQ的詳細定義

          4.1.1 空隊列



          4.1.2 滿隊列

          判斷隊列滿可以有多種方法,協(xié)議中規(guī)定的是頭指針比尾指針大一,所以隊列滿時,空余一個元素。



          4.1.3 隊列性質

          1. 隊列大小有16bit,最小隊列大小為2個元素(因為滿隊列的定義方式,所以最小為2個元素),對于I/O隊列,最大隊列大小為64k;對于Admin隊列,最大隊列為4k;

          2. QID來標識唯一ID,16bit,由host分配;

          3. host可以修改隊列優(yōu)先級(如果支持的話),共四級,U、H、M、L;

          4.2 仲裁機制

          4.2.1 RR

          RR仲裁,Admin SQ與I/O SQ優(yōu)先級相同,控制器每次可以選擇一個隊列中的多個命令(Arbitration Burst setting)。



          4.2.2 帶有優(yōu)先權的RR

          有3個嚴格的優(yōu)先權,Priority1 > Priority2 > Priority3,在這三個優(yōu)先級隊列中,高優(yōu)先級的隊列中如果有命令,則優(yōu)先執(zhí)行(非搶占式)。



          4.2.3 其他仲裁方式

          Vendor Specific。

          4.3 數據尋址方式(PRP和SGL)

          4.3.1 PRP

          NVMe把Host的內存分為頁的集合,頁的大小在CC寄存器中配置,PRP是一個64位的內存物理地址指針,結構如下:



          最后兩位為0,指四字節(jié)對齊;(n:2)位表示頁內內偏移。

          舉個例子,內存頁大小位4KB,則(11:2)表示頁內偏移。

          PRP尋址有兩種方式,直接用PRP指針尋址,通過PRP List尋址。當使用PRP List尋址時,偏移必須為0h,每一個PRP條目表示一個內存頁,如下:



          Admin命令的數據地址只能采取PRP的方式,I/O命令的數據地址既可以采取PRP的方式,又可以采取SGL的方式。Host在命令中會告訴Controller采用何種方式。具體來說,如果命令當中DW0[15:14]是0,就是PRP的方式,否則就是SGL的方式。

          命令的Dword6~Dword9只定義了PRP1、PRP2兩個數據指針,通過PRP條目可以指向PRP List。如下圖:



          在上面的例子中,PRP1直接指向內存頁,PRP2指向PRP List存在的地址,在PRP List中存有數據的真正的地址。

          更詳細的說

          協(xié)議中PRP Entry是一個指向物理內存頁的指針。PRP被用作NVMe Controller和PC內存之間進行數據傳輸。PRPEntry是固定大小的(8B)。

          首先,明確兩個概念,PRP Entry 為PRP指針,PRP List為PRP列表指針,示意圖如下:


          根據每次傳輸數據的大小,以及PRP指針的偏移(offset)可以分為以下五種情況:

          4.3.2 SGL

          SGL是另外一種索引內存的數據結構。SGL由若干個SGL段組成,SGL段又由若干個SGL描述符組成,所以SGL描述符是SGL數據結構的基本單位。

          目前定義的SGL描述符有6種:

          1. SGL 數據描述符,用來索引數據塊地址,host內存;

          2. SGL 垃圾數據描述符,用來索引無用數據;

          3. SGL 段描述符,用來索引下一個SGL段;

          4. SGL 最后一個段描述符,用來索引最后一個SGL段;

          5. keyed SGL 數據描述符;

          6. Transport SGL 數據描述符;


          在上面SGL例子中,共有3個SGL段,用到了4種SGL描述符。Host需要往SSD中讀取13KB的數據,其中真正只需要11KB數據,這11KB的數據需要放到3個大小不同的內存中,分別是:3KB,4KB和4KB。

          4.3.3 比較PRP與SGL

          無論是PRP還是SGL,本質都是描述內存中的一段數據空間,這段數據空間在物理上可能連續(xù)的,也可能是不連續(xù)的。Host在命令中設置好PRP或者SGL,告訴Controller數據源在內存的什么位置,或者從閃存上讀取的數據應該放到內存的什么位置。

          SGL和PRP本質的區(qū)別在于,一段數據空間,對PRP來說,它只能映射到一個個物理頁,而對SGL來說,它可以映射到任意大小的連續(xù)物理空間,具有更大的靈活性,也能夠描述更大的數據空間。如下圖:


          5. NVMe協(xié)議定義的命令

          5.0 命令執(zhí)行過程

          命令由host提交到內存中的SQ隊列中,更新TDBxSQ后,NVMe控制器通過DMA的方式將SQ中的命令(怎么取,如何取,取多少,因設計而異)取到控制器緩沖區(qū),執(zhí)行命令;執(zhí)行完成后,根據執(zhí)行狀態(tài),組裝完成命令,仍然通過DMA的方式將完成命令寫入內存CQ的隊列中;NVMe控制器通過MSI-X中斷方式通知host已完成命令;最后,host處理CQ命令,更新控制器中HDBxCQ,標識著命令真正完成。

          5.1 命令分類

          命令分為Admin指令與NVM指令(I/O指令)。

          Admin指令只能提交到Admin Controller中,主要負責管理NVMe控制器,也包含對NVM的一些控制指令。

          NVM 指令只能提交到I/O Controller中,主要負責完成數據的傳輸。

          在1.0e版本中,Admin指令有15條(3條與NVM相關),NVM指令有6條;在1.3d版本中,Admin指令有15條(3條與NVM相關),NVM指令有11條。

          5.2 命令通用格式

          命令均為64字節(jié),具有相同的格式,某些字段根據命令的不同有不同的定義。

          Dword0

          CID、傳輸方式、聚合操作、操作碼

          1

          NID(命名空間ID)

          2

          保留

          3

          保留

          4、5

          元數據指針(MPTR)

          6-9

          數據指針(DPTR)

          10-15

          根據命令指定

          完成命令同樣具有相同的格式,某些字段根據命令的不同有不同的定義。

          Dword0

          根據命令指定

          1

          保留

          2

          SQID、SQ頭指針

          3

          狀態(tài)域、P位、CID


          5.3 Admin 指令

          Admin指令與NVM指令根據放置的的隊列組(Queue Pair)來區(qū)分,Admin指令在Admin CQ與SQ里,NVM指令在I/O CQ與SQ里。

          通過Dword0中的8位操作碼定義不同指令,注意并不是絕對的順序增加(eg,沒有03h)。每一種指令都對應有其完成命令,通過SQID(提交隊列ID)+CID(命令ID)唯一標識完成的命令。

          操作碼

          指令

          作用

          00h

          刪除I/O SQ,

          釋放SQ空間

          01h

          創(chuàng)建 I/O SQ,

          保存host分配給SQ的地址、隊列優(yōu)先權、隊列大小

          02h

          獲取日志,

          返回所選日志頁于緩沖區(qū)

          04h

          刪除 I/O CQ,

          釋放CQ空間

          05h

          創(chuàng)建 I/O CQ,

          保存host分配給CQ的地址、中斷向量、隊列大小等

          06h

          Identify

          返回關于controller與namespace能力和狀態(tài)的數據結構(2k字節(jié))

          08h

          撤銷,

          用來撤銷之前完成的指令,best-effort

          09h

          設置features

          根據FID設置相應的features

          0Ah

          獲取 features,

          根據FID返回隊列數量、仲裁信息等

          0Ch

          異步事件請求,

          Controller向host報告運行信息(error or health)

          10h

          固件激活,

          驗證下載的鏡像,提交到Firmware Slot(1-7)中

          11h

          固件鏡像下載,

          下載固件鏡像


          Note:

          • Admin隊列是通過配置ASQ等寄存器創(chuàng)建的

          • 先創(chuàng)建CQ再創(chuàng)建SQ

          5.4 NVM指令

          NVMe控制器讀寫的最小單元是LB,層次圖如下:

          NVM指令與Admin指令結構完全相同,也是通過Dword0中的8位操作碼來定義不同指令。

          操作碼

          指令

          作用

          00h

          Flush

          將數據(和元數據)提交到NVM中,所有命令都要執(zhí)行

          01h

          Write

          將數據(和元數據)寫入NVM中

          02h

          Read

          讀NVM中的數據(和元數據)

          04h

          Wirte Uncorrectable

          標記無效數據塊

          05h

          Compare

          比較從NVM端讀出的數據和比較數據緩沖區(qū)的數據

          09h

          Dataset Management

          標識一定范圍數據的特點,eg,頻繁讀、頻繁寫(提升性能)


          6 控制器結構

          控制器從功能上可以分為三類,I/O、Admin和Discovery。


          在實現過程中,Admin 控制器只有一個,負責管理控制器及其他控制功能??刂破髦皇浅橄蟮母拍?,應用于具體的實現中,可能是一個具體的模塊,也可能多個模塊。

          控制器主要的作用是實現對NVMe定義命令的翻譯,從而實現數據傳輸、狀態(tài)控制等功能。

          6.1 命令執(zhí)行過程

          1. host將命令(1條或者多條)寫入提前分配好的SQ中;

          2. 更新對應SQ的DB寄存器;

          3. NVMe控制器取SQ中命令(通過HDB和TDB可以判斷是否有未完成命令);

          4. NVMe控制器執(zhí)行命令;

          5. NVMe 控制器在命令完成后,將完成命令(可能執(zhí)行成功,也可能失敗,但都會返回完成命令)寫入host內存SQ對應的CQ中;

          6. NVMe 控制器根據實現的中斷方式,提醒host命令已完成;

          7. host響應中斷,處理完成命令;

          8. host 更新對應CQ的DB寄存器。



          6.2 重啟(Reset)

          6.2.1 Controller level

          Controller重啟可能發(fā)生在PCIe總線重啟、PCI重啟、控制器CC.EN從1到0重啟。當重啟發(fā)生時:

          1. 所有的I/O SQ和CQ都被刪除;

          2. 所有未完成的指令(Admin和I/O)應該執(zhí)行撤銷操作;

          3. Controller處于idele狀態(tài),CSTS.RDY清0;

          4. AQA、ASQ、ACQ不受影響。

          重啟后,host操作:

          1. 更新寄存器狀態(tài);

          2. 將CC.EN置1;

          3. 等待CSTS.RDY置1;

          4. 使用Admin命令配置Controller;

          5. 創(chuàng)建I/O CQ和SQ;

          6. 執(zhí)行正常的I/O指令。

          6.2.2 Queue level

          隊列水平的重啟,即,刪除該隊列,再重新創(chuàng)建一個新隊列。刪除隊列的時候,host應該保證隊列處于idle狀態(tài)(所有命令均已完成——接收到了完成命令),否則的話,可能會導致CQ接收不到提交命令的完成命令。

          6.3 中斷

          在Controller完成SQ命令后,根據執(zhí)行狀態(tài),將結果組裝成完成命令寫入CQ中,Controller通過中斷機制通知Host處理完成命令。

          NVMe協(xié)議中支持的中斷方式有4種,pin-based、Single MSI、Multi-message MSI和MSI-X,協(xié)議推薦采用MSI-X中斷方式,能夠支持更多的中斷向量(2K)。

          MSI-X允許每一個CQ發(fā)送自己的中斷信息(相比于發(fā)一條中斷信息提醒全部CQ隊列有很大的優(yōu)勢)。在產生MSI-X中斷信息前,需要檢查該中斷在相應寄存器種不被屏蔽。

          6.4 Controller初始化

          Controller的初始化過程:

          1. 設置PCI和PCIe寄存器;

          2. 等待CSTS.RDY變?yōu)椋?/span>

          3. 配置AQA、ASQ、ACQ寄存器;

          4. 配置CC寄存器;

          5. 將CC.EN置1;

          6. 等待CSTS.RDY置1

          7. Host通過Identify命令,確定Controller的數據結構、確定Namespace的數據結構;

          8. Host通過get features(協(xié)議中是set features,待研究)獲取I/O SQ和CQ信息,然后配置中斷機制;

          9. Host分配適當的I/O CQ、SQ隊列;

          10. 如果Host希望獲取Controller的錯誤或健康信息,可以添加異步事件請求命令。

          Controller 關機

          正常關機:

          1. Host停止提交新的I/O命令,但允許未完成的命令繼續(xù)完成;

          2. Host刪除所有I/O SQ,刪除所有SQ隊列后,所有未完成的命令將被撤銷;

          3. Host刪除所有I/O CQ;

          4. Host將CC.SHN置01b,表示正常關機;關機程序完成時,將CSTS.SHST置10b。

          突然關機:

          1. Host停止提交新的I/O命令;

          2. Host將CC.SHN置10b,表示突然關機;關機程序完成時,將CSTS.SHST置10b

          6.5 host端命令實例

          6.5.1 創(chuàng)建命令



          6.5.2 處理完成命令



          6.6 NVMe與PCIe交互實例(分析包結構)

          以Host發(fā)出read命令為例。

          1. Host準備了一個Read命令給SSD:



          分析該包,Host需要從起始LBA 0x20E0448(SLBA)上讀取128個DWORD (512字節(jié))的數據,讀到哪里去呢?PRP1給出內存地址是0x14ACCB000。這個命令放在編號為3的SQ里 (SQID = 3),CQ編號也是3 (CQID = 3)

          1. Host通過寫SQ的Tail DB,通知Controller來取命令:

          上圖中,上層是NVMe層,下層是PCIe傳輸層的TLP。Host想往SQ Tail DB中寫入的值是5。PCIe是通過一個Memory Write TLP來實現Host寫CQ的Tail DB的。該Tail DB寄存器映射在Host的內存地址為F7C11018,由于NVMe 的寄存器映射到了Host內存中,所以可以根據這個地址寫入寄存器值。

          1. SSD收到通知,去Host端的SQ中取指。

          PCIe是通過發(fā)一個Memory Read TLP到Host的SQ中取指的。可以看到,PCIe需要往Host內存中讀取16個DWORD的數據(一個NVMe指令大?。?,

          1. SSD執(zhí)行讀命令,把數據從閃存中讀到緩存中,然后把數據傳給Host:

          SSD是通過Memory write TLP 把Host命令所需的128個DWORD數據寫入到Host命令所要求的內存中去。SSD每次寫入32個DWORD,一共寫了4次。

          1. SSD往Host的CQ中返回狀態(tài):

          SSD是通過Memory write TLP 把16個字節(jié)的命令完成狀態(tài)信息寫入到Host的CQ中。

          1. SSD采用中斷的方式告訴Host去處理CQ:

          上圖使用的是MSI-X中斷方式。這種方式將中斷信息和正常的數據信息一樣,PCIe打包把中斷信息告知Host。SSD還是通過Memory Write TLP把中斷信息告知Host,這個中斷信息長度是1DWORD。

          1. Host處理相應的CQ

          2. Host處理完相應的CQ后,需要更新SSD端的CQ Head DB告知SSD處理

          完成:


          Host還是通過Memory Write TLP更新SSD端的CQ Head DB。

          該過程完整的包流程如下:


          7. NVMe features

          7.1 固件(Firmware)更新過程

          1. 將固件下載到Controller中(使用 Firmware Image Download命令);

          2. Host提交Firmware Activate命令(也可以激活之前版本的Controller鏡像);

          3. Controller reset;

          4. reset完成后,Host重新初始化Controller,包括Host重新分配I/O隊列,與reset步驟相同。

          7.2 元數據(Metadata)傳輸

          元數據的使用并沒有強制規(guī)定,最經常的使用方法是用做端到端數據的保護信息。有兩種傳輸元數據的方式,一種可以作為LB數據塊的一部分,如下圖:



          另一種可以單獨作為一個邏輯塊傳輸,如下圖:



          7.3 端到端的數據保護

          端到端,一端指主機的內存空間,一端指閃存空間(NVM)。數據傳輸的兩個環(huán)節(jié)如下圖:


          數據在PCIe上傳輸的時候,由于信道噪聲的存在(說白了就是存在干擾),可能導致數據出錯;另外,Controller閃存之間,數據也可能發(fā)生錯誤。采用元數據進行數據的保護是最常用的一種手段。

          充當保護數據角色的元數據結構如下:



          其中,Guard為16bit的CRC校驗碼,Application Tag與LBAT相關,Reference Tag將用戶數據和地址(LBA)相關聯(lián)。下圖為以512bytes的數據塊為例:



          那么按照排列組合,共有四種保護情況(1帶2帶、1不帶2不帶、1帶2不帶、1不帶2帶)。但由于協(xié)議中控制保護信息的只有兩個字段(1. 是否采用保護 2. PRACT位),只有三種情況,如下圖(是以寫命令為例,讀命令相同):


          原文鏈接:

          https://zhuanlan.zhihu.com/p/347599423

          作者:Fappy

          Linux學習指南

          有收獲,點個在看?

          瀏覽 115
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  精品精品国内视频 | 男人美女一起搞基视频网站 | 亚洲va中文字幕 亚洲成人性爱网站 | 中文字幕 - 色网 | 国产精品直接观看 |