NVMe userspace driver that takes a PCI function away from the kernel
  • C 56%
  • OCaml 39.6%
  • Shell 4.4%
Find a file
2026-08-20 23:34:08 +01:00
assets Initial commit 2026-08-20 18:02:53 +01:00
bin Add proper NVMe error type instead of negative int convention used throughout dma h 2026-08-20 18:59:39 +01:00
c Extract mock_state global into explicit handle so multiple mock controllers coexist per process 2026-08-20 19:36:15 +01:00
ocaml Add harness for nvme_prp_build covering malformed PRP list boundaries 2026-08-20 23:02:21 +01:00
scripts Mark gen_test_defaults.sh executable to match other scripts 2026-08-20 22:30:28 +01:00
test Add harness for nvme_prp_build covering malformed PRP list boundaries 2026-08-20 23:02:21 +01:00
.gitignore Initial commit 2026-08-20 18:02:53 +01:00
dune-project Initial commit 2026-08-20 18:02:53 +01:00
lantern.opam Initial commit 2026-08-20 18:02:53 +01:00
README.md Initial commit 2026-08-20 18:02:53 +01:00

lantern demo

Userspace NVMe driver that takes a PCI function away from the kernel through vfio-pci, maps the controller's BAR0 register window and a pool of DMA-able buffers into a process, and then drives the device entirely by hand from there. The kernel keeps only two responsibilities under this arrangement, namely handing over the container, group and device file descriptors, and programming the IOMMU so that every address the controller is told to fetch resolves back to a page the process genuinely owns.

Controller

The enable sequence begins by reading the capability register, because CAP.MQES bounds how deep any queue may be, CAP.DSTRD sets the stride between doorbell registers, CAP.TO gives the ready timeout in five hundred millisecond units, and CAP.MPSMIN decides whether the host page size is usable at all. With those values in hand the driver clears CC.EN and spins until CSTS.RDY falls, programs the admin queue sizes into AQA as zero-based values, writes the queue addresses into ASQ and ACQ, and only then sets CC.EN with an IOSQES of six and an IOCQES of four.

Controller register window

Boundary

Boundary selftest output

QEMU guest

QEMU guest run

Interrupts

Interrupt-driven benchmark