NVMe · Q1–328

NVM Express Base 2.4NVM Command Set 1.3NVMe over PCIe Transport 1.4

Q22–Q30

Doorbell、Queue Full 與 Wrap-around

Doorbell 告訴 controller,Host 的指標已前進到哪個位置;Phase 則讓 Host 分辨 CQ 中的是新完成結果,還是上一圈留下的資料。本冊將位置與有效性一起說明,幫助你正確處理繞回及空間釋放,避免將正常繞回誤判成倒退,或把舊 CQE 處理兩次。

CQ
Completion Queue,完成佇列
CQE
Completion Queue Entry,佇列中的完成項目

每個問題都接著完整解說,依內容帶讀欄位、比較機制或追蹤流程。先看本冊總覽,再沿問題閱讀;必要條件與正常路徑直接顯示。所有數字案例均為教學假設;Status 以 SCT/SC 表示,代碼後的 h 代表十六進位。

SCT
Status Code Type,完成狀態代碼類型

8 格 CQ:把繞回與 Phase 放在同一張表

CQ 索引回到 0,不表示位置 0 裡的舊資料重新有效。Host 還要比對這一圈期待的 Phase,才能確認是否已有新 CQE。

時點Host 下一格/預期 Phase讀取結果與動作
初始化位置 0,預期 P=1;記憶體 P 初始化為 0目前沒有新完成
第一輪末端位置 7,預期 P=1讀到 P=1:處理 CQE,下一格回 0,預期改 0
第二輪起點位置 0,預期 P=0若仍是舊 P=1,不處理;讀到新 P=0 才處理
通知 controller 已處理的範圍CQ Head 從 7 更新成 2表示位置 7、0、1 的 3 筆 CQE 已處理完畢,不是指標倒退 5 格

舉例看懂:這次前進距離為 (2−7+8) mod 8=3,所以 Host 將 Doorbell 寫成位置 2,通知 controller 有 3 格已可重用;不是因為寫了 2,就表示釋放 2 格。Phase 用來確認 Host 讀到的是新 CQE,CQ Head Doorbell 則通知 controller 哪些 CQE 已處理完畢,兩者負責不同工作。

來源:Base 2.4 §3.3.1 · Base 2.4 §4.2.1, 4.2.3–4.2.4 · PCIe Transport 1.4 §3.1–3.4

先把觀念接起來

教學 1 · 指標是位置,差值才是數量

Doorbell 中的 2 表示索引位置 2,不表示這次提交了 2 筆。對 8 個位置的環狀 queue,從 7 前進到 2,經過的是 7、0、1,共 3 個位置。如果只用一般數字大小比較,看到 2<7 就判定倒退,便會把正常繞回誤認為非法操作。

教學 2 · Phase 不是成功位元

Phase 只用來判斷這個 CQ 位置是否包含目前這一圈的新完成結果。即使 Phase 有效,CQE 內仍可能是失敗 Status;反過來,舊 CQE 即使留有 Success,只要 Phase 不符合期待值,就不能再處理一次。因此,先確認有效性,再解讀 SCT 與 SC,才能避免誤讀殘留資料。

SCT
Status Code Type,完成狀態代碼類型

教學 3 · 為何 Host 處理完還要寫 CQ Head

Host 在自己的程式中將 CQE 標記為已處理,並不會自動通知 controller。必須更新 CQ Head Doorbell,controller 才能得知哪些位置已可重用。如果漏掉這一步,即使 Host 已處理完所有結果,controller 仍可能因 CQ Full 而停住。這時應檢查空間釋放流程,而不是先把停滯歸因於媒體延遲。

