2023年9月13日 星期三

原理NVM Express - NVM Command Set

NVM subsystem中,可能會存在多個controllers,每一個controller可能會去存取某些特定namespaceNamespace由多個logical blocks所組成,而logical blockscontroller存取data的最小單位。而一個logical blockssize為何,可以為512 bytes, 1 KiB, 4 KiB…等,主要透過Identify commandIdentify Namespace data structure(INDS)的內容可以得知,單位為bytes


如圖1所示,表列了所有NVM command的指令的種類,並且使用Opcode來區分FlushWriteRead Command為必須support(mandatory),其餘則為optionalHost必須在CSTS.RDY = 1的情況下才能提交I/O command

Figure 1. I/O command Set

 

而提交I/O commandSQ和回覆CQ的格式和Admin Command一樣,然後CDW10~CDW15還是根據不同的command有不同的欄位定義。

CompareReadVerifyWriteWrite Zeroes command中,如果Host在提交指令的時候設Limit Retry欄位為1,表示commanderror recovery時間的限制,不能retry太多次,而error recovery時間限制主要透過Set Feature – Error Recovery來設定。

 

Namespaces

Namespacelogical blocks的集合,logical block address編號0開始,直到namespace的最大的size,每個namespace都會有獨立的ID來表示(NSID)。而要如何得知NSID是否是有效(valid)的呢?主要透過Identify Controller Data Structure裡的Number of Namespaces(NN)欄位來得知,但是NSID 0是無效的,所以有效的NSID就是1 ~ NN,然後NSID 0xFFFFFFFF主要用來表示broadcast,也就是表示all namespace的意思。

 

NSID

如圖2所示,如果NSID介於1~NN則是valid NSID, 其餘的是invalid,然後valid NSID之中又包含AllocatedUnallocatedNSIDAllocated代表NSID指定到NVME Subsystem中存在的namespace, Unallocated NSID代表還沒指定到任何namespaceNSID的另外一個狀態就是ActiveInactive,如果此NSIDattach到某個controller,那麼此NSID則為active,反之則為inactive。那NSID彼此之間的關係是什麼呢? 首先可以看到紫色框框的部分,Unallocated NSID一定是Inactive的狀態,綠色框框的部分Allocated NSID可能是ActiveInactive,取決於是否有attach到任何controller

host發了一個帶著Inactive NSIDcommand,則controller會回error completion with status “Invalid Field。如果host發了一個帶著Invalid NSIDcommandcontroller會回error completion with status “Invalid Namespace or Format

Figure 2. NSID Types

 

NSID and Namespace Usage

如果Controllersupport Namespace Management, ANA ReportingNVM Sets的話,NSID必定不能重複,如果全部都沒有support的話,則(1) shared namespace的話NSID必須唯一,(2) 如果是private namespace的話則NSID可以重複。

ICDS.MNAN(Maximum Number of Allowed Namespaces)欄位如果為0的話,那麼NVM Subsystem中最大的allocated NSIDs就由ICDS.NN欄位來決定。

那麼要如何去尋找NVM Subsystem中有哪些active NSID? 有兩種方式,(1) 對每個supported NSID(MNAM or NN field)Identify Namespace Data Structure(INDS),如果回報非全04096 bytes則為active namespace,(2) 透過Identify – Active Namespace ID list(CNS 02h)來取得如3的List,這個list會列出目前狀態為activeNSID,其餘entry則需清為0list最多可以回報1024active NSID

Figure 3. Namespace List Format

 

那麼要如何去尋找NVM Subsystem中有哪些allocated NSID? 可以透過Identify - Allocated Namespace ID list(CNS 10h)來取得,格式和圖3一樣。

NSID可能在經過系統power off後會改變,所以host可以透過UUID or NGUID or EUI64來辨別是否和pweroff前,是否為同一個namesapce

 

Namespace Size, Capacity and Utilization

上述有提到host可以透過INDS來得知有哪些NSIDactive的狀態,除了得知狀態以外,structure裡面還包還含了一些資訊如下:

NSZE: Namespace Size,描述這個namespace總大小為何,單位為LBAs,而LBA編號為從0開始,所以此欄位回報值為n的話,就是從LBA 0 ~ LBA n-1

NCAP: Namespace Capacity,表示NSZE裡面最大可以有多少LBA被分配到namespace裡,正常來說NSZE等於NCAP

NUSE: Namespace Utilization,此欄位表示當前已經有多少LBA已經被分配到namespace裡。

Figure 4. Namespace Attribute

 

其中這三個欄位還會被NSFEATTHINP bit所影響,THINP全名應是為Thin Provisioning,意思就是NSZE的空間並不會一開始就全部都分配,而是只分配目前實際使用的空間的大小,當有寫入資料的時候再索取空間,所以當THINP1b的時候,NCAP值是會小於(或等於)NSZE的值,且NUSE必須隨時更新目前系統上實際使用了多少空間。如果THINP bit0b,則固定NSZE = NCAP = NUSE

 

Namespace Creation & Attachment

在介紹I/O command之前,首先先介紹一下Admin command中Namespace ManagementNamespace AttachmentNamespace Management可以create一個新的namespacedelete現存的namespace,Command格式如圖5所示,主要會用到DPTR欄位和Select欄位。

Figure 5. Namespace Management Command

