Tutorials
This page is hw/femu/docs/tutorials/README.md at FEMU 39a55eeb6 (2026-10-02), licensed GPL-2.0-or-later. Send corrections to the FEMU repository.
Hands-on walkthroughs. Each one starts a guest with an emulated device, runs a workload inside it, and reads what the device reports. Every tutorial stands on its own, but they build on each other in this order.
| Tutorial | You learn to | Device |
|---|---|---|
| 01 Your first SSD | boot a BlackBox SSD from your own QEMU command line, measure read and write latency, read the write amplification factor (WAF) | BBSSD, 2 GiB of NAND |
| 02 Garbage collection and WAF | provoke garbage collection (GC), measure the WAF of one run, and see how over-provisioning, the GC threshold, the victim policy and hot/cold separation change it | BBSSD |
| 03 Zoned namespaces | read the zone report, move zones through their states, use Zone Append, fio's zoned mode and zonefs | ZNS |
| 04 Flexible Data Placement | write through placement identifiers, read the FDP log pages, and measure what placement does to the WAF | BBSSD with FDP |
| 05 Latency tuning | change NAND times, the cell type, the channel bus, the host link and the firmware cost, and measure each with fio | BBSSD |
| 06 Several namespaces | run a BlackBox, a ZNS, a NoSSD and a KV namespace on one controller | mixed |
| 07 Key-value SSD | store, retrieve, list and delete values with nvme-cli | KV |
| 08 CXL SSD as memory | start a femu-cxl-ssd, find it in the guest, use it as a DAX device or a NUMA node, and read its counters | CXL Type-3 SSD |
| 09 Configuration files | describe a device in a file and expand it with ssd-config.sh instead of writing a long -device line | any |
Before you start
You need a built FEMU and a guest image. The
quick start does both in about five
minutes of work: femu-compile.sh in build-femu/ and
make-guest-image.sh for the image.
The tutorials use three shell variables on the host. Set them once in the terminal you start QEMU from and in the one you use to reach the guest:
cd build-femu # the directory femu-compile.sh built in
export IMGDIR=$HOME/images # where make-guest-image.sh put the image
export OSIMGF=$IMGDIR/u20s.qcow2 # the guest image
export SSH_PORT=8080 # host port forwarded to the guest's SSH
run-guest-ssh.sh reads IMGDIR and SSH_PORT, so with these set,
./run-guest-ssh.sh opens a shell in the guest and
./run-guest-ssh.sh CMD runs one command there.
How to read the tutorials
- Blocks marked as a FEMU example hold a QEMU command line or
-deviceoptions. The documentation checks start each of them under QEMU'sqtestaccelerator, so they are known to be accepted by the current code. The checks do not boot a guest. shblocks run inside the guest unless the text says "on the host". Run them in the shell./run-guest-ssh.shgives you.textblocks show output. Unless a block says it is illustrative, it was captured from a real run: FEMU at commit 1a03ded0f, the Ubuntu 24.04 guest frommake-guest-image.sh(Linux 6.8, nvme-cli 2.8, fio 3.36), on a 20-core host. Latencies and throughput depend on the host. Counter values such as the WAF depend only on the workload, and fio's random offsets change between runs, so expect them within a few percent of the values shown.- The QEMU command lines run without
sudo. That works when your user is in thekvmgroup; otherwise putsudoin front, as therun-*.shlaunchers do. Without root, FEMU usually cannot lock the device memory (ulimit -lis too small) and says so at start; the device works, but host paging can add jitter to latency, so usesudoor raise the limit for latency measurements. - Each emulated device lives in host memory: plan for the device size
plus the guest's
-min free host RAM.
Where to go next
- Measuring and performance tuning explain how to get numbers that repeat.
- The parameter manual explains every group of device parameters and how they interact.
- The design pages explain what happens inside the device.