需要時回顧本篇名詞
Controller / namespace
controller 接收命令並管理存取;namespace 是命令可指定的一份邏輯儲存空間。NVM subsystem 則包含 controller 與非揮發儲存資源,同一 subsystem 可以有多個 controller。
SQ / CQ / SQE / CQE
Submission Queue(SQ)是提交佇列,Completion Queue(CQ)是完成佇列;SQE 與 CQE 分別是其中的一筆命令及完成項目。QID 識別 queue,CID 區分同一 SQ 中尚未完成的命令,NSID 則識別 namespace。
Register / Identify / Feature / Log
Register 提供可存取的控制或狀態資訊;Identify 查詢物件的能力與屬性;Feature 用來讀取或變更工作設定;Log Page 回報特定種類的狀態或紀錄。FID、LID、CNS、CSI 則分別用來選擇 Feature、Log Page、Identify 資料結構及命令集。
index / offset / zero-based
index 指出清單中的第幾筆,通常從 0 起算;offset 表示與起點相隔多遠,解讀時必須確認單位。若數量欄位採 zero-based 編碼,實際數量等於欄位值加 1;但不是所有欄位看到 0 都要加 1。Dword 是 4 bytes,1 byte 是 8 bits。
Scope / reset / retention
scope 表示操作影響哪些物件;retention 表示狀態是否保留。清除 CC.EN 所觸發的 Controller Reset,是 Controller Level Reset(CLR)的一種。同屬 CLR 的不同觸發方式,仍可能採用不同的 Register 保留規則。

本冊題目

  1. Q22 · Host 應在什麼時候更新 SQ Tail Doorbell 與 CQ Head Doorbell?
  2. Q23 · Doorbell 值重複、倒退、超過 Queue 範圍或寫到錯誤 QID 時,可能造成什麼問題?
  3. Q24 · Host 如何根據 CAP.DSTRD 計算每個 SQ 與 CQ Doorbell 的位置?
  4. Q25 · Host 能否存取未建立、已刪除或 Controller 未 Enable 時的 Queue Doorbell?
  5. Q26 · SQ Tail 與 CQ Head 發生 Wrap-around 時,Host 與 Controller 應如何處理?
  6. Q27 · CQ Wrap-around 後 Phase Tag 如何變化?Host 如何利用 Phase Tag 辨識新 Completion?
  7. Q28 · CQ Full 通常如何形成?CQ Full 時 Controller 能否繼續處理相關 SQ?
  8. Q29 · Host 釋放 CQ 空間後,Controller 應如何恢復 Command 處理?
  9. Q30 · 多個 SQ 共用一個 CQ 時,Host 如何依 SQID 與 CID 辨識 Completion 來源?

Q22 Host 應在什麼時候更新 SQ Tail Doorbell 與 CQ Head Doorbell?

SQ
Submission Queue,提交佇列
跟著解說理解

Host 需要通知 controller,哪些 SQE 已經準備好,以及哪些 CQE 已經處理完畢。更新 SQ Tail 是提交新命令;更新 CQ Head 則是釋放已處理的完成位置,讓 controller 可以再次使用。

SQE
Submission Queue Entry,佇列中的命令項目

1. 操作前先準備什麼

每條 SQ/CQ 各有自己的 Doorbell;更新其中一條不會自動更新另一條。

更新前,先確認 queue 仍然有效,而且 controller 已就緒。提交命令時也要確認 SQ 有足夠的可用位置,再依 CAP.DSTRD 找到正確的 Doorbell Register。

SQ Tail 指向下一個可放入 SQE 的位置;CQ Head 指向下一個等待 Host 處理的 CQE。Doorbell 要寫入更新後的索引值,而不是這次新增或處理了幾筆。

SQE
Submission Queue Entry,佇列中的命令項目

2. 先後順序與完成條件

提交時,Host 先寫好完整的 SQE,並依平台要求確保 controller 能看見這些記憶體內容,之後才更新 SQ Tail。接收完成結果時,則先讀取並處理有效的 CQE,再更新 CQ Head。Host 可以一次提交多筆命令,也可以一次釋放多個已處理的完成位置。

