NVMe概述html
NVMe是一個針對基於PCIe的固態硬盤的高性能的、可擴展的主機控制器接口。json
NVMe的顯著特徵是提供多個隊列來處理I/O命令。單個NVMe設備支持多達64K個I/O 隊列,每一個I/O隊列能夠管理多達64K個命令。緩存
當主機發出一個I/O命令的時候,主機系統將命令放置到提交隊列(SQ),而後使用門鈴寄存器(DB)通知NVMe設備。數據結構
當NVMe設備處理完I/O命令以後,設備將處理結果寫入到完成隊列(CQ),並引起一箇中斷通知主機系統。架構
NVMe使用MSI/MSI-X和中斷聚合來提升中斷處理的性能。app
NVMe驅動概述異步
NVMe驅動是一個C函數庫,可直接連接到應用程序從而在應用與NVMe固態硬盤之間提供直接的、零拷貝的數據傳輸。這是徹底被動的,意味着不會開啓線程,只是執行來自應用程序自己的函數調用。這套庫函數直接控制NVMe設備,經過將PCI BAR寄存器直接映射到本地進程中而後執行基於內存映射的I/O(MMIO)。I/O是經過隊列對(QP)進行異步提交,其通常的執行流程跟Linux的libaio相比起來,並不是徹底不一樣。函數
NVM Express(NVMe)是一個寄存器級接口,容許帶內主機軟件與NVM子系統通訊。NVMe管理界面(NVMe-MI)容許管理控制器經過一個或多個外部接口與NVMe NVM子系統進行帶外通訊。性能
NVMe是一種Host與SSD之間通信的協議測試
圖1:NVMe管理接口協議分層
NVMe-MI利用管理組件傳輸協議(MCTP)做爲命令傳輸和利用現有的MCTP SMBus / I2C和PCIe綁定物理層。
NVMe是爲SSD所生的。NVMe出現以前,SSD絕大多數走的是AHCI和SATA的協議,後者實際上是爲傳統HDD服務的。與HDD相比,SSD具備更低的延時和更高的性能,AHCI已經不能跟上SSD性能發展的步伐了,已經成爲制約SSD性能的瓶頸。
跟ATA spec中定義的命令相比,NVMe的命令個數少了不少,徹底是爲SSD量身定製的。
NVMe有三寶:Submission Queue (SQ),Completion Queue(CQ)和Doorbell Register (DB)。 SQ和CQ位於Host的內存中,DB則位於SSD的控制器內部。上圖:
SQ和CQ在Host的memory中以及DB在SSD端,上圖中的NVMe Subsystem通常就是SSD。
SQ位於Host內存中,Host要發送命令時,先把準備好的命令放在SQ中,而後通知SSD來取;CQ也是位於Host內存中,一個命令執行完成,成功或失敗,SSD總會往CQ中寫入命令完成狀態。
DB又是幹什麼用的呢?Host發送命令時,不是直接往SSD中發送命令的,而是把命令準備好放在本身的內存中,那怎麼通知SSD來獲取命令執行呢?Host就是經過寫SSD端的DB寄存器來告知SSD的。
1.4架構模型
圖2:單端口PCIe SSD
圖3:帶SMBus / I2C的雙端口PCIe SSD
NVMe管理界面用於發送命令消息,該命令消息由以NVM子系統內的控制器爲目標的標準NVMe管理命令組成; 用於訪問NVM子系統中控制器的PCI Express配置,I / O和存儲空間的命令; 和管理接口特定命令,用於清點,配置和監視NVM子系統。
圖4:與單端口PCIe SSD相關的NVM子系統
圖5示出了與圖3中所示的PCIe SSD相對應的示例NVM子系統。NVM子系統,包含一個與PCIe端口0相關聯的控制器和兩個與PCIe端口1相關聯的控制器。存在與每一個PCIe端口相關聯的管理端點和SMBus / I2C端口。因爲NVM子系統包含管理端點,所以全部控制器都具備關聯的控制器管理接口。
圖5:與帶有SMBus / I2C的雙端口PCIe SSD相關的NVM子系統
管理接口請求消息和響應消息做爲MCTP消息傳輸,消息類型經過MCTP設置爲NVM Express管理消息(請參閱MCTP ID和代碼規範)。 全部命令消息都源自管理控制器,並從管理端點生成響應消息。
4消息處理模型
NVMe-MI使用請求和響應處理模型。
圖14:NVMe-MI MCTP消息分類
4.1 request消息
request消息是由管理控制器生成的NVMe-MI消息,用於發送給管理端點。
request消息指定管理端點要執行的操做。
4.2 reponse消息
reponse消息是管理端點完成時生成的NVMe-MI消息處理先前發出的request消息。
NVM Express基於配對的提交和完成隊列機制
命令由主機軟件放入提交隊列。完成被放入控制器關聯的完成隊列。多個提交隊列可使用相同的完成隊列。提交和完成隊列在內存中分配。
存在管理員提交和關聯的完成隊列以用於控制器管理和控制(例如,建立和刪除I / O提交和完成隊列,停止命令,等等)。只有屬於管理員命令集的命令才能夠提交給管理員提交隊列。
I / O命令集與I / O隊列對一塊兒使用。該規範定義了一個I / O命令集,命名爲NVM命令集。主機選擇一個用於全部I / O隊列的I / O命令集對。
主機軟件建立隊列,最高可達控制器支持的最大值。一般的數量建立的命令隊列基於系統配置和預期的工做負載。例如, 在基於四核處理器的系統上,每一個核心可能有一個隊列對,以免鎖定和確保數據結構在適當的處理器核心緩存中建立。圖1提供了圖形隊列對機制的表示,顯示提交隊列和。之間的1:1映射完成隊列。圖2顯示了多個I / O提交隊列使用相同的示例核心B上的I / O完成隊列。圖1和圖2顯示了之間始終存在1:1管理員提交隊列和管理員完成隊列。
提交隊列(SQ)是一個循環緩衝區,具備主機軟件用於提交的固定插槽大小控制器執行的命令。主機軟件更新相應的SQ Tail門鈴當有一到n個新命令要執行時註冊。以前的SQ Tail值被覆蓋當有新的門鈴寄存器寫入時控制器。控制器按順序提取SQ條目可是,提交隊列能夠按任何順序執行這些命令。
4.1.1空隊列
當Head入口指針等於Tail入口指針時,隊列爲Empty。圖8定義了Empty隊列條件。
圖8:空隊列定義
4.1.2滿隊列
當Head等於尾部時,隊列爲Full。隊列中的條目數full比隊列大小少一個。
圖9定義了完整隊列條件。注意:在肯定隊列是否爲Full時,應考慮隊列包裝條件。
圖9:完整隊列定義
7控制器架構
主機軟件(Host)經過預先分配的提交隊列向控制器(Controller)提交命令。經過SQ Tail Doorbell寄存器寫入警告控制器新提交的命令。前一個門鈴寄存器值和當前寄存器寫入之間的差別表示已提交的命令數。
控制器從提交隊列中提取命令並將它們發送到NVM子系統進行處理。
命令處理
1.主機將一個或多個命令放置在位於內存中的提交隊列(SQ)的下一個可用的槽位中執行。
2. Host用SQ尾部指針的新值去更新SQ的TailDB寄存器。這告訴了SSD控制器有一個新的命令被提交須要被處理。
3. SSD控制器將命令從SQ中轉移到控制器中以供下一步執行。(從哪個SQ中取出下一條候選命令去執行的仲裁方法,請參見4.11一節。)
4.控制器接下來執行下一條命令。命令的執行完成多是亂序的(與提交或開始執行的時間點無關)。
5.在命令完成執行以後,SSD控制器將一個完成隊列條目(CQE)放在相關的完成隊列(CQ)的下一個空閒槽位中。做爲CQE的一部分,SSD控制器經過修改完成條目的SQ頭指針指示最新的SQE已經被消費了。每個新的CQE都有一個從前一個條目中反轉的相位標記(Phase Tag), 以向Host代表這個CQE是一個新條目。
6. SSD控制器給Host產生一箇中斷,以代表有一個新的CQE已經產生,能夠被消費和處理了。在圖中演示的是MSI-X中斷,然而,中斷也能夠是基於PIN或者MSI的中斷。注意:基於中斷聯合設置,可能或不能爲每個新的CQE產生一箇中斷。
7. Host消費和處理在CQ中放置的新的CQE。包括基於錯誤狀況採起的任何操做。Host繼續消耗和處理CQE,直到它遇到之前消費的一個條目的相位標籤(Phase Tag)從當前完成隊列條目(CQEs)的值中反轉。
8. Host更新CQ的HeadDB寄存器,代表CQE已經被消費了。在更新相關聯的CQ的HeadDB寄存器以前,Host可能消費了多個CQE。
通俗易懂的話總結一下就是:
1. Host寫命令到SQ
2. Host更新SQ的TailDB, 通知SSD取命令
3. SSD收到命令,因而從SQ中取出命令
4. SSD執行命令
5. 命令執行完成後,SSD往CQ中寫入命令執行結果,同時修改CQ的TailDB
6. SSD發短信通知Host命令已經執行完成
7. Host收到命令後,到CQ中查看命令完成狀態
8. Host處理完CQ中的命令執行結果,更新CQ中的HeadDB, 回覆SSD, "命令執行結果已經處理完畢,辛苦啦"
NVMe over PCIe和RDMA本質上都是「玩隊列」。 NVMe over PCIe有兩條隊列,一條提交隊列(SQ)和一條完成隊列(CQ);而RDMA有三條隊列,一條發送隊列(SQ),一條接收隊列(RQ)和一條完成隊列(CQ),而一個SQ和一個RQ被稱之爲一個QP(隊列對)。
對應nvme驅動代碼位置:
nvme_pcie.c
1.Int nvme_pcie_qpair_submit_request()
TAILQ_INSERT_TAIL(&pqpair->outstanding_tr, tr, tq_list);
(對應app代碼位置:bdev_nvme_submit_request( ) )??是嗎,只是名稱相近?
2. static void nvme_pcie_qpair_complete_tracker()
TAILQ_INSERT_HEAD(&pqpair->free_tr, tr, tq_list);
bdev_nvme.c
static const struct spdk_bdev_fn_table nvmelib_fn_table = { (device function table)
.destruct = bdev_nvme_destruct,
.submit_request = bdev_nvme_submit_request,
.io_type_supported = bdev_nvme_io_type_supported,
.get_io_channel = bdev_nvme_get_io_channel,
.dump_info_json = bdev_nvme_dump_info_json,
.write_config_json = bdev_nvme_write_config_json,
.get_spin_time = bdev_nvme_get_spin_time,
};
static struct spdk_bdev_module nvme_if = {
.name = "nvme",
.module_init = bdev_nvme_library_init,
.module_fini = bdev_nvme_library_fini,
.config_text = bdev_nvme_get_spdk_running_config,
.config_json = bdev_nvme_config_json,
.get_ctx_size = bdev_nvme_get_ctx_size,
};
關於MSI-X,在igb_uio.c裏igbuio_msix_mask_irq( )
淺談NVMe與MSI-X
https://blog.csdn.net/wangpeng22/article/details/78390694?locationNum=2&fps=1
https://blog.csdn.net/weijitao/article/details/46566789
http://blog.sina.com.cn/s/blog_6472c4cc0102dskj.html
NVMe制定了Host與SSD之間通信的命令,以及命令如何執行的。
NVMe有兩種命令,
一種叫Admin Command,用以Host管理和控制SSD;
另一種就是I/O Command,用以Host和SSD之間數據的傳輸。下面是NVMe1.2支持的命令列表:
NVMe支持的Admin Command:
NVMe支持的I/O Command:
lib/bdev/nvme/bdev_nvme.c
_bdev_nvme_submit_request( )有IO操做的處理,
nvme_ctrlr_ut.c
test_nvme_ctrlr_init_en_1_rdy_0
test_nvme_ctrlr_init_en_1_rdy_1
test_nvme_ctrlr_init_en_0_rdy_0
test_nvme_ctrlr_init_en_0_rdy_1
test_nvme_ctrlr_init_en_0_rdy_0_ams_rr
test_nvme_ctrlr_init_en_0_rdy_0_ams_wrr
test_nvme_ctrlr_init_en_0_rdy_0_ams_vs
test_alloc_io_qpair_rr_1
test_ctrlr_get_default_ctrlr_opts
test_ctrlr_get_default_io_qpair_opts
test_alloc_io_qpair_wrr_1
test_alloc_io_qpair_wrr_2
test_spdk_nvme_ctrlr_update_firmware
test_nvme_ctrlr_fail
test_nvme_ctrlr_construct_intel_support_log_page_list
test_nvme_ctrlr_set_supported_features
test_spdk_nvme_ctrlr_doorbell_buffer_config----5 Admin Command Set
test_nvme_ctrlr_test_active_ns
nvme_ctrlr_cmd_ut.c ----- AdminCommand的功能測試集
test_get_log_pages----5 Admin Command Set
test_set_feature_cmd----5 Admin Command Set
test_set_feature_ns_cmd----5 Admin Command Set
test_get_feature_cmd----5 Admin Command Set
test_get_feature_ns_cmd----5 Admin Command Set
test_abort_cmd----5 Admin Command Set
test_io_raw_cmd
test_io_raw_cmd_with_md
test_namespace_attach----5 Admin Command Set
test_namespace_detach----5 Admin Command Set
test_namespace_create----5 Admin Command Set
test_namespace_delete----5 Admin Command Set
test_format_nvme
test_fw_commit----5 Admin Command Set
test_fw_image_download----5 Admin Command Set