Skip to main content

NoSSD

Mirrored from the FEMU repository

This page is hw/femu/docs/modes/nossd.md at FEMU 39a55eeb6 (2026-10-02), licensed GPL-2.0-or-later. Send corrections to the FEMU repository.

NoSSD mode (femu_mode=2, the default) emulates an NVMe drive with no media model. Reads and writes copy data between guest memory and a host DRAM buffer and complete as soon as the poller finishes the copy. There is no FTL, no GC and no NAND time.

Use it when the storage device should not be the bottleneck: work on the host I/O stack, the NVMe driver, polling, SPDK or io_uring, or as an upper bound to compare a timed mode against. For a device with SSD latency and garbage collection, use BlackBox.

Requirements​

  • Host and guest: see the mode table and requirements.md. Any guest kernel with the NVMe driver works.
  • Host memory: devsz_mb plus guest RAM plus about 1 GiB for QEMU, about 9 GiB for run-nossd.sh (a 4 GiB device and a 4 GiB guest).
  • Host cores: the pollers spin on host cores. For throughput work, give each femu-poller thread a core of its own.

Launch​

From build-femu/:

./run-nossd.sh

The FEMU device in that script is:

-device femu,devsz_mb=4096,id=nvme0

femu_mode is not set, so it is 2. Writing femu_mode=2 has the same effect.

Configuration​

NoSSD ignores the NAND geometry, timing and FTL properties. These are the ones that change its behaviour.

Capacity and namespaces​

Properties: mode, capacity and namespaces.

devsz_mb is the namespace size. namespaces, namespace_sizes and namespace_modes split it into several namespaces (multi-namespace guide).

Queues and pollers​

Properties: queues, pollers and interrupts.

  • queues sets the number of I/O queue pairs (default 8).
  • By default one poller thread serves every I/O queue. With multipoller_enabled=1, FEMU runs ceil(queues / poller_ratio) pollers, each owning a round-robin share of the queues:
-device femu,devsz_mb=4096,queues=8,multipoller_enabled=1,poller_ratio=2

This starts four pollers. Give each one a host core.

Properties: host link and controller firmware.

pcie_bandwidth_mbps, pcie_prop_delay_ns and fw_cpu_ns add link and firmware time to each Read and Write. With any of them set, NoSSD completes commands through the same timed queue as the other modes instead of in the poller sweep, which adds work per command.

-device femu,devsz_mb=4096,pcie_bandwidth_mbps=3500,pcie_prop_delay_ns=1000

Optional commands and features​

Properties: controller identity and capabilities, LBA formats, metadata and protection.

  • oncs turns on optional NVM commands. The default (0x14) offers Dataset Management and Save/Select. Add 0x8 for Write Zeroes, 0x1 for Compare, 0x100 for Copy.
  • NoSSD supports namespace management, metadata and protection information and Streams (streams=on, which tracks streams but places nothing).

Use it from the guest​

Check the device:

sudo nvme list
sudo nvme id-ctrl /dev/nvme0 | grep -E '^(mn|sn) '

The model is FEMU NoSSD NVMe Controller and the serial number starts with vNoSSD.

Measure latency and throughput with fio. Unlike BlackBox, unwritten blocks read at the same speed as written ones:

sudo fio --name=lat --filename=/dev/nvme0n1 --direct=1 --ioengine=io_uring \
--rw=randread --bs=4k --iodepth=1 --runtime=30 --time_based
sudo fio --name=tput --filename=/dev/nvme0n1 --direct=1 --ioengine=io_uring \
--rw=randread --bs=4k --iodepth=64 --numjobs=4 --group_reporting \
--runtime=30 --time_based

The SMART log counts host reads and writes in every mode, NoSSD included:

sudo nvme smart-log /dev/nvme0

The vendor log page C0h stays zero: NoSSD has no media to count.

Limits and refusals​

MessageCause and fix
multipoller_enabled must be 0 (one poller for all queues) or 1 (each poller owns poller_ratio queues)Any other value.
queues must be in [1, 2047]queues out of range.
oncs may only set Compare, Write Uncorrectable, DSM, Write Zeroes, Save/Select Feature Support, Verify and CopyA bit FEMU does not implement.

If the host cannot allocate devsz_mb of memory, QEMU aborts in GLib with failed to allocate N bytes.

Verify​

  1. sudo nvme list shows the model FEMU NoSSD NVMe Controller.
  2. A queue depth 1 random read reports a completion latency of a few microseconds to tens of microseconds, depending on the host, with no difference between written and unwritten blocks.
  3. sudo nvme smart-log /dev/nvme0 shows the read and write command counts moving.

Troubleshooting​

  • Throughput does not grow with more guest jobs. A single poller serves every queue by default. Set multipoller_enabled=1 with a poller_ratio that leaves one poller per host core you can spare, and pin the threads.
  • Latency varies from run to run. The pollers compete with vCPUs and other host work. Pin vCPUs and pollers to separate cores, and keep the host CPU at a fixed frequency (see performance tuning).
  • Data is gone after QEMU exits. FEMU keeps the device only in host memory. A guest reboot keeps the data.

Related issues: #52, #69.