更新 SQ Tail 後,controller 才能得知哪些新命令可以讀取;更新 CQ Head 後,controller 才能得知哪些完成位置可以重用。因此,CQ Head 前進並不表示 Host 提交了新的 I/O 命令。

3. 未符合條件時如何處理

如果 Host 尚未處理 CQE 就提前釋放位置,該 CQE 可能被後續的完成結果覆寫。如果 SQE 尚未準備好就更新 Tail,controller 也可能讀到不完整的命令。這些都是使用順序錯誤,不能預期 controller 一定會回傳某個固定的錯誤 CQE。

驗證時,依時間先後比對 Host 寫入 SQE、更新 Tail、controller 寫入帶有新 Phase 的 CQE,以及 Host 更新 Head 這四個動作。它們分別代表準備命令、提交命令、回報完成及釋放完成位置,不能互相替代。

來源:Base 2.4 §3.3.1 · PCIe Transport 1.4 §3.1–3.4 · Base 2.4 §3.7.1–3.7.4 · Base 2.4 §5.2.13.1.14 (header, reset, hardware, Set Feature events) · Base 2.4 §9.1–9.6.1

回本冊題目

Q23 Doorbell 值重複、倒退、超過 Queue 範圍或寫到錯誤 QID 時,可能造成什麼問題?

跟著解說理解

判斷指標移動是否合法,避免把環狀索引當成只會遞增的計數器。

1. 先區分是哪一種失敗

錯誤會影響被寫入 Doorbell 的 queue。如果是多條 SQ 共用的 CQ,影響還可能延伸到這些 SQ。另外,向不存在的 queue 寫 Doorbell,與向有效 queue 寫入非法值,是兩種不同情況。

合法索引介於 0 與 size−1。寫入較小的值不一定是倒退,因為指標可能剛好繞回起點。再次寫入相同的值也不能視為一定安全的空更新:Base 2.4 Figure 153 將它列為 Invalid Doorbell Write Value 的可能原因之一。

向有效 queue 寫入非法值,而且已有尚未完成的 Asynchronous Event Request(AER,非同步事件要求)時,controller 透過該 AER 回報 Invalid Doorbell Write Value;事件資訊不是這次 MMIO 寫入的 CQE Status。若沒有等待中的 AER,不能單憑這條規則保證已收到通知。向不存在的 queue 寫 Doorbell,結果則是未定義。

MMIO
Memory-Mapped I/O,記憶體映射輸入輸出

2. 用哪些資料確認原因

判斷指標是否合法,需要知道 queue 大小、原來的指標、可用或已處理的位置數量,以及 Doorbell 對應的 QID。只看新寫入的數字,無法判斷這次移動是否正確。

【模擬資料】queue 大小為 8,Tail 從 6 變成 1,代表前進 3 個位置。這次提交是否合法,還要確認原本有 3 個可用位置,而且對應的 SQE 都已準備好。從 6 再寫回 6,不能表示提交了一整圈,也可能構成無效寫入。

3. 結果與後續驗證

合法的指標更新,能讓 controller 算出新提交或新釋放的位置數量。不過,Host 不應靠讀回 Doorbell 來驗證寫入結果,因為 Doorbell 的讀回值由廠商定義。

先依原指標、queue 大小及剩餘空間判斷移動是否合法,不要只比較新舊數字的大小。若發生 Doorbell 錯誤,還應一起檢查對應的非同步事件,以及受影響 queue 是否停止取得新命令。

先用 (new−old+size) modulo size 算出前進量,再確認這些位置是否確實可以提交或釋放。

4. 分開核對事件通知與 Log 紀錄

依 Base §3.3.1.2,若 Doorbell 值非法,而且有尚未完成的 Asynchronous Event Request,controller 會透過它回報對應錯誤事件。受影響的 SQ 可以完成已取得的命令,但不再取得新命令;Host 則需刪除並重建 queue。

