Guest & devices

Virtio devices and storage

Standard virtio devices for disk, network, console, memory, entropy and file sharing, with one disk budget per VM.

FlashVMM's device model is a set of standard virtio-mmio devices (virtio-blk, virtio-net, virtio-console, virtio-balloon, virtio-mem, virtio-rng and virtio-fs) that a stock Linux guest drives with its upstream drivers, backed on every OS by per-VM copy-on-write storage and one host-enforced disk budget per FlashVM.

Every device is a modern (version 2) virtio-mmio register block with its own interrupt line, described to the guest at boot. The guest needs no custom drivers: the kernel's own virtio drivers find the devices and use them. Each OS implements the same devices on its native hypervisor (KVM on Linux, Hypervisor.framework on macOS, Windows Hypervisor Platform on Windows), and each backs the disk with that platform's own copy-on-write mechanism.

Key facts

Runs onLinux (KVM), macOS (HVF; the Virtualization.framework engine adds virtio-fs and Rosetta), Windows (WHP)
InterfacesCLI flash run --disk-mib --disk-bps --disk-iops --share --mem-region-mib, flash set, flash balloon, flash mem, flash share show · MCP flash_cli, flash_api · REST /v1/flashvm/disk, /v1/flashvm/memory/balloon, /v1/flashvm/memory/mem, /v1/flashvm/share
Devicesvirtio-blk (id 2), virtio-net (id 1), virtio-console (id 3), virtio-rng (id 4), virtio-balloon (id 5), virtio-fs (id 26; or virtio-9p, id 9, for older snapshots), virtio-mem (id 24)
Block featuresFLUSH (host fsync), DISCARD (hole punch), WRITE_ZEROES
Disk budget--disk-mib: disk size and quota in one, charged by real host blocks across the rootfs overlay and the shared folder; omitted = the image's size, no quota
virtio-mem block size2 MiB
ConsoleMultiport; the exec channel is port flashvm.exec

How it works

Storage: one shared base, one private overlay

The guest's root disk is a read-only base image shared by every VM, plus a private copy-on-write layer per VM. Reads fall through to the base for sectors the VM has not written; writes land only in that VM's layer, so many VMs share one base while each VM's writes stay its own. Each OS uses its native copy-on-write: Linux keeps a private anonymous overlay with a per-sector presence map; macOS uses APFS copy-on-write clones of the image; Windows uses a sparse NTFS overlay file per VM, removed with the VM. FLUSH makes a guest fsync durable on the host, DISCARD lets fstrim punch holes and give host blocks back, and WRITE_ZEROES zeroes a range without moving a zero payload.

Batched block I/O

On Linux, virtio-blk batches READ and WRITE requests from one queue notification through io_uring, in ring-sized sub-batches, and FLUSH, DISCARD and WRITE_ZEROES run on the synchronous path. This is on by default.

One disk budget

--disk-mib sets the disk's size and its quota together: the disk is that big, the guest agent grows the root filesystem online at boot to fill it, and the host stores only what is written, up to that budget. One budget covers everything the VM writes to host disk: the rootfs overlay (tracked incrementally as sectors become present) and the 9p share (recomputed from real on-disk blocks near the cap, so deleted files are refunded). Both are charged by actual disk blocks, so sparse files and truncate tricks count at their true cost. Admission is a reservation: a write atomically claims its worst case first and settles to the real growth after, so concurrent writes from several vCPUs stay within the cap. At the limit the guest sees ENOSPC or a block I/O error, exactly as a full disk. --disk-bps and --disk-iops add throughput and operation-rate caps; all three change on a running VM.

Network and console

virtio-net is covered on networking. virtio-console offers VIRTIO_CONSOLE_F_MULTIPORT and names its port flashvm.exec; the guest agent opens it for flash exec and flash cp traffic (see the guest and its agent).

Memory: balloon and virtio-mem