如果Select為Create(00h)的話,DPTR會指向host所準備的Data Structure(圖6),主要記載著host想要create大小(NSZE)、LBA格式(FLBAS)和NMIC等等的資訊,NMIC主要用來決定此namespace為shared or private namespace。NSID欄位對於create來說是無效的,原因是因為NSID是由controller來決定,並且會在回覆completion的時候,在completion的CDW0回覆給host此次所create的namespace的NSID為何。當create動作完成,此NSID狀態為Allocated

如果Select為Delete(01h)的話,則NSID必須指定其中一個先前create過的namespace NSID,且不會使用到DPTR欄位。如果NSID為0xFFFFFFFF,則表示host想要delete所有已存在的namespace。當delete動作完成,此NSID狀態為Unallocated

Figure 6. Namespace Management - Data Structure

接下來介紹Namespace Attachment command,當上述create動作完成後,必須做attach到controller的動作,才能透過controller去存取namespace,其格式如圖7所示

Figure 7. Namespace Attachment Command Format


如果Select為Attach
(00h)的話,DPTR會指向host所準備的Controller List(圖8),主要記載著host想要attach的controller ID,NSID則指定先前create過的namespace。當attach動作完成,此NSID狀態為Active

如果Select為Detach(01h)的話,DPTR會指向host所準備的Controller List(圖8),主要記載著host想要detach的controller ID,NSID則指定先前create過的namespace。當detach動作完成,此NSID狀態為Inactive

Figure 8. Controller List Format

■ Write Command

Opcode為01h,格式如圖9所示,主要就是host想要將data寫到哪個LBA range,需要使用到欄位為NSID、DPTR、CDW10~CDW15。DPTR指向的是host所準備好的write data的data buffer base address,因此controller就可以知道去哪裡讀資料(controller read),然後在Starting LBA(SLBA)欄位填入欲寫入LBA的起始位置,然後長度由Number of Logical Blocks(NLB)決定,因此LBA range為 SLBA ~ SLBA+(NLB-1)。

Figure 9. Write Command Format 

■ Read Command

Opcode為02h,格式如圖10所示,主要就是host從哪個LBA range將想要的data讀出來,需要使用到欄位為NSID、DPTR、CDW10~CDW15。DPTR指向的是host所準備好的read data buffer base address,因此controller就可以知道要將資料(controller write)寫到何處,然後在SLBA欄位填入欲讀出LBA的起始位置,然後長度由NLB決定,因此LBA range為 SLBA ~ SLBA+(NLB - 1)

Figure 10. Read Command Format


■ Flush Command

Opcode為00h,主要是目的是要將之前寫在Volatile Write Cache(VWC)裡的data,寫到nand flash裡面。VWC基本上就是會暫存Write command的data,來縮短data寫入nand裡面的時間,來得到較好的performance。VWC可以透過ICDS.VWC[0](圖11)來得知controller是否有support,然後透過Set Feature - Volatile Write CacheWrite Cache Enable bit(WCE)來開啟VWC功能(圖12)。

Flush Command(圖13)並不會用到CDW10之後的欄位,因此為reserved,也因為不用帶任何data buffer,因此DPTR並不會使用到。

Figure 11. ICDS.VWC field

Figure 12. Set Feature - Volatile Write Cache

Figure 13. Flush Command Format


■ Write Uncorrectable Command

Opcode為04h格式如圖14所示主要是目的是將指定的LBA range標記為invalid(無效的),需要使用到欄位為NSID、CDW10~CDW12,透過SLBA和NLB欄位指定LBA range。如果host發出任何Read cmd到WriteUNC指定的range,controller必須回報error completion with status "Unrecovered Read Error "。如果要消除LBA的invalid的狀態,則host必須提交Write cmd到想要消除的LBA range。

Figure 14. Write Uncorrectable Command Format


■ Write Zeroes Command

Opcode為08h,格式如圖15所示,主要是目的是將指定的LBA range寫全0,但是資料並不是透過host給予,所以controller可以自己決定用什麼方式來實現,可能是用標記的方式或自己產生全0的data寫入Nand裡面,需要使用到欄位為NSID、CDW10~CDW12和CDW14、CDW15,透過SLBA和NLB欄位指定LBA range。如果host發出任何Read cmd到Write Zeroes指定的range,controller會回全0的data

Figure 15. Write Zeroes Command  Format


■ Compare Command

Opcode為05h,格式如圖16所示,主要就是host將想要比較的data準備好並與指定的LBA range做比較,需要使用到欄位為NSID、DPTR、CDW10~CDW12、 CDW14和CDW15。DPTR指向的是host所準備好的compare data buffer base address,因此controller就從哪裡讀取資料(controller read),然後由SLBA和NLB指定compare LBA range,並且由controller來執行compare的動作,如果比對結果一致則回覆Successful completion,不一致則回覆error completion with status "Compare Failure"。

Figure 16. Compare Command Format

■ Verify Command

Opcode為0Ch,格式如圖17所示,主要就是host想要確認資料的完整性,因此controller會需要將data從Nand裡面讀出來做integrity checks,所以verify屬於read的行為,需要使用到欄位為NSID、CDW10~CDW12、 CDW14和CDW15。Verify不需要從host給予data因此不需要DPTR,然後由SLBA和NLB指定verify的LBA range。


Figure 17. Compare Command Format


Reference: NVM Express Base Specification Revision 1.4c


沒有留言:

張貼留言

解析 NVM Express - 透過Linux OS 解析M.2 NVMe SSD

在之前,我撰寫了三篇有關NVMe的文章 ,分別是" 原理NVM Express - NVMe Submission Queue & Completion Queue (SQ & CQ) "、" 原理NVM Express - Admi...