這是 Error 類型的非同步事件,應讀取事件指定的 Log,取得補充資料。MMIO 寫入本身沒有 More 位元。另外,若是寫到不存在 QID 的 Doorbell,規範已將結果列為未定義,不能再要求它一定產生 Log。

MMIO
Memory-Mapped I/O,記憶體映射輸入輸出

來源:Base 2.4 §3.3.1 · PCIe Transport 1.4 §3.1–3.4 · Base 2.4 §5.2.2 · Base 2.4 §3.7.1–3.7.4 · Base 2.4 §5.2.13.1.14 (header, reset, hardware, Set Feature events) · Base 2.4 §9.1–9.6.1

回本冊題目

Q24 Host 如何根據 CAP.DSTRD 計算每個 SQ 與 CQ Doorbell 的位置?

跟著解說理解

Host 必須根據 NVMe Register 的起始位址及 QID,找出要更新的 Doorbell 位址,才能把通知送到正確的 queue。

1. 先確認資料的來源與範圍

Doorbell 位址以該 controller 的 MMIO 起始位址為基準,不是以 SQ 或 CQ 記憶體的起始位址為基準。

PCI BAR0/BAR1 用來找出 NVMe Register 空間的位置;CAP.DSTRD 則用來計算相鄰 Doorbell 的位址間距。

2. 欄位、單位與判讀例子

stride=4×2^DSTRD;SQy offset=1000h+2y×stride;CQy offset=1000h+(2y+1)×stride。每個 Doorbell 本身仍是 32 bits。

先取得映射後的 Register 起始位址,再由 DSTRD 算出 stride。接著依 QID 選用 SQ 或 CQ 的公式,算出 Doorbell 位址,最後使用規定的存取寬度執行 MMIO 寫入。

例:DSTRD=2、QID=3,SQ offset=1060h、CQ offset=1070h。把各 offset 加到 controller base,才是完整位址。

3. 判讀時要保留的條件

計算位址本身不會產生 Command Status。如果算錯位址,可能寫到另一條有效 queue,也可能形成結果未定義的存取。controller 無法因此得知 Host 原本想更新哪一條 queue。

把算出的 Doorbell 位址,與建立 queue 時使用的 QID 及 BAR 映射範圍交叉比對。DSTRD 是計算間距時使用的編碼,不能直接當成 byte 數,也不能直接拿來乘上 QID。

BAR
Base Address Register,基底位址暫存器

來源:Base 2.4 §3.1.4 (CAP, VS) · PCIe Transport 1.4 §3.1–3.4 · PCIe Transport 1.4 §3.8.1 (NVMe configuration access) · Base 2.4 §3.7.1–3.7.4 · Base 2.4 §5.2.13.1.14 (header, reset, hardware, Set Feature events) · Base 2.4 §9.1–9.6.1

回本冊題目

Q25 Host 能否存取未建立、已刪除或 Controller 未 Enable 時的 Queue Doorbell?

跟著解說理解

Doorbell 只有在對應 queue 有效時才能使用。即使 Host 能算出某個 Doorbell 的 Register 位址,也不代表那條 queue 目前已經建立。

1. 先確認 Queue 的有效期間

I/O queue 必須在建立成功後才能使用;刪除成功或 Controller Reset 之後,Host 就不能再沿用原來的 queue。

檢查 Host 維護的 queue 紀錄,以及 CC.EN、CSTS.RDY。Doorbell 的讀回值不能用來判斷 queue 是否存在。

SQyTDBL 與 CQyHDBL 分別通知有效 queue 的新 Tail 與 Head。Admin Queue 的 QID 為 0,其設定來自 AQA、ASQ、ACQ,並隨 controller 初始化建立可用狀態。

對 I/O queue,Host 先建立並等待成功,再開始使用。準備刪除時,先停止提交新命令,並在 Delete 成功後停止使用原 queue。Controller Reset 之後,即使打算沿用相同 QID,也必須重新建立 I/O queue。

2. 不存在的 Queue 沒有固定錯誤回報

