Chapter 14: Firecracker's Device Model
If you run qemu-system-x86_64 --help and scroll through the device list, you will count hundreds of options: ISA bridges, SCSI controllers, USB hubs, VGA cards, audio codecs, NVMe controllers, PCI root complexes, and dozens more. A real cloud provider running QEMU must audit and seccomp-filter every one of those paths, because a compromised guest can reach any of them through the device protocol. The question Firecracker was designed to answer is whether a general-purpose virtual machine actually needs all of that surface, or whether a server workload can live comfortably inside a much shorter list.
The answer Firecracker gives in production is: seven device types. That is not a capability gap or a temporary limitation. It is the security model made concrete.
The Device Inventory
Firecracker's FAQ.md states the set directly: virtio-net, virtio-balloon, virtio-block, virtio-vsock, serial console, and a minimal keyboard controller. A seventh device — virtio-rng — was added in v1.4.0 and is exposed through the /entropy API endpoint. Every virtio device uses the MMIO transport; there is no PCI bus, no PCIe root complex, no USB controller, no GPU, no audio subsystem, no NVMe or SCSI stack, no virtio-console (device type 3), no virtio-GPU (type 16), no virtio-fs (type 26), no virtio-input (type 18), and no virtio-crypto (type 20). There is also no ACPI power management plane.
The full inventory as of Firecracker main (June 2026):
| Device | Virtio ID | Transport | Notes |
|---|---|---|---|
| virtio-net | 1 | MMIO | RX + TX queues; MMDS intercept embedded here |
| virtio-block | 2 | MMIO | 1 queue; sync or io_uring file engine |
| virtio-rng | 4 | MMIO | 1 queue; entropy from aws-lc-rs |
| virtio-balloon | 5 | MMIO | Traditional memory balloon |
| virtio-vsock | 19 | MMIO | 3 queues; AF_UNIX backend on host |
| Serial console | — | I/O port 0x3F8, IRQ 4 | 16550A UART via vm-superio |
| i8042 | — | I/O port 0x060, IRQ 1 | Reset signalling only |
The virtio IDs come from src/vmm/src/devices/virtio/generated/virtio_ids.rs; the legacy device registrations from src/vmm/src/device_manager/legacy.rs.
The two non-virtio entries — the serial console and the i8042 keyboard controller — deserve a word each. The i8042 is not there to support a keyboard. Its sole function is to let the guest signal a reboot. docs/design.md says as much: "Within Firecracker, the purpose of the I8042 device is to signal the microVM that the guest has requested a reboot." It is registered at I/O port 0x060, 5 bytes, IRQ GSI 1. Because the guest kernel is told via boot parameters (i8042.noaux i8042.nomux i8042.dumbkbd) not to probe the controller's hardware features, the actual I/O surface is small and the interaction is deterministic.
The serial console is a 16550A-compatible UART emulated by the vm-superio crate, specifically vm_superio::Serial. On x86_64 it appears at I/O port 0x3F8 (COM1), size 8 bytes, IRQ GSI 4. On aarch64 the same serial device is memory-mapped at SERIAL_MEM_START rather than an I/O port — a platform difference the guest kernel handles through its own driver but that the chapter source code in legacy.rs makes explicit per-arch. The serial console is not a virtio device and does not appear in the MMIO device region; it is a classic ISA-style I/O-port device that predates the virtio era entirely.
The virtio-MMIO Transport
Connecting the guest to a device requires a transport: a shared protocol by which the guest driver and the host device negotiate capabilities, exchange buffers, and signal completion. QEMU supports two transports for virtio: PCI and MMIO. Firecracker uses only MMIO, implementing OASIS virtio specification version 1.2, §4.2.
The choice matters for boot latency and attack surface simultaneously. A PCI bus requires an ACPI table for device discovery, a host bridge emulator, interrupt routing through an I/O APIC, and MSI/MSI-X plumbing for modern devices. MMIO skips all of that: the guest learns about each device's location from the kernel command line (the virtio_mmio.device= parameter), and the transport consists of a fixed-layout register window per device. There is nothing dynamic to probe and nothing to enumerate.
Each virtio-MMIO device in Firecracker occupies exactly MMIO_LEN = 0x1000 bytes (4 KiB) of MMIO address space. On x86_64 the first device slot starts at MEM_32BIT_DEVICES_START = 0xC000_1000, immediately after a boot timer device that sits at MMIO32_MEM_START = 0xC000_0000. Each additional device is assigned the next 4 KiB-aligned slot via AllocPolicy::FirstMatch in src/vmm/src/device_manager/mmio.rs. The address layout is fixed at VM construction time; there is no hotplug.
The Register Map
Every virtio-MMIO device exposes the same register layout at the base of its 4 KiB window, defined by virtio 1.2 §4.2.2 and implemented in src/vmm/src/devices/virtio/transport/mmio.rs:
| Offset | Size | R/W | Field |
|---|---|---|---|
| 0x000 | 4 | RO | MagicValue (0x7472_6976, ASCII "virt") |
| 0x004 | 4 | RO | Version (0x2; not legacy 0x1) |
| 0x008 | 4 | RO | DeviceID (virtio type integer) |
| 0x00c | 4 | RO | VendorID (0x0) |
| 0x010 | 4 | RO | DeviceFeatures (page selected by 0x014) |
| 0x014 | 4 | WO | DeviceFeaturesSel |
| 0x020 | 4 | WO | DriverFeatures |
| 0x024 | 4 | WO | DriverFeaturesSel |
| 0x030 | 4 | WO | QueueSel |
| 0x034 | 4 | RO | QueueNumMax (queue's max_size) |
| 0x038 | 4 | WO | QueueNum |
| 0x044 | 4 | RW | QueueReady |
| 0x050 | 4 | WO | QueueNotify (NOTIFY_REG_OFFSET) |
| 0x060 | 4 | RO | InterruptStatus (bit 0 = vring, bit 1 = config change) |
| 0x064 | 4 | WO | InterruptACK |
| 0x070 | 4 | RW | DeviceStatus |
| 0x080 | 4 | WO | QueueDescLow |
| 0x084 | 4 | WO | QueueDescHigh |
| 0x090 | 4 | WO | QueueAvailLow |
| 0x094 | 4 | WO | QueueAvailHigh |
| 0x0a0 | 4 | WO | QueueUsedLow |
| 0x0a4 | 4 | WO | QueueUsedHigh |
| 0x0fc | 4 | RO | ConfigGeneration |
| 0x100–0xfff | var | RW | Device-specific configuration space |
The MagicValue at offset 0x000 reads 0x7472_6976 — the ASCII bytes for "virt" stored little-endian. A guest driver that sees any other value knows immediately that the MMIO window does not contain a virtio device. The Version field reads 0x2, explicitly distinguishing this from the legacy virtio 0.9 transport (which reads 0x1); Firecracker does not support the legacy transport.
Initialization: The Status State Machine
Device initialization follows a strict state machine mandated by virtio 1.2 §3.1.1 and enforced in src/vmm/src/devices/virtio/mod.rs. The sequence is: write 0 to DeviceStatus (reset), then set ACKNOWLEDGE (bit 0, value 1) to signal the driver has found the device, then set DRIVER (bit 1, value 2) to signal it knows how to drive it. After that comes feature negotiation — the driver reads DeviceFeatures with DeviceFeaturesSel cycling through 32-bit pages, sets DriverFeatures similarly, then sets FEATURES_OK (bit 3, value 8) and re-reads DeviceStatus to confirm the device accepted the negotiated feature set. Only if FEATURES_OK is still set does the driver proceed to configure virtqueues and finally set DRIVER_OK (bit 2, value 4) to indicate readiness.
Two additional bits signal abnormal states: DEVICE_NEEDS_RESET (bit 6, value 64) is set by the device when it encounters an unrecoverable error; FAILED (bit 7, value 128) is set by the driver when it gives up. Writes that set FAILED are accepted at any point; clearing individual bits other than a full reset (writing 0) is rejected. The state machine is not a suggestion — a guest that attempts to skip steps gets a device that stays inert.
Queue Notification and ioeventfd
The most performance-sensitive operation in the virtio protocol is the queue notification: the moment the guest driver tells the host that it has placed new buffers into the available ring. If this notification required a full VM exit — the vCPU exiting to kernel mode, the kernel dispatching the MMIO write to the VMM, the VMM processing it — the round-trip cost would dominate I/O latency.
Firecracker avoids this via KVM's ioeventfd mechanism. When a device is registered, the VMM calls KVM_IOEVENTFD to install an ioeventfd at the device's notify register address, device_base + NOTIFY_REG_OFFSET where NOTIFY_REG_OFFSET = 0x050. The queue index is passed as the datamatch value. From that point on, the guest's write to offset 0x050 causes KVM to signal the corresponding eventfd file descriptor directly, without returning to userspace through the normal MMIO exit path. The VMM thread watching that eventfd wakes up and processes the queue — still in userspace, still in the firecracker process, but without a kernel round-trip for the notification itself. The code is in src/vmm/src/device_manager/mmio.rs.
The IRQ Limit
Originally Firecracker gave each virtio device its own legacy GSI line, which capped the device count at 11. IRQ sharing was added in PR #2286 to relax that limit. The current ceiling is 19 virtio devices, bounded by available legacy GSI lines (GSI 5 through 23) rather than by MMIO address space or any architectural constraint. In practice, the defined device catalog reaches nowhere near that ceiling — the constraint is policy, not capacity.
The Individual Devices
virtio-net
The network device has two queues: RX (index 0) and TX (index 1). There is no control virtqueue. Both queues are capped at NET_QUEUE_MAX_SIZE = 256 descriptors. The maximum frame buffer size is MAX_BUFFER_SIZE = 65562 bytes. The constant is defined as the raw integer in src/vmm/src/devices/virtio/net/mod.rs without an explanatory comment; the arithmetic that accounts for it — 65536-byte maximum Ethernet payload, 12-byte virtio_net_hdr_v1 header, 14-byte Ethernet frame header — is inferred from the value.
The feature bits Firecracker always advertises include checksum offload on both sides (VIRTIO_NET_F_CSUM bit 0, VIRTIO_NET_F_GUEST_CSUM bit 1), TSO4 and TSO6 in both directions (bits 7, 8, 11, 12), UFO in both directions (bits 10, 14), receive buffer merging (VIRTIO_NET_F_MRG_RXBUFbit 15),VIRTIO_F_VERSION_1(bit 32), andVIRTIO_RING_F_EVENT_IDX(bit 29). MAC address support (VIRTIO_NET_F_MACbit 5) and MTU advertisement (VIRTIO_NET_F_MTUbit 3) are offered conditionally when the respective values are configured at VM creation time. Notably,VIRTIO_NET_F_STATUS(bit 16) and multiqueue supportVIRTIO_NET_F_MQ` (bit 22) are intentionally not advertised — there is no live link status signalling and only one pair of queues.
The device-specific configuration space exposed at register offset 0x100 holds: guest_mac (6 bytes), a status word and a max virtqueue pairs word that are both present for protocol compliance but unused, and the MTU (2 bytes).
virtio-block
The block device uses a single queue with a maximum of 256 descriptors (FIRECRACKER_MAX_QUEUE_SIZE = 256) and addresses storage in 512-byte sectors. The feature set is pared to what a container workload actually needs: VIRTIO_F_VERSION_1 (bit 32) and VIRTIO_RING_F_EVENT_IDX (bit 29) always; VIRTIO_BLK_F_FLUSH (bit 9) when the drive is configured with writeback caching; VIRTIO_BLK_F_RO (bit 5) for read-only drives. Geometry, topology, and size/segment-max negotiation are not advertised. The device configuration space contains exactly one field: capacity, a u64 counting 512-byte sectors.
Firecracker implements three operation types: VIRTIO_BLK_T_IN (read), VIRTIO_BLK_T_OUT (write), and VIRTIO_BLK_T_FLUSH. Discard (VIRTIO_BLK_T_DISCARD) and write-zeroes (VIRTIO_BLK_T_WRITE_ZEROES) are not implemented — the tradeoff is explicit in the source rather than simply absent.
The device supports two file engines: a synchronous engine that issues blocking syscalls, and an asynchronous engine backed by io_uring with a submission queue depth of IO_URING_NUM_ENTRIES = 128 entries. Disk identity for snapshot versioning is a 20-byte ASCII string (VIRTIO_BLK_ID_BYTES = 20) derived from the backing file's st_dev, st_rdev, and st_ino fields.
virtio-vsock
The vsock device provides a stream socket channel between the guest and a process on the host without requiring a network interface or IP routing. It has three queues: RX (index 0), TX (index 1), and Event (index 2), each sized 256 descriptors. Feature bits: VIRTIO_F_VERSION_1 (bit 32), VIRTIO_F_IN_ORDER (bit 35), and VIRTIO_RING_F_EVENT_IDX (bit 29). VIRTIO_VSOCK_F_SEQPACKET is not advertised.
The host CID is hardcoded as VSOCK_HOST_CID = 2, as the virtio-vsock specification reserves. The guest CID is user-configured at VM creation time.
The backend is an AF_UNIX socket on the host, not the vhost-vsock kernel module. This is deliberate. vhost would move the data path into the kernel, eliminating some context switches, but the kernel would then become directly reachable from the guest — which is precisely the attack surface that the combination of KVM and seccomp filtering is designed to interpose. From Issue #650: "we don't want to use vhost since that would be another attack surface to directly expose the host kernel." The AF_UNIX backend stays in the firecracker userspace process, subject to the same seccomp filter as every other VMM operation.
Connection routing works as follows: connections that the host initiates arrive at the single UDS path configured at boot time; Firecracker forwards them into the guest on the appropriate port. Connections that the guest initiates cause Firecracker to open a UDS path derived from the configured path plus the target port number — for example, if the UDS path is ./v.sock, a guest connection to port 52 causes Firecracker to connect to ./v.sock_52. The maximum per-packet buffer is MAX_PKT_BUF_SIZE = 64 * 1024 (64 KiB).
virtio-rng
The entropy device is the newest addition to the standard catalog, shipping in Firecracker v1.4.0. It has one queue, 256 descriptors, and no device-specific configuration space — read_config and write_config are both no-ops, which is correct: OASIS virtio 1.2 §5.4 defines no device-specific feature bits or configuration fields for RNG devices. The only feature bit is VIRTIO_F_VERSION_1 (bit 32).
The entropy source is aws-lc-rs, AWS's Rust bindings to AWS-LC — a FIPS-validated fork of BoringSSL. Each request calls aws_lc_rs::rand::fill(&mut rand_bytes). Individual requests are capped at MAX_ENTROPY_BYTES = 64 * 1024 (65536 bytes) to prevent a single oversized descriptor chain from monopolizing the device. On the guest side the device appears as /dev/hwrng, which requires CONFIG_HW_RANDOM_VIRTIO=y in the kernel configuration.
The rationale for using aws-lc-rs rather than the kernel's getrandom(2) comes down to the same seccomp concern seen elsewhere in Firecracker: getrandom is not in the Firecracker seccomp allowlist by default, and relying on a library that manages its own entropy pool avoids the need to add a system call to the filter surface.
virtio-balloon
The balloon device appears in the inventory table but is not covered in depth here — its interface is straightforward enough not to warrant it. It exposes two queues: an inflate queue (index 0) on which the guest returns physical page frame numbers the host may reclaim, and a deflate queue (index 1) on which the host returns pages to the guest. A third stats queue is defined by the virtio spec but is optional and not all configurations enable it. The balloon device has no device-specific configuration fields beyond the standard feature negotiation. Its role in a microVM context is memory overcommit recovery — allowing the host to reclaim guest pages under pressure without a full guest shutdown.
MMDS: Metadata Without a Second Network Interface
Every cloud provider needs a way to deliver instance metadata to a running virtual machine — the AWS instance identity document, credentials refreshed from IAM, user data scripts, and similar dynamic configuration. The traditional approach is to run a separate HTTP server on a link-local address (169.254.169.254 in the AWS case) and route guest traffic to it. For a microVM that starts in well under a second and runs for seconds, standing up a separate network path for metadata has disproportionate cost.
Firecracker's solution is MMDS — the MicroVM Metadata Service — implemented not as a separate device but as a software shim embedded inside the virtio-net device path. The implementation is called MmdsNetworkStack, or "Dumbo" in internal Firecracker naming. Every Ethernet frame leaving the guest through the virtio-net TX queue is inspected before being forwarded to the host TAP file descriptor. If the frame's IPv4 destination address matches the configured MMDS address, it is diverted to Dumbo instead of transmitted.
Dumbo is a bespoke HTTP 1.1 / TCP / IPv4 stack implemented inside the firecracker process, outside the KVM boundary. It is deliberately narrow: it handles GET and PUT requests only, implements no congestion control, handles no 802.1Q VLAN tagging, and does no IP fragmentation. ARP responses use the fixed MAC address 06:01:23:45:67:01. The implementation lives in src/vmm/src/devices/virtio/net/device.rs, woven into the same code that handles normal frame forwarding.
MMDS supports two versions. V1 requires no authentication — any guest process can read metadata — and is deprecated. V2 follows the IMDSv2 pattern: the guest first sends a PUT to /latest/api/token with the header X-metadata-token-ttl-seconds (range: 1 through 21600 seconds), receives a token, and presents that token in subsequent GET requests via X-metadata-token or X-aws-ec2-metadata-token. This prevents server-side request forgery attacks where a guest web server is tricked into relaying metadata to an external attacker.
The elegance of MMDS is that it adds no device, no IRQ, no MMIO window, no additional seccomp filter surface, and no process boundary. It reuses the packet processing path that is already active for every frame the guest sends.
Rate Limiters
Running multi-tenant workloads on shared hardware requires more than memory and CPU isolation. A guest that drives its virtio-block device at full disk bandwidth starves every other microVM on the same host. Firecracker addresses this with token-bucket rate limiters that can be applied per-device to two independent dimensions: bytes (bandwidth) and operations per second (ops).
Rate limiting for block and net devices was introduced in Firecracker v0.4.0. The one-time burst feature was added in v0.7.0. The ability to update rate limiters on running block and net devices via PATCH was added in v0.24.0. As of v1.16.0, rate limiting was extended to the serial console (PR #5824).
The Token Bucket
The implementation lives in src/vmm/src/rate_limiter/mod.rs as TokenBucket:
pub struct TokenBucket {
size: u64, // max capacity (tokens)
initial_one_time_burst: u64, // original burst budget, never replenished
refill_time: u64, // ms to refill from 0 to size
one_time_burst: u64, // remaining burst credit
budget: u64, // current token budget
last_update: Instant,
processed_capacity: u64, // size / gcd(size, refill_time_ns)
processed_refill_time: u64, // refill_time_ns / gcd(size, refill_time_ns)
}
TokenBucket::new() returns None — rate limiting disabled — when size == 0 or complete_refill_time_ms == 0. An enabled bucket starts full (budget == size). Refill is computed on demand rather than on a tick:
refill_amount = (time_delta_ns * processed_capacity) / processed_refill_time
The fields processed_capacity and processed_refill_time are the GCD-reduced forms of size and refill_time_ns. This prevents integer overflow in the multiplication without losing precision on the refill rate. Sub-token time accumulation is handled by advancing last_update by the exact nanoseconds consumed for the tokens generated, not by the raw elapsed time — so fractional-token time carries forward and the long-run rate is exact.
The reduce() Call and Its Three Outcomes
When a device wants to process a request, it calls TokenBucket::reduce(n) where n is the token cost of the operation. The call returns one of three variants:
BucketReduction::Success — the budget covered the request; tokens are deducted and processing proceeds immediately.
BucketReduction::Failure — even after a passive replenish (update budget based on elapsed time since last_update), there are not enough tokens. The request is deferred.
BucketReduction::OverConsumption(f64) — the request exceeds the bucket's total size, meaning it would need to borrow more than one full refill cycle's worth of tokens. This case resolves Issue #259, which identified a deadlock: if the only request in flight is larger than the bucket size, a strict "must have tokens" policy blocks it forever, because the bucket can never grow large enough. Instead, Firecracker allows it, drains budget to zero, and returns the overconsumption ratio as a f64. The comment in mod.rs describes it as "overconsumption of (remaining tokens / size) times larger than the bucket size"; the formula is (request_size − remaining_budget) / bucket_size, where remaining_budget is what is left after passive auto-replenishment at the moment of the call. The ratio is used to compute an appropriate back-pressure delay.
The one_time_burst field is consumed first. If the burst allowance covers the entire request, the regular budget is not touched at all. This means a freshly-started microVM can absorb a startup I/O spike beyond the steady-state rate limit before the regular bucket begins draining.
The RateLimiter and Its Timer
pub struct RateLimiter {
bandwidth: Option<TokenBucket>, // byte tokens
ops: Option<TokenBucket>, // operation tokens
timer_fd: TimerFd,
timer_active: bool,
}
A single RateLimiter pairs two independent TokenBucket instances — one for bandwidth (bytes), one for operation count — with a TimerFd for deferred resumption. Both buckets must agree that a request can proceed; if either returns Failure, the timer is armed for REFILL_TIMER_DURATION = Duration::from_millis(100) (a compile-time constant, not configurable via API). On OverConsumption(ratio), the timer is armed for ratio * refill_time milliseconds instead. While timer_active == true, consume() returns false immediately, gating both buckets with a single timer regardless of which one triggered the throttle.
There is a subtle implementation point worth naming: the TimerFd is created at RateLimiter::new() time even when both buckets are None and rate limiting is effectively disabled. The reason is that the Firecracker seccomp filter may block timerfd_create(2) at the time a rate limiter is later re-enabled via update_buckets(). Creating the fd up front, when the process still has an unrestricted syscall surface, prevents a later seccomp violation from silently disabling rate limiting at runtime.
RateLimiter implements AsRawFd. The VMM's epoll loop watches the timer fd and calls event_handler() when it fires, which clears timer_active and allows the device's queue processing to resume.
API Schema and Runtime Updates
The TokenBucket object in Firecracker's OpenAPI spec (src/firecracker/swagger/firecracker.yaml) exposes three fields: size (int64, minimum 0 — total token capacity), refill_time (int64, in milliseconds — time to refill from empty to full), and one_time_burst (int64, optional). The effective steady-state rate in tokens per second is size / (refill_time / 1000).
A RateLimiter object wraps two optional TokenBucket instances under the keys bandwidth and ops. Rate limiters are accepted on:
PUT /drives/{drive_id}andPATCH /drives/{drive_id}(block devices, ops and bandwidth)PUT /network-interfaces/{iface_id}andPATCH /network-interfaces/{iface_id}(net, ops and bandwidth)PUT /serial(serial console, since v1.16.0)PUT /pmem/{id}(virtio-pmem, since v1.16.0, PR #5789)
virtio-pmem is not part of the standard device catalog described in this chapter, but it accepts the same RateLimiter schema as the devices above.
To disable an existing rate limiter while the VM is running, send size: 0, refill_time: 0; TokenBucket::new() returns None and update_buckets() sets the field to None, removing the throttle entirely until a new non-zero configuration is applied.
Rate limiter state survives snapshot-restore. The persisted form TokenBucketState in src/vmm/src/rate_limiter/persist.rs stores size, one_time_burst, refill_time, the current budget, and elapsed_ns (nanoseconds since last_update). Restoring this state reconstructs the bucket mid-flight, preserving the throttle window that was active at snapshot time rather than resetting every bucket to full.
Why the List Is Short
The device model's length is not an engineering tradeoff between development time and capability. It is a direct consequence of the threat model stated in docs/design.md:
"All vCPU threads are considered to be running malicious code as soon as they have been started; these malicious threads need to be contained."
Every device emulator is code reachable from the guest through the virtio queue protocol — or, for legacy devices, through I/O port reads and writes. A device class that does not exist cannot have an exploitable implementation bug. QEMU's device catalog has been the source of dozens of CVEs: heap overflows in the Cirrus VGA emulator, out-of-bounds writes in the ATI MMIO handler, USB subsystem escapes, NVMe controller vulnerabilities. Firecracker avoids that surface by never implementing those device classes, not by attempting to audit and harden them.
The vsock backend makes the same argument — see §virtio-vsock — and so does the choice of MMIO over PCI: narrower transport, smaller guest-reachable surface. The principle generalizes across every entry in the inventory.
The question for each potential addition is not "could we implement this?" but "does this attack surface cost less than the capability it provides?" For server workloads running functions and containers, virtio-net, virtio-block, virtio-vsock, virtio-rng, a serial console, and a reboot signal are sufficient. The catalog is closed precisely because that boundary is defensible.
Sources And Further Reading
- Firecracker source tree (
main, June 2026): https://github.com/firecracker-microvm/firecracker FAQ.md— device inventory and design philosophy: https://github.com/firecracker-microvm/firecracker/blob/main/FAQ.mddocs/design.md— threat model and i8042 purpose: https://github.com/firecracker-microvm/firecracker/blob/main/docs/design.mddocs/entropy.md— virtio-rng design andaws-lc-rsrationale: https://github.com/firecracker-microvm/firecracker/blob/main/docs/entropy.mddocs/vsock.md— vsock backend, UDS routing, connection protocol: https://github.com/firecracker-microvm/firecracker/blob/main/docs/vsock.mddocs/mmds/mmds-design.md— Dumbo, V1/V2 authentication design: https://github.com/firecracker-microvm/firecracker/blob/main/docs/mmds/mmds-design.mddocs/mmds/mmds-user-guide.md— MMDS operator reference: https://github.com/firecracker-microvm/firecracker/blob/main/docs/mmds/mmds-user-guide.mddocs/kernel-policy.md— i8042 boot parameter policy: https://github.com/firecracker-microvm/firecracker/blob/main/docs/kernel-policy.mdCHANGELOG.md— version history for rate limiter, virtio-rng, v1.16.0 changes: https://github.com/firecracker-microvm/firecracker/blob/main/CHANGELOG.md- virtio-MMIO transport source —
src/vmm/src/devices/virtio/transport/mmio.rs: https://github.com/firecracker-microvm/firecracker/blob/main/src/vmm/src/devices/virtio/transport/mmio.rs - MMIO device manager —
src/vmm/src/device_manager/mmio.rs: https://github.com/firecracker-microvm/firecracker/blob/main/src/vmm/src/device_manager/mmio.rs - Rate limiter source —
src/vmm/src/rate_limiter/mod.rs: https://github.com/firecracker-microvm/firecracker/blob/main/src/vmm/src/rate_limiter/mod.rs - Rate limiter persist —
src/vmm/src/rate_limiter/persist.rs: https://github.com/firecracker-microvm/firecracker/blob/main/src/vmm/src/rate_limiter/persist.rs - OpenAPI spec —
src/firecracker/swagger/firecracker.yaml: https://github.com/firecracker-microvm/firecracker/blob/main/src/firecracker/swagger/firecracker.yaml - OASIS virtio 1.2 CS01 — transport register map (§4.2), initialization sequence (§3.1.1), RNG device (§5.4): https://docs.oasis-open.org/virtio/virtio/v1.2/cs01/virtio-v1.2-cs01.html
- Issue #650 — vsock vhost exclusion rationale: https://github.com/firecracker-microvm/firecracker/issues/650
- Issue #1268 — legacy GSI IRQ limit and sharing: https://github.com/firecracker-microvm/firecracker/issues/1268
- Issue #259 — rate limiter OverConsumption deadlock fix: https://github.com/firecracker-microvm/firecracker/issues/259
- PR #5789 — virtio-pmem rate limiting (v1.16.0): https://github.com/firecracker-microvm/firecracker/pull/5789
- PR #5824 — serial console rate limiting (v1.16.0): https://github.com/firecracker-microvm/firecracker/pull/5824
- AWS Open Source Blog — Announcing Firecracker (2018): https://aws.amazon.com/blogs/opensource/firecracker-open-source-secure-fast-microvm-serverless/