Every VM has a virtio-balloon. Setting a target asks the guest to return pages; the host releases each returned page with madvise(MADV_DONTNEED). The balloon also offers free-page reporting (VIRTIO_BALLOON_F_REPORTING, queue 2): the guest continuously hands back ranges of free memory and the host releases them, rounded to whole 4 KiB pages, with no host action. The two are counted separately, so a balloon request reports exactly the pages it reclaimed. A VM created with --mem-region-mib also gets a virtio-mem region that plugs and unplugs memory in 2 MiB blocks toward a live target. See memory.

Entropy

virtio-rng serves the guest from host randomness (on Linux, a /dev/urandom descriptor opened when the device is built). At cold boot the guest agent credits host entropy from virtio-rng or from the start frame; a restored or forked guest is reseeded from fresh bytes the host draws at resume. Details on the guest and its agent.

File sharing

virtio-fs exports one host directory to the guest with FlashVMM's own FUSE server, the same on every OS, mounted at the path the host names. Names and attributes are cached for one second, reads and writes go in 1 MiB requests, and the guest's page cache is dropped the moment a file changes on the host, so edits made on the host show up at once. Over 20,000 files on Apple silicon: walk and stat in 0.10 s, read every file in 0.08 s. Build output stays in the VM: node_modules, .venv and tool caches always, target, build, dist where the project’s .gitignore ignores them. The guest kernel keeps them on the VM’s own storage from the first file, decided per folder with nothing for a person or an AI agent to set up; the project folder on the host never sees them, and rm -rf works as anywhere. A real 10,000-file node_modules installs, resolves and reads in 0.3 s on Apple silicon, faster than on the Mac’s own disk; 1.1 s on Windows on Arm and 1.3 s on Linux. local=none sends it through the share instead. Folders can be exported beside it (a login, a cache), and with journal=on every change is recorded so a rewind puts the folder back too. Writes count against the disk budget. fs=9p serves the same folder over 9P2000.L for older snapshots.

Interfaces

CLI

# A 2 GiB disk (size and quota), throughput and IOPS caps, a share, a virtio-mem region
flash run --bundle ./bundle --vcpus 2 --mem-mib 1024 --id build \
  --disk-mib 2048 --disk-bps 104857600 --disk-iops 5000 \
  --share host_dir=/srv/work,tag=work,at=/data \
  --mem-region-mib 1024 --detach

# Change the disk budget and caps live (0 removes the quota)
flash set build --disk-mib 4096 --disk-bps 0

# Memory, live
flash balloon build --target-pages 65536
flash mem build --target-mib 512

# The share
flash share show build

MCP

flash_cli(args: ["set", "build", "--disk-mib", "4096"])
flash_api(vm_id: "build", method: "GET", path: "/v1/flashvm/disk")
flash_api(vm_id: "build", method: "PATCH", path: "/v1/flashvm/memory/balloon", body: {"target_pages": 65536})

REST

GET   /v1/flashvm/disk                 quota, rate caps and usage
PATCH /v1/flashvm/disk                 {"disk_mib": 4096, "disk_bps": 0, "disk_iops": 5000}
GET   /v1/flashvm/memory/balloon
PATCH /v1/flashvm/memory/balloon       {"target_pages": 65536}
GET   /v1/flashvm/memory/mem
PATCH /v1/flashvm/memory/mem           {"requested_mib": 512}
GET   /v1/flashvm/share

Contract:

  • PATCH /v1/flashvm/disk with none of its fields returns 422 nothing_to_change.
  • virtio-mem calls on a VM created without mem_region_mib return 422 mem_not_attached.
  • A balloon request on a paused VM returns 409 vm_paused; resume it first.
  • Devices are fixed at boot: attaching or detaching a share returns 422 share_immutable, and a NIC 409 hotplug_unsupported.

Guarantees

  • Stock drivers. Every device is upstream virtio, driven by the guest kernel's own drivers.
  • Private writes. The shared base is read-only; each VM's writes live in its own copy-on-write layer.
  • One honest budget. Disk and share are charged together by real host blocks, with reservations that hold under concurrent writes.
  • Durable when asked. A guest fsync reaches the host disk.
  • Memory flows back. Free guest memory returns to the host continuously, and on request.

See folder share, live limits and memory.

What it does

Related