PCIe §3.1.2 將向不存在的 SQ 或 CQ 寫 Doorbell 列為結果未定義的行為。CSTS.RDY=0 時也不符合命令提交的前提,因此不能要求 controller 一定回報 Invalid Queue Identifier 或某個指定的非同步事件。

以 Create 與 Delete 的完成時間界定 queue 的有效期間,再檢查所有 Doorbell 更新是否都發生在這段期間內。

來源:PCIe Transport 1.4 §3.1–3.4 · Base 2.4 §3.3.1 · Base 2.4 §3.3.3–3.4.1 · Base 2.4 §5.3.3–5.3.4 · Base 2.4 §3.7.1–3.7.4 · Base 2.4 §5.2.13.1.14 (header, reset, hardware, Set Feature events) · Base 2.4 §9.1–9.6.1

回本冊題目

Q26 SQ Tail 與 CQ Head 發生 Wrap-around 時,Host 與 Controller 應如何處理?

跟著解說理解

環狀 queue 讓固定大小的記憶體可以重複使用。指標走到尾端後回到起點,不需要每繞一圈就重新建立 queue。

1. 操作前先準備什麼

SQ Tail 與 CQ Head 都由 Host 推進;SQ Head 與 CQ Tail 則由 controller 維護。判斷指標變化時,要先分清楚是哪一端負責更新。

計算時使用該 queue 實際配置的位置數 N,也就是 QSIZE+1。CAP.MQES 表示能力上限,不能直接當成每條 queue 的實際大小。

每前進一步計算 (index+1) modulo N。Tail 是下一個寫入位置,Head 是下一個讀取位置,兩者相等表示空。

2. 先後順序與完成條件

索引從 N−1 回到 0 時,Host 仍須正確追蹤這次實際前進了幾個位置。更新 SQ Tail 不能超過可用空間;更新 CQ Head 不能跳過尚未處理的 CQE。

例如 N=8,CQ Head 從 7 變成 2,表示 Host 已處理索引 7、0、1 的 3 筆 CQE,而不是指標倒退了 5 個位置。

3. 未符合條件時如何處理

合法的 wrap-around 不是錯誤。若誤把 queue 大小 N 當成最大合法索引,並將 N 寫入 Doorbell,才會超出範圍。非法指標的處理方式見第 23 題。

驗證時,要一起檢查 Head、Tail 與 queue 大小的環狀索引關係。Doorbell 數值變小,可能只是正常跨過尾端,不能單憑這點判定違反規範。

來源:Base 2.4 §3.3.1 · PCIe Transport 1.4 §3.1–3.4 · Base 2.4 §3.7.1–3.7.4 · Base 2.4 §5.2.13.1.14 (header, reset, hardware, Set Feature events) · Base 2.4 §9.1–9.6.1

回本冊題目

Q27 CQ Wrap-around 後 Phase Tag 如何變化?Host 如何利用 Phase Tag 辨識新 Completion?

跟著解說理解

CQ 的同一個位置會反覆使用。Phase Tag 讓 Host 分辨目前看到的是這一圈的新完成結果,還是上一圈留下的舊資料。

1. 操作前先準備什麼

Phase 用來辨識 CQE 屬於哪一圈,不表示命令成功或失敗,也不是 SQ 的指標。

Phase 是 PCIe CQE 的基本機制,不需要額外啟用 Feature。建立 CQ 前,Host 將每個位置的 Phase 初始化為 0,並將自己第一次等待的 Phase 設為 1。

CQE DW3 bit16 為 P;controller 每次在同一 slot 放入新 CQE 時反轉該 slot 的前次 Phase。

2. 先後順序與完成條件

Phase 跟著整圈變,不跟著每筆 CQE 變

