NVMe
NVMe
Category: Storage
Overview
NVMe (Non-Volatile Memory Express) is a storage protocol for flash over PCIe, replacing SATA AHCI. It supports up to 65,535 queues of 65,535 commands each for massive parallelism, achieving ~100µs latency and >7 GB/s throughput on PCIe 4.0 x4.
1. Theory & Fundamentals
- Interface: PCIe (x1/x2/x4); also NVMe-oF over TCP/RDMA
- Latency: ~100 µs consumer; ~10 µs Optane/datacenter
- Throughput: 7 GB/s read on PCIe 4.0 x4
- Queues: 1 Admin + up to 65,535 I/O queues
- Commands/queue: Up to 65,535 (vs AHCI single queue of 32)
- Form factors: M.2 2280, U.2, PCIe AIC, EDSFF
2. Frame / Packet Structure
NVMe Submission Queue Entry (64 bytes):
CDW0: Opcode(8b)|FUSE|PSDT|CID(16b)
NSID: Namespace ID
PRP1/PRP2: Data pointers (DMA)
CDW10–CDW15: Command-specific
Completion Queue Entry (16 bytes):
DW0: Result
DW2: SQ Head | SQ ID
DW3: CID | Phase | Status
Key opcodes:
Admin: 0x06=Identify, 0x09=Get Features
I/O: 0x01=Write, 0x02=Read, 0x00=Flush
3. Protocol Mechanics
- Doorbell: Host writes tail pointer to signal new SQ entries
- Completion: Controller writes CQE; asserts MSI-X interrupt
- Phase bit: Alternates 0/1 to distinguish old/new completions
- PRP: Physical Region Pages for scatter-gather DMA
- Namespace: Logical storage partition (NSID)
- Admin queue: Device config, firmware update, NS management
4. Hardware Implementation
- M.2 slot: 2280 most common (PCIe x4)
- SSDs: Samsung 990 Pro, WD Black SN850, SK Hynix P41
- SoC: i.MX8M, RK3588, Raspberry Pi CM4 with PCIe
- Industrial: M.2 SSD modules for embedded data logging
- Host controller: CPU PCIe root complex + Linux NVMe driver
5. Register-Level / Configuration
// NVMe BAR0 register definitions
#define NVME_REG_CAP 0x00 // Capabilities
#define NVME_REG_CC 0x14 // Controller Config
#define NVME_REG_CSTS 0x1C // Controller Status
#define NVME_REG_AQA 0x24 // Admin Queue Attrs
#define NVME_REG_ASQ 0x28 // Admin SQ Base Addr
#define NVME_REG_ACQ 0x30 // Admin CQ Base Addr
// Enable controller
*(uint32_t*)(bar0+NVME_REG_CC) = 0x00460001;
// Wait CSTS.RDY=1
while(!(*(uint32_t*)(bar0+NVME_REG_CSTS)&1));
6. Driver / Software Development
void NVMe_Read(uint32_t nsid, uint64_t slba,
uint16_t nlb, void *buf) {
NVMe_SQE cmd = {0};
cmd.cdw0 = 0x02; // Read opcode
cmd.nsid = nsid;
cmd.prp1 = virt_to_phys(buf);
cmd.cdw10 = slba & 0xFFFFFFFF;
cmd.cdw11 = slba >> 32;
cmd.cdw12 = nlb - 1; // 0-based
submit_sq_entry(&cmd);
ring_doorbell(io_sq_tail++);
wait_cq_completion();
}
7. Debugging & Testing
- nvme-cli:
nvme id-ctrl /dev/nvme0,nvme smart-log,nvme format - fio:
--ioengine=libaio --iodepth=32 --rw=randread --bs=4k - PCIe analyzer for link-level debug
- Common issues: PCIe link not training; DMA coherency; IOMMU issues; command timeout
8. Real-World Applications
- High-performance embedded systems (edge AI, video)
- Industrial PCs and HMIs
- Network appliances
- Medical imaging storage
- Autonomous vehicle data recording
9. Advanced Topics & Edge Cases
- NVMe-oF: NVMe over TCP or RDMA for disaggregated storage
- ZNS (Zoned Namespace): Append-only zones for write ordering
- Computational Storage: Execute code on NVMe device
- Multi-path I/O: Two paths to same SSD for availability
- PCIe 5.0: 14 GB/s per x4 for next-gen NVMe
10. Standards & Variants
| Version | Notes |
|---|---|
| NVMe 1.4 | Current base |
| NVMe 2.0 | Unified (base+ZNS+NVMe-oF) |
| NVMe-oF | Over TCP/RDMA |
| NVMe ZNS | Zoned namespace |
💡 Practical Examples
Ex 1: nvme id-ctrl /dev/nvme0 — model, serial, firmware, queue depths.
Ex 2: nvme smart-log /dev/nvme0 — temperature, wear indicator, error count.
Ex 3: fio benchmark: fio --name=rr --ioengine=libaio --iodepth=32 --rw=randread --bs=4k --size=10G --filename=/dev/nvme0n1
🧪 Practice Questions
Beginner: 1) NVMe interface? 2) Queue count? 3) What is a namespace? 4) Replaces what? 5) M.2 form factor?
Intermediate: 1) SQ/CQ doorbell mechanism. 2) Phase bit purpose. 3) Bare-metal Identify command. 4) PRP vs SGL. 5) NVMe vs SATA latency.
Advanced: 1) Bare-metal NVMe driver on ARM. 2) NVMe-oF TCP target. 3) ZNS log device. 4) Command timeout debug. 5) Firmware update via admin queue.
Checklist
- [ ] Understand NVMe queue model
- [ ] Read BAR0 capability registers
- [ ] Submit Admin Identify command
- [ ] Submit I/O Read and Write
- [ ] Handle completions correctly
- [ ] Use nvme-cli for management
- [ ] Benchmark with fio
- [ ] Debug with PCIe analyzer
- [ ] Implement multi-queue I/O
- [ ] Understand ZNS and NVMe-oF