教學假設 CQ 有 4 個位置,Host 第一圈期待 P=1。

  1. 檢查目前 Head 的 P

    P 不符期待值:這個位置還沒有本圈的新結果,先等待;不要解讀殘留的 CID 或 Status。

  2. P 符合 → 處理 CQE

    Base 2.4 §4.2.1 規定:若 controller 用多次寫入建立 CQE,須在最後一次寫入時更新 P。Host 讀取其他欄位時,還要遵循平台的記憶體存取規則。這一圈 Head 依序走 0、1、2、3,新 CQE 都使用 P=1。

  3. Head 從 3 回到 0 → 反轉期待值

    下一圈期待 P=0。若只從 1 移到 2,尚未換圈,期待值不變。

重新建立 CQ 時,要重新初始化 Phase 與 Host 的期待值。此處的 4-entry 大小只是方便看懂換圈的教學假設。

CID
Command Identifier,同一提交佇列內的命令識別碼

3. 未符合條件時如何處理

Phase 不符合期待值,表示該位置還沒有這一圈的新完成結果,並不代表某種錯誤 Status。此時不能把該位置殘留的 CID 或 SC 當成新命令的結果。

CID
Command Identifier,同一提交佇列內的命令識別碼

測試至少要讓 CQ 完整繞過一圈,並比對 CQ Head、Host 期待的 P 與 CQE 實際的 P。重建 queue 時必須重新初始化,不能沿用前一次 queue 的期待值。

來源:Base 2.4 §4.2.1, 4.2.3–4.2.4 · Base 2.4 §3.3.1 · Base 2.4 §3.7.1–3.7.4 · Base 2.4 §4.2.3 · Base 2.4 §5.2.13.1.2 · Base 2.4 §5.2.2 · Base 2.4 §5.2.13.1.14 (header, reset, hardware, Set Feature events)

回本冊題目

Q28 CQ Full 通常如何形成?CQ Full 時 Controller 能否繼續處理相關 SQ?

跟著解說理解

CQ 的空間管理用來避免尚未處理的完成結果被覆寫。當 controller 產生 completion 的速度,超過 Host 處理並釋放位置的速度,CQ 就可能變滿。

1. 機制與適用範圍

影響該 CQ 與其關聯 SQ;其他不使用此 CQ 的 SQ 必須繼續處理。

CQ 保留一個位置不用;當 (Tail+1) modulo N = Head 時,就表示 CQ 已滿。這裡的 Tail 由 controller 維護,Host 不能直接讀取它。

2. 用操作與結果理解

判斷容量時,要看 CQ 的實際大小、Host 更新 CQ Head 的情況,以及尚未處理的完成結果。Number of Queues 表示 queue 數量,不能用來推算一條 CQ 能容納多少筆 CQE。

Host 逐筆確認 Phase 並處理 CQE,之後再更新 Head,釋放已處理的位置。在可用位置出現之前,controller 不得向這條 CQ 寫入新的完成結果。

controller 可以停止處理關聯 SQ 中的新 entry。規範在這裡使用 may,因此不能進一步推論:所有已取得的命令都必須立刻停止,或都必須繼續執行。

3. 容易誤判的地方

CQ Full 是空間已滿的狀態,不是一個必須回報的 NVMe 錯誤碼。controller 不能為了騰出空間,覆寫 Host 尚未確認處理完畢的 CQE。

如果只有共用這條 CQ 的 SQ 停滯,先檢查 Host 是否持續處理並釋放 CQE。如果連使用其他獨立 CQ 的 SQ 也因這條 CQ 已滿而停止,則要檢查是否違反繼續處理其他 SQ 的要求。

來源:Base 2.4 §3.3.1 · Base 2.4 §3.4.1–3.4.5 · Base 2.4 §3.7.1–3.7.4 · Base 2.4 §4.2.3 · Base 2.4 §5.2.13.1.2 · Base 2.4 §5.2.2 · Base 2.4 §5.2.13.1.14 (header, reset, hardware, Set Feature events)

回本冊題目

Q29 Host 釋放 CQ 空間後,Controller 應如何恢復 Command 處理?

跟著解說理解

CQ 空間釋放後,原本受容量限制的工作便能繼續。CQ Full 本身不表示 queue 已失效,因此不需要只因空間曾經用完就重新建立 queue。

1. 操作前先準備什麼

Host 釋放的是這條 CQ 中的完成位置,讓關聯 SQ 的命令可以回報結果。這不會改變可建立的 queue 數量,也不會改變 namespace 的能力。

先確認 queue 仍然存在,而且沒有其他停止處理的原因,例如正在重設、CSTS.CFS 已設定,或 queue 處於 Processing Paused 狀態。

Host 將新的 Head 索引寫入 CQ Head Doorbell。controller 根據 Head 的前進量得知哪些位置可以重用,後續寫入 CQE 時仍須使用正確的 Phase。

2. 先後順序與完成條件

Host 處理 CQE 並更新 Head 後,controller 才得知有新的可用空間,接著可以寫入等待回報的完成結果,並繼續處理受影響的工作。實際執行次序仍受仲裁設定及其他正常條件限制。

已釋放的位置可以再次使用,不必重建 queue。不過,規範沒有為所有裝置訂出同一個固定時間,要求從 Head 更新到下一筆 CQE 出現必須相隔多久。

3. 未符合條件時如何處理

正確更新 CQ Head 不會另外產生一筆成功 CQE。如果 Head 值非法,應依 Doorbell 的錯誤處理規則判斷,不能套用 Create Queue 的錯誤 Status。

檢查後續 CQE 是否寫入合法且已釋放的位置,並比較共用這條 CQ 的 SQ 與其他獨立 SQ 的處理進度。

來源:Base 2.4 §3.3.1 · PCIe Transport 1.4 §3.1–3.4 · Base 2.4 §3.4.1–3.4.5 · Base 2.4 §3.7.1–3.7.4 · Base 2.4 §4.2.3 · Base 2.4 §5.2.13.1.2 · Base 2.4 §5.2.2 · Base 2.4 §5.2.13.1.14 (header, reset, hardware, Set Feature events)

回本冊題目

Q30 多個 SQ 共用一個 CQ 時,Host 如何依 SQID 與 CID 辨識 Completion 來源?

SQID
Submission Queue Identifier,提交佇列識別碼
跟著解說理解

Host 必須將每筆 completion 配對到原來的命令,才能交付正確結果。CID 只要求在同一條 SQ 的未完成命令之間保持唯一;不同 SQ 可以同時使用相同 CID。

1. 先確認資料的來源與範圍

Host 追蹤命令時,必須一起考慮 controller、SQ 的這次建立與使用期間、SQID 及 CID。controller 與 queue 的使用期間是 Host 自己維護的上下文,並不是 CQE 裡額外增加的欄位。

SQID
Submission Queue Identifier,提交佇列識別碼

Host 使用建立 queue 時記錄的 SQ 與 CQ 對應關係,以及未完成命令的追蹤表,來尋找原命令。Identify 不會回報每筆未完成命令的位置。

2. 欄位、單位與判讀例子

CQE.SQID 指出命令來自哪條 SQ,CID 則指出該 SQ 內的哪筆命令。SQHD 回報 controller 已消費到的 SQ 位置,不代表這筆完成命令原先所在的 SQ 位置。

Host 先確認 CQE 的 Phase 有效,再用 SQID 與 CID 找到原命令,處理 Status 及回傳資料,並更新該 SQ 的 Head 紀錄。這些工作完成後,才釋放 CQ 中的這個位置。

例如 SQ1 的 CID9 與 SQ2 的 CID9 可以共用同一條 CQ。即使兩筆命令以相反順序完成,Host 仍可透過 SQID 與 CID 分別找到正確的原命令。

3. 判讀時要保留的條件

同一條 SQ 中,未完成命令的 CID 重複時,可能回報 Command ID Conflict(0/03h)。controller 為了偵測衝突,會搜尋多少筆既有命令,由實作決定;這不免除 Host 維持 CID 唯一性的責任。

先確認 CQE 指出的 SQID 確實關聯到這條 CQ,再確認 CID 屬於目前這次建立的 SQ,而不是前一次 queue 留下的追蹤資料。

來源:Base 2.4 §4.2.1, 4.2.3–4.2.4 · Base 2.4 §3.3.1 · Base 2.4 §4.1.1 · Base 2.4 §3.7.1–3.7.4 · Base 2.4 §4.2.3 · Base 2.4 §5.2.13.1.2 · Base 2.4 §5.2.2 · Base 2.4 §5.2.13.1.14 (header, reset, hardware, Set Feature events)

回本冊題目

原文定位與既有圖表判讀

Base 的文件頁碼等於 PDF 頁碼減 26;NVM 與 PCIe 兩份規格的文件頁碼則與 PDF 頁碼相同。以下依提供的 PDF 本文列出章節、頁碼及 Figure 編號。若同一頁包含其他主題,只引用本題需要的定義,不納入 Fabrics 或 PCIe Link、封包內容。

  • Base 2.4 · §3.1.4 (CAP, VS)
    文件頁 54–59 · PDF 80–85 · Figure 36–37
  • Base 2.4 · §3.3.1
    文件頁 88–91 · PDF 114–117 · Figure 73–74
  • Base 2.4 · §3.4.1–3.4.5
    文件頁 101–105 · PDF 127–131 · Figure 80–81
  • Base 2.4 · §3.3.3–3.4.1
    文件頁 101 · PDF 127
  • Base 2.4 · §3.7.1–3.7.4
    文件頁 120–124 · PDF 146–150
  • Base 2.4 · §4.1.1
    文件頁 139–142 · PDF 165–168 · Figure 92–93
  • Base 2.4 · §4.2.1, 4.2.3–4.2.4
    文件頁 144–157 · PDF 170–183 · Figure 97–105, 109
  • Base 2.4 · §4.2.3
    文件頁 145–155 · PDF 171–181 · Figure 101–105
  • Base 2.4 · §5.2.2
    文件頁 183–190 · PDF 209–216 · Figure 150–156
  • Base 2.4 · §5.2.13.1.2
    文件頁 218–220 · PDF 244–246 · Figure 212
  • Base 2.4 · §5.2.13.1.14 (header, reset, hardware, Set Feature events)
    文件頁 244–256, 258, 262–264 · PDF 270–282, 284, 288–290 · Figure 232–244, 246, 252–253
  • Base 2.4 · §5.3.3–5.3.4
    文件頁 531–532 · PDF 557–558 · Figure 580–583
  • Base 2.4 · §9.1–9.6.1
    文件頁 825–826 · PDF 851–852
  • PCIe Transport 1.4 · §3.1–3.4
    文件頁 9–13 · PDF 9–13 · Figure 3–8
  • PCIe Transport 1.4 · §3.8.1 (NVMe configuration access)
    文件頁 16–18 · PDF 16–18 · Figure 10–17

需要看欄位圖時

以下連結可開啟對應的圖表教學,查閱欄位及判讀方式。每張圖保留固定的教學位置,方便之後反覆查詢。

使用的原始文件
  • NVM Express Base Specification · Revision 2.4 · 2026-07-31
    NVM-Express-Base-Specification-Revision-2.4-Ratified-2026.07.31.pdf
  • NVM Express NVM Command Set Specification · Revision 1.3 · 2026-07-31
    NVM-Express-NVM-Command-Set-Specification-Revision-1.3-Ratified-2026.07.31.pdf
  • NVM Express NVMe over PCIe Transport Specification · Revision 1.4 · 2026-07-31
    NVM-Express-NVMe-over-PCIe-Transport-Specification-Revision-1.4-Ratified-2026.07.31.pdf