├── .buildkite ├── common.py ├── pipeline_cpu_template.py ├── pipeline_cross.py ├── pipeline_perf.py ├── pipeline_pr.py └── pipeline_pr_no_block.py ├── .cargo ├── audit.toml └── config.toml ├── .dockerignore ├── .git-blame-ignore-revs ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── codecov.yml ├── dependabot.yml ├── pull_request_template.md └── workflows │ ├── deny_dirty_cargo_locks.yml │ ├── dependency_modification_check.yml │ ├── send_pr_notification.yml │ ├── send_release_notification.yml │ └── trigger_ab_tests.yml ├── .gitignore ├── .gitlint ├── .mailmap ├── .mdformat.toml ├── .python-version ├── CHANGELOG.md ├── CHARTER.md ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── CREDITS.md ├── Cargo.lock ├── Cargo.toml ├── DEPRECATED.md ├── FAQ.md ├── LICENSE ├── MAINTAINERS.md ├── NOTICE ├── PGP-KEY.asc ├── README.md ├── SECURITY.md ├── SPECIFICATION.md ├── THIRD-PARTY ├── deny.toml ├── docs ├── RELEASE_POLICY.md ├── api-change-runbook.md ├── api_requests │ ├── actions.md │ ├── block-caching.md │ ├── block-io-engine.md │ ├── block-vhost-user.md │ ├── patch-block.md │ └── patch-network-interface.md ├── ballooning.md ├── cpu_templates │ ├── boot-protocol.md │ ├── cpu-template-helper.md │ ├── cpu-templates.md │ ├── cpuid-normalization.md │ └── schema.json ├── design.md ├── dev-machine-setup.md ├── device-api.md ├── entropy.md ├── formal-verification.md ├── gdb-debugging.md ├── getting-started.md ├── hugepages.md ├── images │ ├── api_change_flowchart.png │ ├── fc_decal_icon-dark_dark-bg.png │ ├── fc_decal_icon-dark_dark-bg.svg │ ├── fc_logo_full.svg │ ├── fc_logo_full_transparent-bg.png │ ├── fc_logo_full_transparent-bg_white-fg.png │ ├── fc_logo_full_white-bg.png │ ├── fc_logo_full_white-bg_tiny.png │ ├── fc_logo_icon-dark.svg │ ├── fc_logo_icon.svg │ ├── fc_logo_icon_transparent-bg.png │ ├── fc_logo_icon_transparent-bg_square.png │ ├── fc_logo_icon_white-bg.png │ ├── fc_logo_icon_white-bg_square.png │ ├── fc_sticker_full_white-bg.png │ ├── fc_sticker_full_white-bg.svg │ ├── fc_sticker_icon_white-bg.png │ ├── fc_sticker_icon_white-bg.svg │ ├── firecracker_host_integration.png │ ├── firecracker_threat_containment.png │ ├── uffd_flow1.png │ ├── uffd_flow2.png │ ├── uffd_flow3.png │ ├── uffd_flow4.png │ ├── vsock-connections.drawio │ └── vsock-connections.png ├── initrd.md ├── jailer.md ├── kernel-policy.md ├── logger.md ├── metrics.md ├── mmds │ ├── mmds-design.md │ └── mmds-user-guide.md ├── network-performance.md ├── network-setup.md ├── prod-host-setup.md ├── pvh.md ├── rootfs-and-kernel-setup.md ├── seccomp.md ├── seccompiler.md ├── snapshotting │ ├── handling-page-faults-on-snapshot-resume.md │ ├── network-for-clones.md │ ├── random-for-clones.md │ ├── snapshot-editor.md │ ├── snapshot-support.md │ └── versioning.md ├── tracing.md └── vsock.md ├── resources ├── chroot.sh ├── guest_configs │ ├── DISCLAIMER.md │ ├── ci.config │ ├── debug.config │ ├── ftrace.config │ ├── microvm-kernel-ci-aarch64-5.10.config │ ├── microvm-kernel-ci-aarch64-6.1.config │ ├── microvm-kernel-ci-x86_64-5.10-no-acpi.config │ ├── microvm-kernel-ci-x86_64-5.10.config │ └── microvm-kernel-ci-x86_64-6.1.config ├── overlay │ ├── etc │ │ └── systemd │ │ │ └── system │ │ │ ├── fcnet.service │ │ │ └── var-lib-systemd.mount │ └── usr │ │ └── local │ │ └── bin │ │ ├── devmemread.c │ │ ├── fast_page_fault_helper.c │ │ ├── fcnet-setup.sh │ │ ├── fillmem.c │ │ ├── init.c │ │ └── readmem.c ├── rebuild.sh └── seccomp │ ├── aarch64-unknown-linux-musl.json │ ├── unimplemented.json │ └── x86_64-unknown-linux-musl.json ├── rust-toolchain.toml ├── src ├── acpi-tables │ ├── Cargo.toml │ └── src │ │ ├── aml.rs │ │ ├── dsdt.rs │ │ ├── fadt.rs │ │ ├── lib.rs │ │ ├── madt.rs │ │ ├── rsdp.rs │ │ └── xsdt.rs ├── clippy-tracing │ ├── Cargo.toml │ ├── README.md │ ├── src │ │ └── main.rs │ └── tests │ │ └── integration_tests.rs ├── cpu-template-helper │ ├── Cargo.toml │ ├── build.rs │ └── src │ │ ├── fingerprint │ │ ├── compare.rs │ │ ├── dump.rs │ │ └── mod.rs │ │ ├── main.rs │ │ ├── template │ │ ├── dump │ │ │ ├── aarch64.rs │ │ │ ├── mod.rs │ │ │ └── x86_64.rs │ │ ├── mod.rs │ │ ├── strip │ │ │ ├── aarch64.rs │ │ │ ├── mod.rs │ │ │ └── x86_64.rs │ │ └── verify │ │ │ ├── aarch64.rs │ │ │ ├── mod.rs │ │ │ └── x86_64.rs │ │ └── utils │ │ ├── aarch64.rs │ │ ├── mock_kernel │ │ └── main.c │ │ ├── mod.rs │ │ └── x86_64.rs ├── firecracker │ ├── Cargo.toml │ ├── build.rs │ ├── examples │ │ ├── README.md │ │ ├── seccomp │ │ │ ├── harmless.rs │ │ │ ├── jailer.rs │ │ │ ├── malicious.rs │ │ │ └── panic.rs │ │ └── uffd │ │ │ ├── fault_all_handler.rs │ │ │ ├── malicious_handler.rs │ │ │ ├── on_demand_handler.rs │ │ │ └── uffd_utils.rs │ ├── src │ │ ├── api_server │ │ │ ├── mod.rs │ │ │ ├── parsed_request.rs │ │ │ └── request │ │ │ │ ├── actions.rs │ │ │ │ ├── balloon.rs │ │ │ │ ├── boot_source.rs │ │ │ │ ├── cpu_configuration.rs │ │ │ │ ├── drive.rs │ │ │ │ ├── entropy.rs │ │ │ │ ├── instance_info.rs │ │ │ │ ├── logger.rs │ │ │ │ ├── machine_configuration.rs │ │ │ │ ├── metrics.rs │ │ │ │ ├── mmds.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── net.rs │ │ │ │ ├── snapshot.rs │ │ │ │ ├── version.rs │ │ │ │ └── vsock.rs │ │ ├── api_server_adapter.rs │ │ ├── generated │ │ │ ├── mod.rs │ │ │ └── prctl.rs │ │ ├── lib.rs │ │ ├── main.rs │ │ ├── metrics.rs │ │ └── seccomp.rs │ ├── swagger │ │ └── firecracker.yaml │ └── tests │ │ └── verify_dependencies.rs ├── jailer │ ├── Cargo.toml │ └── src │ │ ├── cgroup.rs │ │ ├── chroot.rs │ │ ├── env.rs │ │ ├── main.rs │ │ └── resource_limits.rs ├── log-instrument-macros │ ├── Cargo.toml │ └── src │ │ └── lib.rs ├── log-instrument │ ├── Cargo.toml │ ├── README.md │ ├── examples │ │ ├── five.rs │ │ ├── four.rs │ │ ├── one.rs │ │ ├── six.rs │ │ ├── three.rs │ │ └── two.rs │ └── src │ │ └── lib.rs ├── rebase-snap │ ├── Cargo.toml │ └── src │ │ └── main.rs ├── seccompiler │ ├── Cargo.toml │ ├── build.rs │ └── src │ │ ├── bin.rs │ │ ├── bindings.rs │ │ ├── lib.rs │ │ └── types.rs ├── snapshot-editor │ ├── Cargo.toml │ └── src │ │ ├── edit_memory.rs │ │ ├── edit_vmstate.rs │ │ ├── info.rs │ │ ├── main.rs │ │ └── utils.rs ├── utils │ ├── Cargo.toml │ └── src │ │ ├── arg_parser.rs │ │ ├── lib.rs │ │ ├── time.rs │ │ └── validators.rs └── vmm │ ├── Cargo.toml │ ├── benches │ ├── block_request.rs │ ├── cpu_templates.rs │ ├── memory_access.rs │ └── queue.rs │ ├── src │ ├── acpi │ │ ├── mod.rs │ │ └── x86_64.rs │ ├── arch │ │ ├── aarch64 │ │ │ ├── cache_info.rs │ │ │ ├── fdt.rs │ │ │ ├── gic │ │ │ │ ├── gicv2 │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── regs │ │ │ │ │ │ ├── dist_regs.rs │ │ │ │ │ │ ├── icc_regs.rs │ │ │ │ │ │ └── mod.rs │ │ │ │ ├── gicv3 │ │ │ │ │ ├── mod.rs │ │ │ │ │ └── regs │ │ │ │ │ │ ├── dist_regs.rs │ │ │ │ │ │ ├── icc_regs.rs │ │ │ │ │ │ ├── mod.rs │ │ │ │ │ │ └── redist_regs.rs │ │ │ │ ├── mod.rs │ │ │ │ └── regs.rs │ │ │ ├── kvm.rs │ │ │ ├── layout.rs │ │ │ ├── mod.rs │ │ │ ├── output_GICv2.dtb │ │ │ ├── output_GICv3.dtb │ │ │ ├── output_initrd_GICv2.dtb │ │ │ ├── output_initrd_GICv3.dtb │ │ │ ├── regs.rs │ │ │ ├── vcpu.rs │ │ │ └── vm.rs │ │ ├── mod.rs │ │ └── x86_64 │ │ │ ├── cpu_model.rs │ │ │ ├── gdt.rs │ │ │ ├── generated │ │ │ ├── arch_prctl.rs │ │ │ ├── hyperv.rs │ │ │ ├── hyperv_tlfs.rs │ │ │ ├── mod.rs │ │ │ ├── mpspec.rs │ │ │ ├── msr_index.rs │ │ │ └── perf_event.rs │ │ │ ├── interrupts.rs │ │ │ ├── kvm.rs │ │ │ ├── layout.rs │ │ │ ├── mod.rs │ │ │ ├── mptable.rs │ │ │ ├── msr.rs │ │ │ ├── regs.rs │ │ │ ├── vcpu.rs │ │ │ ├── vm.rs │ │ │ └── xstate.rs │ ├── builder.rs │ ├── cpu_config │ │ ├── aarch64 │ │ │ ├── custom_cpu_template.rs │ │ │ ├── mod.rs │ │ │ ├── static_cpu_templates │ │ │ │ ├── mod.rs │ │ │ │ └── v1n1.rs │ │ │ └── test_utils.rs │ │ ├── mod.rs │ │ ├── templates.rs │ │ ├── templates_serde.rs │ │ ├── test_utils.rs │ │ └── x86_64 │ │ │ ├── cpuid │ │ │ ├── amd │ │ │ │ ├── mod.rs │ │ │ │ └── normalize.rs │ │ │ ├── common.rs │ │ │ ├── intel │ │ │ │ ├── mod.rs │ │ │ │ └── normalize.rs │ │ │ ├── mod.rs │ │ │ └── normalize.rs │ │ │ ├── custom_cpu_template.rs │ │ │ ├── mod.rs │ │ │ ├── static_cpu_templates │ │ │ ├── c3.rs │ │ │ ├── mod.rs │ │ │ ├── t2.rs │ │ │ ├── t2a.rs │ │ │ ├── t2cl.rs │ │ │ └── t2s.rs │ │ │ └── test_utils.rs │ ├── device_manager │ │ ├── acpi.rs │ │ ├── legacy.rs │ │ ├── mmio.rs │ │ ├── mod.rs │ │ ├── persist.rs │ │ └── resources.rs │ ├── devices │ │ ├── acpi │ │ │ ├── mod.rs │ │ │ └── vmgenid.rs │ │ ├── bus.rs │ │ ├── legacy │ │ │ ├── i8042.rs │ │ │ ├── mod.rs │ │ │ ├── rtc_pl031.rs │ │ │ └── serial.rs │ │ ├── mod.rs │ │ ├── pseudo │ │ │ ├── boot_timer.rs │ │ │ └── mod.rs │ │ └── virtio │ │ │ ├── balloon │ │ │ ├── device.rs │ │ │ ├── event_handler.rs │ │ │ ├── metrics.rs │ │ │ ├── mod.rs │ │ │ ├── persist.rs │ │ │ ├── test_utils.rs │ │ │ └── util.rs │ │ │ ├── block │ │ │ ├── device.rs │ │ │ ├── mod.rs │ │ │ ├── persist.rs │ │ │ ├── vhost_user │ │ │ │ ├── device.rs │ │ │ │ ├── event_handler.rs │ │ │ │ ├── mod.rs │ │ │ │ └── persist.rs │ │ │ └── virtio │ │ │ │ ├── device.rs │ │ │ │ ├── event_handler.rs │ │ │ │ ├── io │ │ │ │ ├── async_io.rs │ │ │ │ ├── mod.rs │ │ │ │ └── sync_io.rs │ │ │ │ ├── metrics.rs │ │ │ │ ├── mod.rs │ │ │ │ ├── persist.rs │ │ │ │ ├── request.rs │ │ │ │ └── test_utils.rs │ │ │ ├── device.rs │ │ │ ├── generated │ │ │ ├── mod.rs │ │ │ ├── virtio_blk.rs │ │ │ ├── virtio_config.rs │ │ │ ├── virtio_net.rs │ │ │ └── virtio_ring.rs │ │ │ ├── iov_deque.rs │ │ │ ├── iovec.rs │ │ │ ├── mmio.rs │ │ │ ├── mod.rs │ │ │ ├── net │ │ │ ├── device.rs │ │ │ ├── event_handler.rs │ │ │ ├── generated │ │ │ │ ├── if_tun.rs │ │ │ │ ├── iff.rs │ │ │ │ ├── mod.rs │ │ │ │ └── sockios.rs │ │ │ ├── metrics.rs │ │ │ ├── mod.rs │ │ │ ├── persist.rs │ │ │ ├── tap.rs │ │ │ └── test_utils.rs │ │ │ ├── persist.rs │ │ │ ├── queue.rs │ │ │ ├── rng │ │ │ ├── device.rs │ │ │ ├── event_handler.rs │ │ │ ├── metrics.rs │ │ │ ├── mod.rs │ │ │ └── persist.rs │ │ │ ├── test_utils.rs │ │ │ ├── vhost_user.rs │ │ │ ├── vhost_user_metrics.rs │ │ │ └── vsock │ │ │ ├── csm │ │ │ ├── connection.rs │ │ │ ├── mod.rs │ │ │ └── txbuf.rs │ │ │ ├── device.rs │ │ │ ├── event_handler.rs │ │ │ ├── metrics.rs │ │ │ ├── mod.rs │ │ │ ├── packet.rs │ │ │ ├── persist.rs │ │ │ ├── test_utils.rs │ │ │ └── unix │ │ │ ├── mod.rs │ │ │ ├── muxer.rs │ │ │ ├── muxer_killq.rs │ │ │ └── muxer_rxq.rs │ ├── dumbo │ │ ├── mod.rs │ │ ├── pdu │ │ │ ├── arp.rs │ │ │ ├── bytes.rs │ │ │ ├── ethernet.rs │ │ │ ├── ipv4.rs │ │ │ ├── mod.rs │ │ │ ├── tcp.rs │ │ │ └── udp.rs │ │ └── tcp │ │ │ ├── connection.rs │ │ │ ├── endpoint.rs │ │ │ ├── handler.rs │ │ │ └── mod.rs │ ├── gdb │ │ ├── arch │ │ │ ├── aarch64.rs │ │ │ ├── mod.rs │ │ │ └── x86.rs │ │ ├── event_loop.rs │ │ ├── mod.rs │ │ └── target.rs │ ├── initrd.rs │ ├── io_uring │ │ ├── generated.rs │ │ ├── mod.rs │ │ ├── operation │ │ │ ├── cqe.rs │ │ │ ├── mod.rs │ │ │ └── sqe.rs │ │ ├── probe.rs │ │ ├── queue │ │ │ ├── completion.rs │ │ │ ├── mmap.rs │ │ │ ├── mod.rs │ │ │ └── submission.rs │ │ └── restriction.rs │ ├── lib.rs │ ├── logger │ │ ├── logging.rs │ │ ├── metrics.rs │ │ └── mod.rs │ ├── mmds │ │ ├── data_store.rs │ │ ├── mod.rs │ │ ├── ns.rs │ │ ├── persist.rs │ │ ├── token.rs │ │ └── token_headers.rs │ ├── persist.rs │ ├── rate_limiter │ │ ├── mod.rs │ │ └── persist.rs │ ├── resources.rs │ ├── rpc_interface.rs │ ├── seccomp.rs │ ├── signal_handler.rs │ ├── snapshot │ │ ├── crc.rs │ │ ├── mod.rs │ │ └── persist.rs │ ├── test_utils │ │ ├── mock_resources │ │ │ ├── dirtying_init.tgz │ │ │ ├── make_noisy_kernel.sh │ │ │ ├── mod.rs │ │ │ ├── test_elf.bin │ │ │ ├── test_noisy_elf.bin │ │ │ └── test_pe.bin │ │ └── mod.rs │ ├── utils │ │ ├── byte_order.rs │ │ ├── mod.rs │ │ ├── net │ │ │ ├── ipv4addr.rs │ │ │ ├── mac.rs │ │ │ └── mod.rs │ │ ├── signal.rs │ │ └── sm.rs │ ├── vmm_config │ │ ├── balloon.rs │ │ ├── boot_source.rs │ │ ├── drive.rs │ │ ├── entropy.rs │ │ ├── instance_info.rs │ │ ├── machine_config.rs │ │ ├── metrics.rs │ │ ├── mmds.rs │ │ ├── mod.rs │ │ ├── net.rs │ │ ├── snapshot.rs │ │ └── vsock.rs │ └── vstate │ │ ├── kvm.rs │ │ ├── memory.rs │ │ ├── mod.rs │ │ ├── vcpu.rs │ │ └── vm.rs │ └── tests │ ├── devices.rs │ ├── integration_tests.rs │ └── io_uring.rs ├── tests ├── README.md ├── conftest.py ├── data │ ├── cpu_template_helper │ │ ├── fingerprint_AMD_GENOA_5.10host.json │ │ ├── fingerprint_AMD_GENOA_6.1host.json │ │ ├── fingerprint_AMD_MILAN_5.10host.json │ │ ├── fingerprint_AMD_MILAN_6.1host.json │ │ ├── fingerprint_ARM_NEOVERSE_N1_5.10host.json │ │ ├── fingerprint_ARM_NEOVERSE_N1_6.1host.json │ │ ├── fingerprint_ARM_NEOVERSE_V1_5.10host.json │ │ ├── fingerprint_ARM_NEOVERSE_V1_6.1host.json │ │ ├── fingerprint_ARM_NEOVERSE_V2_5.10host.json │ │ ├── fingerprint_ARM_NEOVERSE_V2_6.1host.json │ │ ├── fingerprint_INTEL_CASCADELAKE_5.10host.json │ │ ├── fingerprint_INTEL_CASCADELAKE_6.1host.json │ │ ├── fingerprint_INTEL_ICELAKE_5.10host.json │ │ ├── fingerprint_INTEL_ICELAKE_6.1host.json │ │ ├── fingerprint_INTEL_SAPPHIRE_RAPIDS_5.10host.json │ │ ├── fingerprint_INTEL_SAPPHIRE_RAPIDS_6.1host.json │ │ ├── fingerprint_INTEL_SKYLAKE_5.10host.json │ │ └── fingerprint_INTEL_SKYLAKE_6.1host.json │ ├── custom_cpu_templates │ │ ├── AARCH64_WITH_SVE_AND_PAC.json │ │ ├── C3.json │ │ ├── SPR_TO_T2_5.10.json │ │ ├── SPR_TO_T2_6.1.json │ │ ├── T2.json │ │ ├── T2A.json │ │ ├── T2CL.json │ │ ├── T2S.json │ │ └── V1N1.json │ ├── metadata.json │ ├── metadata_invalid.json │ └── msr │ │ ├── msr_list_SPR_TO_T2_5.10_INTEL_SAPPHIRE_RAPIDS_5.10host_5.10guest.csv │ │ ├── msr_list_SPR_TO_T2_5.10_INTEL_SAPPHIRE_RAPIDS_5.10host_6.1guest.csv │ │ ├── msr_list_SPR_TO_T2_6.1_INTEL_SAPPHIRE_RAPIDS_6.1host_5.10guest.csv │ │ ├── msr_list_SPR_TO_T2_6.1_INTEL_SAPPHIRE_RAPIDS_6.1host_6.1guest.csv │ │ ├── msr_list_T2A_AMD_MILAN_5.10host_5.10guest.csv │ │ ├── msr_list_T2A_AMD_MILAN_5.10host_6.1guest.csv │ │ ├── msr_list_T2A_AMD_MILAN_6.1host_5.10guest.csv │ │ ├── msr_list_T2A_AMD_MILAN_6.1host_6.1guest.csv │ │ ├── msr_list_T2CL_INTEL_CASCADELAKE_5.10host_5.10guest.csv │ │ ├── msr_list_T2CL_INTEL_CASCADELAKE_5.10host_6.1guest.csv │ │ ├── msr_list_T2CL_INTEL_CASCADELAKE_6.1host_5.10guest.csv │ │ ├── msr_list_T2CL_INTEL_CASCADELAKE_6.1host_6.1guest.csv │ │ ├── msr_list_T2CL_INTEL_ICELAKE_5.10host_5.10guest.csv │ │ ├── msr_list_T2CL_INTEL_ICELAKE_5.10host_6.1guest.csv │ │ ├── msr_list_T2CL_INTEL_ICELAKE_6.1host_5.10guest.csv │ │ ├── msr_list_T2CL_INTEL_ICELAKE_6.1host_6.1guest.csv │ │ ├── msr_list_T2S_INTEL_CASCADELAKE_5.10host_5.10guest.csv │ │ ├── msr_list_T2S_INTEL_CASCADELAKE_5.10host_6.1guest.csv │ │ ├── msr_list_T2S_INTEL_CASCADELAKE_6.1host_5.10guest.csv │ │ ├── msr_list_T2S_INTEL_CASCADELAKE_6.1host_6.1guest.csv │ │ ├── msr_list_T2S_INTEL_SKYLAKE_5.10host_5.10guest.csv │ │ ├── msr_list_T2S_INTEL_SKYLAKE_5.10host_6.1guest.csv │ │ ├── msr_list_T2S_INTEL_SKYLAKE_6.1host_5.10guest.csv │ │ ├── msr_list_T2S_INTEL_SKYLAKE_6.1host_6.1guest.csv │ │ ├── msr_reader.sh │ │ ├── msr_writer.sh │ │ └── wrmsr_list.txt ├── fmt.toml ├── framework │ ├── __init__.py │ ├── ab_test.py │ ├── artifacts.py │ ├── defs.py │ ├── gitlint_rules.py │ ├── http_api.py │ ├── jailer.py │ ├── microvm.py │ ├── microvm_helpers.py │ ├── properties.py │ ├── state_machine.py │ ├── static_analysis.py │ ├── utils.py │ ├── utils_cpu_templates.py │ ├── utils_cpuid.py │ ├── utils_drive.py │ ├── utils_ftrace.py │ ├── utils_imdsv2.py │ ├── utils_iperf.py │ ├── utils_repo.py │ ├── utils_uffd.py │ ├── utils_vsock.py │ ├── vm_config.json │ ├── vm_config_cpu_template_C3.json │ ├── vm_config_missing_mem_size_mib.json │ ├── vm_config_missing_vcpu_count.json │ ├── vm_config_network.json │ ├── vm_config_smt_true.json │ ├── vm_config_with_mmdsv1.json │ ├── vm_config_with_mmdsv2.json │ └── with_filelock.py ├── host_tools │ ├── __init__.py │ ├── cargo_build.py │ ├── change_net_config_space.c │ ├── cpu_load.py │ ├── drive.py │ ├── fcmetrics.py │ ├── memory.py │ ├── metrics.py │ ├── network.py │ ├── proc.py │ ├── test_syscalls.c │ ├── udp_offload.py │ ├── vsock_helper.c │ └── waitpkg.c ├── integration_tests │ ├── build │ │ ├── test_clippy.py │ │ ├── test_coverage.py │ │ ├── test_dependencies.py │ │ ├── test_gdb.py │ │ ├── test_seccomp_no_redundant_rules.py │ │ └── test_unittests.py │ ├── functional │ │ ├── conftest.py │ │ ├── test_api.py │ │ ├── test_api_server.py │ │ ├── test_balloon.py │ │ ├── test_binary.py │ │ ├── test_binary_size.py │ │ ├── test_cmd_line_parameters.py │ │ ├── test_cmd_line_start.py │ │ ├── test_concurrency.py │ │ ├── test_cpu_all.py │ │ ├── test_cpu_features_aarch64.py │ │ ├── test_cpu_features_host_vs_guest.py │ │ ├── test_cpu_features_x86_64.py │ │ ├── test_cpu_template_helper.py │ │ ├── test_dirty_pages_in_full_snapshot.py │ │ ├── test_drive_vhost_user.py │ │ ├── test_drive_virtio.py │ │ ├── test_error_code.py │ │ ├── test_feat_parity.py │ │ ├── test_kernel_cmdline.py │ │ ├── test_kvm_ptp.py │ │ ├── test_log_instrument.py │ │ ├── test_logging.py │ │ ├── test_max_devices.py │ │ ├── test_metrics.py │ │ ├── test_mmds.py │ │ ├── test_net.py │ │ ├── test_net_config_space.py │ │ ├── test_pause_resume.py │ │ ├── test_pvtime.py │ │ ├── test_rng.py │ │ ├── test_rtc.py │ │ ├── test_serial_io.py │ │ ├── test_shut_down.py │ │ ├── test_signals.py │ │ ├── test_snapshot_basic.py │ │ ├── test_snapshot_editor.py │ │ ├── test_snapshot_not_losing_dirty_pages.py │ │ ├── test_snapshot_phase1.py │ │ ├── test_snapshot_restore_cross_kernel.py │ │ ├── test_topology.py │ │ ├── test_uffd.py │ │ └── test_vsock.py │ ├── performance │ │ ├── test_benchmarks.py │ │ ├── test_block_ab.py │ │ ├── test_boottime.py │ │ ├── test_drive_rate_limiter.py │ │ ├── test_huge_pages.py │ │ ├── test_initrd.py │ │ ├── test_memory_overhead.py │ │ ├── test_network_ab.py │ │ ├── test_process_startup_time.py │ │ ├── test_rate_limiter.py │ │ ├── test_snapshot_ab.py │ │ ├── test_steal_time.py │ │ ├── test_vhost_user_metrics.py │ │ └── test_vsock_ab.py │ ├── security │ │ ├── conftest.py │ │ ├── test_custom_seccomp.py │ │ ├── test_jail.py │ │ ├── test_nv.py │ │ ├── test_sec_audit.py │ │ ├── test_seccomp.py │ │ ├── test_seccomp_validate.py │ │ └── test_vulnerabilities.py │ ├── style │ │ ├── test_gitlint.py │ │ ├── test_licenses.py │ │ ├── test_markdown.py │ │ ├── test_python.py │ │ ├── test_repo.py │ │ ├── test_rust.py │ │ └── test_swagger.py │ └── test_kani.py ├── pyproject.toml └── pytest.ini └── tools ├── ab_test.py ├── bindgen-patches └── 0001-change-c_char-to-c_uchar-in-ifrn_name.patch ├── bindgen.sh ├── bump-version.sh ├── devctr ├── Dockerfile ├── ctr_gitconfig ├── poetry.lock └── pyproject.toml ├── devtool ├── functions ├── gh_release.py ├── release-notes.py ├── release-prepare.sh ├── release-tag.sh ├── release.sh ├── sandbox.py ├── setup-ci-artifacts.sh ├── test-popular-containers ├── build_rootfs.sh ├── fcnet.start └── test-docker-rootfs.py ├── test.sh ├── test_bindings.py └── update-credits.sh /.buildkite/pipeline_pr_no_block.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | """Generate Buildkite pipelines dynamically""" 6 | 7 | from common import BKPipeline, get_changed_files, run_all_tests 8 | 9 | # Buildkite default job priority is 0. Setting this to 1 prioritizes PRs over 10 | # scheduled jobs and other batch jobs. 11 | DEFAULT_PRIORITY = 1 12 | 13 | pipeline = BKPipeline( 14 | with_build_step=False, 15 | timeout_in_minutes=45, 16 | # some non-blocking tests are performance, so make sure they get ag=1 instances 17 | priority=DEFAULT_PRIORITY + 1, 18 | agents={"ag": 1}, 19 | ) 20 | 21 | pipeline.build_group( 22 | "❓ Optional", 23 | pipeline.devtool_test( 24 | devtool_opts="--performance -c 1-10 -m 0", 25 | pytest_opts="integration_tests/ -m 'no_block_pr and not nonci' --log-cli-level=INFO", 26 | ), 27 | ) 28 | if not run_all_tests(get_changed_files()): 29 | pipeline.steps = [] 30 | print(pipeline.to_json()) 31 | -------------------------------------------------------------------------------- /.cargo/audit.toml: -------------------------------------------------------------------------------- 1 | [advisories] 2 | # The `paste` dependency is transitively included via `gdbstub`. 3 | # While the crate is archived/unmaintained, the author considers it feature-complete 4 | # and functionally stable. gdbstub will be update once they migrate 5 | # to an alternative solution. 6 | # See https://github.com/daniel5151/gdbstub/issues/168 7 | ignore = ["RUSTSEC-2024-0436"] 8 | -------------------------------------------------------------------------------- /.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target-dir = "build/cargo_target" 3 | rustflags = [ 4 | "-Ccodegen-units=1", 5 | ] 6 | 7 | [net] 8 | git-fetch-with-cli = true 9 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | .git/ 2 | build/ 3 | src/ 4 | tests/ 5 | docs/ 6 | resources/ 7 | tools/test-popular-containers/ 8 | test_results/ 9 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | 8d2463fa21386d6c0c90b2010aaee5550b505c87 2 | ae93e49470433648b144a64514eef708cce15143 3 | 45739f4b57b7b824473b612aefebec8b7c2e31fd 4 | 7221ae7f943bcd127c6710e81d9fa2f520afa073 5 | 7c4687fab64d4dd574fe43cf583a302b43ce53ab 6 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # All markdown files 2 | *.md @xmarcalx @kalyazin @pb8o @Manciukic 3 | 4 | # But not the ones in docs/ 5 | docs/*.md 6 | 7 | # Except these specific ones 8 | docs/getting-started.md @xmarcalx @kalyazin @pb8o @Manciukic 9 | docs/prod-host-setup.md @xmarcalx @kalyazin @pb8o @Manciukic 10 | 11 | # Also cover all "*policy*.md" documents 12 | **/*policy*.md @xmarcalx @kalyazin @pb8o @Manciukic 13 | **/*POLICY*.md @xmarcalx @kalyazin @pb8o @Manciukic 14 | 15 | # Also these non-md files in the repository root 16 | THIRD_PARTY @xmarcalx @kalyazin @pb8o @Manciukic 17 | LICENSE @xmarcalx @kalyazin @pb8o @Manciukic 18 | NOTICE @xmarcalx @kalyazin @pb8o @Manciukic 19 | PGP-KEY.asc @xmarcalx @kalyazin @pb8o @Manciukic 20 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '[Bug] Title' 5 | labels: 'Quality: Bug' 6 | assignees: '' 7 | --- 8 | 9 | # Describe the bug 10 | 11 | `[Author TODO: A clear and concise description of what the bug is.]` 12 | 13 | ## To Reproduce 14 | 15 | `[Author TODO: Steps to reproduce the behaviour:]` 16 | 17 | 1. Start Firecracker via.... 18 | 1. Configure Firecracker via... 19 | 1. ... 20 | 21 | ## Expected behaviour 22 | 23 | `[Author TODO: A clear and concise description of what you expected to happen.]` 24 | 25 | ## Environment 26 | 27 | `[Author TODO: Please supply the following information):]` 28 | 29 | - Firecracker version: 30 | - Host and guest kernel versions: 31 | - Rootfs used: 32 | - Architecture: 33 | - Any other relevant software versions: 34 | 35 | ## Additional context 36 | 37 | `[Author TODO: How has this bug affected you?]` 38 | 39 | `[Author TODO: What are you trying to achieve?]` 40 | 41 | `[Author TODO: Do you have any idea of what the solution might be?]` 42 | 43 | ## Checks 44 | 45 | - [ ] Have you searched the Firecracker Issues database for similar problems? 46 | - [ ] Have you read the existing relevant Firecracker documentation? 47 | - [ ] Are you certain the bug being reported is a Firecracker issue? 48 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '[Feature Request] Title' 5 | labels: '' 6 | assignees: '' 7 | --- 8 | 9 | # Feature Request 10 | 11 | `[Author TODO: Why is this feature request important? What are the use cases? Please describe.]` 12 | 13 | ## Describe the desired solution 14 | 15 | `[Author TODO: A clear and concise description of how you would like the feature to work.]` 16 | 17 | ## Describe possible alternatives 18 | 19 | `[Author TODO: A clear and concise description of any alternative solutions or features you have considered.]` 20 | 21 | `[Author TODO: How do you work around not having this feature?]` 22 | 23 | ## Additional context 24 | 25 | `[Author TODO: Add additional context about this feature request here.]` 26 | 27 | ## Checks 28 | 29 | - [ ] Have you searched the Firecracker Issues database for similar requests? 30 | - [ ] Have you read all the existing relevant Firecracker documentation? 31 | - [ ] Have you read and understood Firecracker's core tenets? 32 | -------------------------------------------------------------------------------- /.github/codecov.yml: -------------------------------------------------------------------------------- 1 | codecov: 2 | # We utilize optional statuses that are okay to fail, so 3 | # having codecov only post if all statuses pass won't work. 4 | require_ci_to_pass: no 5 | notify: 6 | # No need to wait for long running tests if the build tests are done. 7 | wait_for_ci: false 8 | coverage: 9 | # Our target is 80% coverage 10 | range: 80..100 11 | status: 12 | project: 13 | firecracker: 14 | # Allow drop of up to 0.5% 15 | threshold: 0.5% 16 | target: 80% 17 | # There are 15 uploads per commit (|{instance type} x {kernel version}| = 15). 18 | # Codecov will update the comment with every new upload. If we want to instead 19 | # only post the comment after all 15 reports are received, add `after_n_builds: 15` 20 | # below 21 | comment: 22 | # Only relevant for initial report: We want a report even though 23 | # codecov integration is not merged to main yet, to see it works 24 | # without having to go through multiple PR cycles. 25 | require_base: false 26 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: "cargo" 4 | directory: "/" 5 | schedule: 6 | interval: "weekly" 7 | day: "monday" 8 | allow: 9 | - dependency-type: "all" 10 | open-pull-requests-limit: 100 11 | groups: 12 | firecracker: 13 | patterns: 14 | - "*" 15 | -------------------------------------------------------------------------------- /.github/pull_request_template.md: -------------------------------------------------------------------------------- 1 | ## Changes 2 | 3 | ... 4 | 5 | ## Reason 6 | 7 | ... 8 | 9 | ## License Acceptance 10 | 11 | By submitting this pull request, I confirm that my contribution is made under 12 | the terms of the Apache 2.0 license. For more information on following Developer 13 | Certificate of Origin and signing off your commits, please check 14 | [`CONTRIBUTING.md`][3]. 15 | 16 | ## PR Checklist 17 | 18 | - [ ] I have read and understand [CONTRIBUTING.md][3]. 19 | - [ ] I have run `tools/devtool checkstyle` to verify that the PR passes the 20 | automated style checks. 21 | - [ ] I have described what is done in these changes, why they are needed, and 22 | how they are solving the problem in a clear and encompassing way. 23 | - [ ] I have updated any relevant documentation (both in code and in the docs) 24 | in the PR. 25 | - [ ] I have mentioned all user-facing changes in `CHANGELOG.md`. 26 | - [ ] If a specific issue led to this PR, this PR closes the issue. 27 | - [ ] When making API changes, I have followed the 28 | [Runbook for Firecracker API changes][2]. 29 | - [ ] I have tested all new and changed functionalities in unit tests and/or 30 | integration tests. 31 | - [ ] I have linked an issue to every new `TODO`. 32 | 33 | ______________________________________________________________________ 34 | 35 | - [ ] This functionality cannot be added in [`rust-vmm`][1]. 36 | 37 | [1]: https://github.com/rust-vmm 38 | [2]: https://github.com/firecracker-microvm/firecracker/blob/main/docs/api-change-runbook.md 39 | [3]: https://github.com/firecracker-microvm/firecracker/blob/main/CONTRIBUTING.md 40 | -------------------------------------------------------------------------------- /.github/workflows/deny_dirty_cargo_locks.yml: -------------------------------------------------------------------------------- 1 | name: Check no Cargo.lock files are dirty 2 | 3 | on: pull_request 4 | 5 | jobs: 6 | no_dirty_cargo_locks_check: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: "Checkout repository" 10 | uses: actions/checkout@v3 11 | with: 12 | ref: ${{ github.event.pull_request.head.sha }} 13 | 14 | - name: "Check no Cargo.lock files are dirty" 15 | run: | 16 | exit_code=0 17 | # This breaks for paths with whitespaces in them, but we have an integration test 18 | # that prevents those from existing in this repository. 19 | for f in $(find . -name 'Cargo.lock' -not -path "./build/*"); do 20 | is_dirty=0 21 | ( 22 | cd "$(dirname "$f")" 23 | cargo --locked metadata --format-version 1 >/dev/null 2>&1 24 | ) || is_dirty=$?; 25 | # GitHub Actions execute run steps as `bash -e`, so we need the temporary 26 | # variable to not exit early. 27 | if [ $is_dirty -ne 0 ]; then 28 | echo "Lockfile $f is dirty" 29 | exit_code=1 30 | fi 31 | done 32 | exit $exit_code 33 | -------------------------------------------------------------------------------- /.github/workflows/dependency_modification_check.yml: -------------------------------------------------------------------------------- 1 | name: Check no dependencies were modified 2 | 3 | on: pull_request 4 | 5 | jobs: 6 | dependency_changed_check: 7 | runs-on: ubuntu-latest 8 | steps: 9 | - name: "Checkout repository" 10 | uses: actions/checkout@v3 11 | with: 12 | ref: ${{ github.event.pull_request.head.sha }} 13 | 14 | - name: "Check Cargo.lock not in changeset" 15 | run: | 16 | git fetch origin 17 | git diff origin/$GITHUB_BASE_REF.. --name-only| ( ! grep "Cargo.lock") 18 | -------------------------------------------------------------------------------- /.github/workflows/send_pr_notification.yml: -------------------------------------------------------------------------------- 1 | name: Send notification on PR opened 2 | 3 | on: 4 | pull_request_target: 5 | types: [labeled] 6 | 7 | jobs: 8 | send_notification: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: notify 12 | run: | 13 | if ${{ github.event.label.name == format('Status{0} Awaiting review', ':') }}; then 14 | curl -X POST ${{ secrets.SLACK_PR_NOTIFICATION_WEBHOOK }} \ 15 | -H 'Content-Type: application/json' \ 16 | -d '{ "GITHUB_PR_URL": "${{ github.event.pull_request.html_url }}", 17 | "PR_ADDITIONS": "${{ github.event.pull_request.additions }}", 18 | "PR_DELETIONS": "${{ github.event.pull_request.deletions }}", 19 | "PR_CHANGED_FILES": "${{ github.event.pull_request.changed_files }}"}' 20 | fi 21 | -------------------------------------------------------------------------------- /.github/workflows/send_release_notification.yml: -------------------------------------------------------------------------------- 1 | name: Send notification on release created 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | send_notification: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - name: notify 12 | run: | 13 | curl -X POST ${{ secrets.SLACK_RELEASE_NOTIFICATION_WEBHOOK }} \ 14 | -H 'Content-Type: application/json' \ 15 | -d '{ "GITHUB_RELEASE_URL": "${{ github.event.release.html_url }}", 16 | "GITHUB_RELEASE_TAG": "${{ github.event.release.tag_name }}"}' 17 | -------------------------------------------------------------------------------- /.github/workflows/trigger_ab_tests.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - main 5 | - firecracker-v* 6 | - feature/* 7 | 8 | jobs: 9 | trigger_ab_test: 10 | runs-on: ubuntu-latest 11 | if: ${{ github.event.forced == false }} 12 | steps: 13 | - name: "Check out repository" 14 | uses: actions/checkout@v4 15 | with: 16 | # Required to make it fetch more than the just fetched commits (we need it to resolve at least one commit 17 | # _before_ what was pushed so that below "git diff" works. 18 | fetch-depth: 0 19 | - name: "Trigger Buildkite Pipeline" 20 | run: | 21 | should_schedule_ab_test=0 22 | # Iterates over all files modified in the just-merged PR. If any of them is rust-related (e.g. .rs, .toml, 23 | # .lock or .cargo/config) or a seccomp definition (resources/seccomp/*), sets `should_schedule_ab_test` to 1, 24 | # meaning we will schedule a build of the A/B-testing pipeline to check the just-merged PR for 25 | # performance regressions. 26 | for f in $(git --no-pager diff --name-only ${{ github.event.before }}..${{ github.event.after }}); do 27 | if [[ "$(basename $f)" =~ (\.(rs|toml|lock)|config)$ ]] || [[ "$f" =~ ^resources/seccomp/ ]]; then 28 | should_schedule_ab_test=1 29 | fi 30 | done 31 | if [[ $should_schedule_ab_test -eq 1 ]]; then 32 | curl -X POST https://api.buildkite.com/v2/organizations/firecracker/pipelines/performance-a-b-tests/builds \ 33 | -H 'Content-Type: application/json' \ 34 | -H 'Authorization: Bearer ${{ secrets.BUILDKITE_TOKEN }}' \ 35 | -d "{ 36 | \"commit\": \"HEAD\", 37 | \"branch\": \"$GITHUB_REF_NAME\", 38 | \"env\": { 39 | \"REVISION_A\": \"${{ github.event.before }}\", 40 | \"REVISION_B\": \"${{ github.event.after }}\" 41 | } 42 | }" 43 | fi 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /build/ 2 | /.kernel/ 3 | target 4 | *.rs.bk 5 | *.iml 6 | .idea 7 | __pycache__ 8 | *.pyc 9 | .vscode 10 | test_results/* 11 | *.core 12 | *.profraw 13 | .DS_Store 14 | *.bin 15 | /resources/linux 16 | /resources/x86_64 17 | /resources/aarch64 18 | -------------------------------------------------------------------------------- /.gitlint: -------------------------------------------------------------------------------- 1 | [general] 2 | regex-style-search=True 3 | 4 | [title-max-length] 5 | line-length=72 6 | 7 | [body-max-line-length] 8 | line-length=72 9 | 10 | [ignore-body-lines] 11 | # Ignore HTTP reference links 12 | # Ignore lines that start with 'Co-Authored-By', with 'Signed-off-by' or with 'Fixes' 13 | regex=(^\[.+\]: http.+)|(^Co-Authored-By)|(^Signed-off-by)|(^Fixes:) 14 | 15 | [ignore-by-author-name] 16 | # Ignore certain rules for commits of which the author name matches a regex 17 | # E.g. Match commits made by dependabot 18 | regex=dependabot 19 | 20 | # Ignore certain rules, you can reference them by their id or by their full name 21 | # Use 'all' to ignore all rules. Dependabot constructs commit bodies from 22 | # changelogs, so disable all rules. 23 | ignore=all 24 | -------------------------------------------------------------------------------- /.mdformat.toml: -------------------------------------------------------------------------------- 1 | wrap = 80 2 | # Defaults from https://mdformat.readthedocs.io/en/stable/users/configuration_file.html 3 | number = false 4 | end_of_line = "lf" -------------------------------------------------------------------------------- /.python-version: -------------------------------------------------------------------------------- 1 | 3.10.14 2 | -------------------------------------------------------------------------------- /CHARTER.md: -------------------------------------------------------------------------------- 1 | # Firecracker Charter 2 | 3 | ## Mission 4 | 5 | Our mission is to enable secure, multi-tenant, minimal-overhead execution of 6 | container and function workloads. 7 | 8 | ## Tenets (unless you know better ones) 9 | 10 | These tenets guide Firecracker's development: 11 | 12 | 1. **Built-In Security**: We provide compute security barriers that enable 13 | multi-tenant workloads, and cannot be mistakenly disabled by customers. 14 | Customer workloads are simultaneously considered sacred (shall not be 15 | touched) and malicious (shall be defended against). We continuously invest in 16 | defense in depth and maintain mechanisms that ensure security best practices. 17 | 1. **Light-Weight Virtualization**: We prioritize measuring Firecracker's 18 | hardware overhead in the dimensions that are important for our customers, and 19 | we strive to make this overhead negligible. 20 | 1. **Minimalist in Features**: If it's not clearly required for our mission, we 21 | won't build it. We maintain a single implementation per capability, and 22 | deprecate obsolete implementations; resolving exceptions is a high priority 23 | issue. 24 | 1. **Compute Oversubscription**: All of the hardware compute resources exposed 25 | by Firecracker to guests can be securely oversubscribed. 26 | 27 | ## Contributions & Project Roles 28 | 29 | All contributions must align with this charter and follow Firecracker's 30 | [contribution process](CONTRIBUTING.md). 31 | 32 | Firecracker [maintainers](MAINTAINERS.md) merge contributions into the main 33 | branch and create Firecracker releases. Maintainers are also subject to the 34 | mission and tenets outlined above. Anyone may submit and review contributions. 35 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code of Conduct 2 | 3 | This project has adopted the 4 | [Amazon Open Source Code of Conduct](https://aws.github.io/code-of-conduct). For 5 | more information see the 6 | [Code of Conduct FAQ](https://aws.github.io/code-of-conduct-faq) or contact 7 | [opensource-codeofconduct@amazon.com](mailto:opensource-codeofconduct@amazon.com) 8 | with any additional questions or comments. 9 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = ["src/*"] 3 | # We exclude the jailer below so that it does not get build by default. This is because "cargo build" compiles 4 | # for the gnu target, and the jailer needs a statically compiled binary to work correctly. 5 | # See https://github.com/firecracker-microvm/firecracker/commit/3bf285c8f8a815149923c562dd7edaffcaf10c4e 6 | # and https://github.com/firecracker-microvm/firecracker/issues/2102 7 | default-members = [ 8 | "src/clippy-tracing", 9 | "src/cpu-template-helper", 10 | "src/firecracker", 11 | "src/rebase-snap", 12 | "src/seccompiler", 13 | "src/snapshot-editor", 14 | "src/acpi-tables", 15 | ] 16 | resolver = "2" 17 | 18 | [workspace.lints.rust] 19 | missing_debug_implementations = "warn" 20 | unexpected_cfgs = { level = "warn", check-cfg = ['cfg(kani)'] } 21 | 22 | [workspace.lints.clippy] 23 | ptr_as_ptr = "warn" 24 | undocumented_unsafe_blocks = "warn" 25 | cast_possible_truncation = "warn" 26 | cast_possible_wrap = "warn" 27 | cast_sign_loss = "warn" 28 | exit = "warn" 29 | tests_outside_test_module = "warn" 30 | assertions_on_result_states = "warn" 31 | error_impl_error = "warn" 32 | 33 | [profile.dev] 34 | panic = "abort" 35 | 36 | [profile.release] 37 | panic = "abort" 38 | lto = true 39 | strip = "none" 40 | 41 | [profile.bench] 42 | strip = "debuginfo" 43 | -------------------------------------------------------------------------------- /DEPRECATED.md: -------------------------------------------------------------------------------- 1 | # Deprecated Features 2 | 3 | The following functionality of Firecracker is deprecated, and will be removed in 4 | a future major Firecracker release, in accordance with our 5 | [release policy](docs/RELEASE_POLICY.md). 6 | 7 | - \[[#2763](https://github.com/firecracker-microvm/firecracker/pull/2763)\] The 8 | `vsock_id` body field in `PUT` requests on `/vsock` 9 | - \[[#2980](https://github.com/firecracker-microvm/firecracker/pull/2980)\] The 10 | `mem_file_path` body field in `PUT` requests on `/snapshot/load` 11 | - \[[#2973](https://github.com/firecracker-microvm/firecracker/pull/2973)\] 12 | MicroVM Metadata Service v1 (MMDSv1) 13 | - \[[#4126](https://github.com/firecracker-microvm/firecracker/pull/4126)\] 14 | Static CPU templates 15 | - \[[#4209](https://github.com/firecracker-microvm/firecracker/pull/4209)\] The 16 | `rebase-snap` tool 17 | - \[[#4500](https://github.com/firecracker-microvm/firecracker/pull/4500)\] The 18 | `--start-time-cpu-us` and `--start-time-us` CLI arguments 19 | - \[[#4428](https://github.com/firecracker-microvm/firecracker/pull/4428)\] 20 | Booting microVMs using MPTable and command line parameters for VirtIO devices. 21 | The functionality is substituted with ACPI. 22 | - \[[#2628](https://github.com/firecracker-microvm/firecracker/pull/2628)\] The 23 | `--basic` parameter of `seccompiler-bin`. 24 | -------------------------------------------------------------------------------- /MAINTAINERS.md: -------------------------------------------------------------------------------- 1 | # Maintainers 2 | 3 | Firecracker is maintained by a dedicated team within Amazon: 4 | 5 | - Babis Chalios 6 | - Egor Lazarchuk 7 | - Jack Thomson 8 | - Marco Cali 9 | - Nikita Kalyazin 10 | - Pablo Barbachano 11 | - Patrick Roy 12 | - Riccardo Mancini 13 | - Takahiro Itazuri 14 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Firecracker 2 | Copyright 2017-2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | SPDX-License-Identifier: Apache-2.0 4 | 5 | Portions Copyright 2017 The Chromium OS Authors. All rights reserved. 6 | Use of this source code is governed by a BSD-style license that can be 7 | found in the THIRD-PARTY file. 8 | 9 | The Firecracker release bundle includes libseccomp which is available 10 | under the LGPLv2.1 license. This is used in the Firecracker build process 11 | to produce cBPF bytecode that is shipped alongside Firecracker for use by 12 | the Linux kernel. 13 | -------------------------------------------------------------------------------- /PGP-KEY.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | 3 | mDMEXoNLVhYJKwYBBAHaRw8BAQdA/RBM+jgzq6EXzTc7zDmDgcSNENKJqZ7djI7G 4 | Iz1Os720TkZpcmVjcmFja2VyIFNlY3VyaXR5IERpc2Nsb3N1cmVzIDxmaXJlY3Jh 5 | Y2tlci1zZWN1cml0eS1kaXNjbG9zdXJlc0BhbWF6b24uY29tPoiZBBMWCABBAhsD 6 | BQkJZgGABQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAFiEEp07t53fN17pTgiajKCi5 7 | jaKQW+AFAl6DTtACGQEACgkQKCi5jaKQW+BnBwEA/+VBs/9t5aUBb20HZMSYL3tu 8 | Ffh+fI1FSOsMSjXfAe8A/2MlxfdDdYtAhxwwN1Y+hGrm/PdT1LULJqoz14r3xUUJ 9 | tCVCYXJidSwgSXVsaWFuIE1hcmlhbiA8aXVsQGFtYXpvbi5jb20+iHgEMBYIACAW 10 | IQSnTu3nd83XulOCJqMoKLmNopBb4AUCXoNO2QIdAAAKCRAoKLmNopBb4EHTAQDS 11 | ZzcN7MU7mtM79+ev9aoX0/OltBPq/QQy22qa3wbCwQD/cd1nXu3pKUKvyHtTpVFB 12 | Jd+YNpG2ox3e3SfVZyXeRgiIlgQTFggAPgIbAwUJCWYBgAULCQgHAgYVCgkICwIE 13 | FgIDAQIeAQIXgBYhBKdO7ed3zde6U4ImoygouY2ikFvgBQJeg07QAAoJECgouY2i 14 | kFvgKggBAIUpB5stOoo/NjSMwpTMwa/jiqephv/GarCrluYRbQ/aAQDTn7aCX4ab 15 | b/vqLjiePos5tuToBoRXkL8QzdGyeONpBrQsQ29tcHV0ZSBDYXBzdWxlIDxjb21w 16 | dXRlLWNhcHN1bGVAYW1hem9uLmNvbT6IlgQTFggAPhYhBKdO7ed3zde6U4Imoygo 17 | uY2ikFvgBQJeg09JAhsDBQkJZgGABQsJCAcCBhUKCQgLAgQWAgMBAh4BAheAAAoJ 18 | ECgouY2ikFvgyNcBAKSacUhi9Kb4C7Ybdzu4EKgQxfKnBucoubonF658K/GVAQDA 19 | d0sVeTVu3g/Z/7DHCBg8Jn+LSl3fCoEUeK4Z2fBeAbg4BF6DS1YSCisGAQQBl1UB 20 | BQEBB0B8rM1FwSBZzXAg2IxqJ8qUkwMVorbXlA+p/MNXQdeACAMBCAeIfgQYFggA 21 | JhYhBKdO7ed3zde6U4ImoygouY2ikFvgBQJeg0tWAhsMBQkJZgGAAAoJECgouY2i 22 | kFvgz8sA/jz0dUAwtTMtkdvjP4Dewrq1d8o7sgy1wV5Ax/a20DFyAQCJQIMf4MtF 23 | jrojJjAIHRUlukf4VVEtGS7IroK56JS3Bw== 24 | =1xBx 25 | -----END PGP PUBLIC KEY BLOCK----- 26 | 27 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | ## Reporting Security Issues 2 | 3 | We take all security reports seriously. When we receive such reports, we will 4 | investigate and subsequently address any potential vulnerabilities as quickly as 5 | possible. If you discover a potential security issue in this project, please 6 | notify AWS/Amazon Security via our 7 | [vulnerability reporting page](http://aws.amazon.com/security/vulnerability-reporting/) 8 | or directly via email to [AWS Security](mailto:aws-security@amazon.com). Please 9 | do *not* create a public GitHub issue in this project. 10 | -------------------------------------------------------------------------------- /THIRD-PARTY: -------------------------------------------------------------------------------- 1 | // Copyright 2017 The Chromium OS Authors. All rights reserved. 2 | // 3 | // Redistribution and use in source and binary forms, with or without 4 | // modification, are permitted provided that the following conditions are 5 | // met: 6 | // 7 | // * Redistributions of source code must retain the above copyright 8 | // notice, this list of conditions and the following disclaimer. 9 | // * Redistributions in binary form must reproduce the above 10 | // copyright notice, this list of conditions and the following disclaimer 11 | // in the documentation and/or other materials provided with the 12 | // distribution. 13 | // * Neither the name of Google Inc. nor the names of its 14 | // contributors may be used to endorse or promote products derived from 15 | // this software without specific prior written permission. 16 | // 17 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 18 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 20 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 21 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 22 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 23 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 24 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 27 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | -------------------------------------------------------------------------------- /deny.toml: -------------------------------------------------------------------------------- 1 | [licenses] 2 | version = 2 3 | allow = [ 4 | "MIT", 5 | "Apache-2.0", 6 | "BSD-3-Clause", 7 | "ISC", 8 | "Unicode-3.0", 9 | "OpenSSL" 10 | ] 11 | 12 | [[bans.deny]] 13 | name = "serde_derive" 14 | version = ">1.0.171, < 1.0.184" 15 | -------------------------------------------------------------------------------- /docs/cpu_templates/boot-protocol.md: -------------------------------------------------------------------------------- 1 | # Boot protocol register settings 2 | 3 | Firecracker makes certain modifications to the guest's registers regardless of 4 | whether a CPU template is used to comply with the boot protocol. If a CPU 5 | template is used the boot protocol settings are performed _after_ the CPU 6 | template is applied. That means that if the CPU template configures CPUID bits 7 | used in the boot protocol settings, they will be overwritten. 8 | 9 | See also: [CPUID normalization](cpuid-normalization.md) 10 | 11 | ## Boot protocol MSRs (x86_64 only) 12 | 13 | On x86_64, the following MSRs are set to `0`: 14 | 15 | - MSR_IA32_SYSENTER_CS 16 | - MSR_IA32_SYSENTER_ESP 17 | - MSR_IA32_SYSENTER_EIP 18 | - MSR_STAR 19 | - MSR_CSTAR 20 | - MSR_KERNEL_GS_BASE 21 | - MSR_SYSCALL_MASK 22 | - MSR_LSTAR 23 | - MSR_IA32_TSC 24 | 25 | and MSR_IA32_MISC_ENABLE is set to `1`. 26 | 27 | ## Boot protocol ARM registers (aarch64 only) 28 | 29 | On aarch64, the following registers are set: 30 | 31 | - PSTATE to PSR_MODE_EL1h | PSR_A_BIT | PSR_F_BIT | PSR_I_BIT | PSR_D_BIT 32 | - PC to kernel load address (vCPU0 only) 33 | - X0 to DTB/FDT address (vCPU0 only) 34 | -------------------------------------------------------------------------------- /docs/images/api_change_flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/api_change_flowchart.png -------------------------------------------------------------------------------- /docs/images/fc_decal_icon-dark_dark-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/fc_decal_icon-dark_dark-bg.png -------------------------------------------------------------------------------- /docs/images/fc_logo_full_transparent-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/fc_logo_full_transparent-bg.png -------------------------------------------------------------------------------- /docs/images/fc_logo_full_transparent-bg_white-fg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/fc_logo_full_transparent-bg_white-fg.png -------------------------------------------------------------------------------- /docs/images/fc_logo_full_white-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/fc_logo_full_white-bg.png -------------------------------------------------------------------------------- /docs/images/fc_logo_full_white-bg_tiny.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/fc_logo_full_white-bg_tiny.png -------------------------------------------------------------------------------- /docs/images/fc_logo_icon_transparent-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/fc_logo_icon_transparent-bg.png -------------------------------------------------------------------------------- /docs/images/fc_logo_icon_transparent-bg_square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/fc_logo_icon_transparent-bg_square.png -------------------------------------------------------------------------------- /docs/images/fc_logo_icon_white-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/fc_logo_icon_white-bg.png -------------------------------------------------------------------------------- /docs/images/fc_logo_icon_white-bg_square.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/fc_logo_icon_white-bg_square.png -------------------------------------------------------------------------------- /docs/images/fc_sticker_full_white-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/fc_sticker_full_white-bg.png -------------------------------------------------------------------------------- /docs/images/fc_sticker_icon_white-bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/fc_sticker_icon_white-bg.png -------------------------------------------------------------------------------- /docs/images/firecracker_host_integration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/firecracker_host_integration.png -------------------------------------------------------------------------------- /docs/images/firecracker_threat_containment.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/firecracker_threat_containment.png -------------------------------------------------------------------------------- /docs/images/uffd_flow1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/uffd_flow1.png -------------------------------------------------------------------------------- /docs/images/uffd_flow2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/uffd_flow2.png -------------------------------------------------------------------------------- /docs/images/uffd_flow3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/uffd_flow3.png -------------------------------------------------------------------------------- /docs/images/uffd_flow4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/uffd_flow4.png -------------------------------------------------------------------------------- /docs/images/vsock-connections.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/docs/images/vsock-connections.png -------------------------------------------------------------------------------- /docs/initrd.md: -------------------------------------------------------------------------------- 1 | # Creating and using an initrd for Firecracker 2 | 3 | ## Creating 4 | 5 | ### Based on alpine or suse 6 | 7 | You can use the script found 8 | [here](https://github.com/marcov/firecracker-initrd) to generate an initrd 9 | either based on alpine or suse linux. 10 | 11 | The script extracts the init system from each distribution and creates a initrd. 12 | 13 | ### Custom 14 | 15 | Use this option for creating an initrd if you're building your own init or if 16 | you need any specific files / logic in your initrd. 17 | 18 | ```bash 19 | mkdir initrd 20 | cp /path/to/your/init initrd/init 21 | # copy everything else you need in initrd/ 22 | cd initrd 23 | find . -print0 | cpio --null --create --verbose --format=newc > initrd.cpio 24 | ``` 25 | 26 | ## Usage 27 | 28 | When setting your boot source, add a `initrd_path` property like so: 29 | 30 | ```shell 31 | curl --unix-socket /tmp/firecracker.socket -i \ 32 | -X PUT 'http://localhost/boot-source' \ 33 | -H 'Accept: application/json' \ 34 | -H 'Content-Type: application/json' \ 35 | -d "{ 36 | \"kernel_image_path\": \"/path/to/kernel\", 37 | \"boot_args\": \"console=ttyS0 reboot=k panic=1 pci=off\", 38 | \"initrd_path\": \"/path/to/initrd.cpio\" 39 | }" 40 | ``` 41 | 42 | ### Notes 43 | 44 | - You should not use a drive with `is_root_device: true` when using an initrd 45 | - Make sure your kernel configuration has `CONFIG_BLK_DEV_INITRD=y` 46 | - If you don't want to place your init at the root of your initrd, you can add 47 | `rdinit=/path/to/init` to your `boot_args` property 48 | - If you intend to `pivot_root` in your init, it won't be possible because the 49 | initrd is mounted as a rootfs and cannot be unmounted. You will need to use 50 | `switch_root` instead. 51 | -------------------------------------------------------------------------------- /docs/pvh.md: -------------------------------------------------------------------------------- 1 | # PVH boot mode 2 | 3 | Firecracker supports booting x86 kernels in "PVH direct boot" mode 4 | [as specified by the Xen project](https://github.com/xen-project/xen/blob/master/docs/misc/pvh.pandoc). 5 | If a kernel is provided which contains the XEN_ELFNOTE_PHYS32_ENTRY ELF Note 6 | then this boot mode will be used. This boot mode was designed for virtualized 7 | environments which load the kernel directly, and is simpler than the "Linux 8 | boot" mode which is designed to be launched from a legacy boot loader. 9 | 10 | PVH boot mode can be enabled for Linux by setting `CONFIG_PVH=y` in the kernel 11 | configuration. (This is not the default setting.) 12 | 13 | PVH boot mode is enabled by default in FreeBSD, which has support for 14 | Firecracker starting with FreeBSD 14.0. Instructions on building a FreeBSD 15 | kernel and root filesystem are available [here](rootfs-and-kernel-setup.md). 16 | -------------------------------------------------------------------------------- /resources/guest_configs/DISCLAIMER.md: -------------------------------------------------------------------------------- 1 | ### DISCLAIMER 2 | 3 | Please keep this document in mind when using these guest kernel configuration 4 | files. 5 | 6 | Firecracker as a virtual machine monitor is designed and built for use with 7 | specific goals, so these kernel configurations are tuned to be secure and to use 8 | the host's resources as optimally as possible, specifically allowing for as many 9 | guests to be running concurrently as possible (high density). 10 | 11 | For example, one of the mechanisms to improve density is to reduce virtual 12 | memory areas of the guest. This decreases the page table size and improves 13 | available memory on the host for other guests to occupy. As Firecracker is 14 | intended for ephemeral compute (short-lived environments, not intended to run 15 | indefinitely), a Firecracker guest is not expected to require large memory 16 | sizes. 17 | 18 | One interesting use-case where this can be seen to cause odd side affects is one 19 | where golang's race detector for aarch64 expected a 48-bit space, but the 20 | guest's kernel config enforced 39-bit. See 21 | [Firecracker issue #3514](https://github.com/firecracker-microvm/firecracker/issues/3514). 22 | -------------------------------------------------------------------------------- /resources/guest_configs/ci.config: -------------------------------------------------------------------------------- 1 | CONFIG_IKCONFIG=y 2 | CONFIG_IKCONFIG_PROC=y 3 | CONFIG_MSDOS_PARTITION=y 4 | CONFIG_SQUASHFS_ZSTD=y 5 | # aarch64 only TBD split into a separate file 6 | CONFIG_DEVMEM=y 7 | # CONFIG_ARM64_ERRATUM_3194386 is not set 8 | # Needed for CTRL+ALT+DEL support 9 | CONFIG_SERIO=y 10 | CONFIG_SERIO_I8042=y 11 | CONFIG_SERIO_LIBPS2=y 12 | CONFIG_SERIO_GSCPS2=y 13 | CONFIG_KEYBOARD_ATKBD=y 14 | CONFIG_INPUT_KEYBOARD=y -------------------------------------------------------------------------------- /resources/guest_configs/debug.config: -------------------------------------------------------------------------------- 1 | CONFIG_FRAME_POINTER=y 2 | # CONFIG_KGDB=y 3 | # CONFIG_KGDB_SERIAL_CONSOLE=y 4 | CONFIG_DEBUG_INFO=y 5 | CONFIG_DEBUG_INFO_DWARF4=y 6 | -------------------------------------------------------------------------------- /resources/guest_configs/ftrace.config: -------------------------------------------------------------------------------- 1 | CONFIG_FTRACE=y 2 | CONFIG_FUNCTION_TRACER=y 3 | CONFIG_FUNCTION_GRAPH_TRACER=y 4 | CONFIG_IRQSOFF_TRACER=y 5 | CONFIG_PREEMPT_TRACER=y 6 | CONFIG_SCHED_TRACER=y 7 | CONFIG_STACK_TRACER=y 8 | CONFIG_BLK_DEV_IO_TRACE=y 9 | CONFIG_FUNCTION_PROFILER=y 10 | CONFIG_FTRACE_MCOUNT_RECORD=y 11 | CONFIG_FTRACE_SYSCALLS=y 12 | -------------------------------------------------------------------------------- /resources/overlay/etc/systemd/system/fcnet.service: -------------------------------------------------------------------------------- 1 | [Service] 2 | Type=oneshot 3 | ExecStart=/usr/local/bin/fcnet-setup.sh 4 | [Install] 5 | WantedBy=sshd.service 6 | -------------------------------------------------------------------------------- /resources/overlay/etc/systemd/system/var-lib-systemd.mount: -------------------------------------------------------------------------------- 1 | # 2 | # Mount /var/lib/systemd as a temporary filesystem 3 | # 4 | 5 | [Unit] 6 | DefaultDependencies=no 7 | Conflicts=umount.target 8 | Before=local-fs.target umount.target 9 | After=swap.target 10 | 11 | [Mount] 12 | What=tmpfs 13 | Where=/var/lib/systemd 14 | Type=tmpfs 15 | Options=mode=1777,strictatime,nosuid,nodev,size=50%%,nr_inodes=10k 16 | 17 | [Install] 18 | WantedBy=local-fs.target 19 | -------------------------------------------------------------------------------- /resources/overlay/usr/local/bin/devmemread.c: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /* 11 | * We try to trigger ENOSYS by mapping a file into memory and then tries to 12 | * load the content from an offset in the file bigger than its length into a 13 | * register asm volatile ("ldr %0, [%1], 4" : "=r" (ret), "+r" (buf)); 14 | */ 15 | 16 | int main() 17 | { 18 | int ret, fd; 19 | char *buf; 20 | 21 | // Assume /dev is mounted 22 | fprintf(stderr, "open /dev/mem\n"); 23 | fd = open("/dev/mem", O_RDWR); 24 | assert(fd > 0); 25 | 26 | buf = mmap(NULL, 65536, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0xf0000); 27 | assert(buf != MAP_FAILED); 28 | 29 | fprintf(stderr, "try to ldr\n"); 30 | asm volatile("ldr %0, [%1], 4" : "=r" (ret), "+r" (buf)); 31 | 32 | fprintf(stderr, "success\n"); 33 | return 0; 34 | } 35 | -------------------------------------------------------------------------------- /resources/overlay/usr/local/bin/fcnet-setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # SPDX-License-Identifier: Apache-2.0 5 | 6 | # This script assigns IP addresses to the existing 7 | # virtual networking devices based on their MAC address. 8 | # It is a simple solution on which Firecracker's integration 9 | # tests are based. Each network device attached in a test will 10 | # assign the next available MAC. 11 | # The IP is obtained by converting the last 4 hexa groups of the MAC into decimals. 12 | 13 | main() { 14 | devs=$(ls /sys/class/net | grep -v lo) 15 | for dev in $devs; do 16 | mac_ip=$(ip link show dev $dev \ 17 | | grep link/ether \ 18 | | grep -Po "(?<=06:00:)([0-9a-f]{2}:?){4}" 19 | ) 20 | ip=$(printf "%d.%d.%d.%d" $(echo "0x${mac_ip}" | sed "s/:/ 0x/g")) 21 | ip addr add "$ip/30" dev $dev 22 | ip link set $dev up 23 | done 24 | } 25 | main 26 | -------------------------------------------------------------------------------- /resources/overlay/usr/local/bin/init.c: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // Init wrapper for boot timing. It points at /sbin/init. 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | // Base address values are defined in arch/src/lib.rs as arch::MMIO_MEM_START. 12 | // Values are computed in arch/src//mod.rs from the architecture layouts. 13 | // Position on the bus is defined by MMIO_LEN increments, where MMIO_LEN is 14 | // defined as 0x1000 in vmm/src/device_manager/mmio.rs. 15 | #ifdef __x86_64__ 16 | #define MAGIC_MMIO_SIGNAL_GUEST_BOOT_COMPLETE 0xd0000000 17 | #endif 18 | #ifdef __aarch64__ 19 | #define MAGIC_MMIO_SIGNAL_GUEST_BOOT_COMPLETE 0x40000000 20 | #endif 21 | 22 | #define MAGIC_VALUE_SIGNAL_GUEST_BOOT_COMPLETE 123 23 | 24 | int main () { 25 | int fd = open("/dev/mem", (O_RDWR | O_SYNC | O_CLOEXEC)); 26 | int mapped_size = getpagesize(); 27 | 28 | char *map_base = mmap(NULL, 29 | mapped_size, 30 | PROT_WRITE, 31 | MAP_SHARED, 32 | fd, 33 | MAGIC_MMIO_SIGNAL_GUEST_BOOT_COMPLETE); 34 | 35 | *map_base = MAGIC_VALUE_SIGNAL_GUEST_BOOT_COMPLETE; 36 | msync(map_base, mapped_size, MS_ASYNC); 37 | 38 | const char *init = "/sbin/init"; 39 | 40 | char *const argv[] = { "/sbin/init", NULL }; 41 | char *const envp[] = { NULL }; 42 | 43 | execve(init, argv, envp); 44 | } 45 | -------------------------------------------------------------------------------- /resources/seccomp/unimplemented.json: -------------------------------------------------------------------------------- 1 | { 2 | "vmm": { 3 | "default_action": "allow", 4 | "filter_action": "trap", 5 | "filter": [] 6 | }, 7 | "api": { 8 | "default_action": "allow", 9 | "filter_action": "trap", 10 | "filter": [] 11 | }, 12 | "vcpu": { 13 | "default_action": "allow", 14 | "filter_action": "trap", 15 | "filter": [] 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | # We keep a rust-toolchain file checked into the repository such that in the 5 | # rare event that we need to do an A/B-test across toolchains, cargo will 6 | # download the toolchains of the A and B revisions on the fly (if they do not 7 | # match the toolchain installed in the environment in which the test is 8 | # executed). This is needed for example if a toolchain upgrade introduces a new 9 | # syscall into our seccomp filters. Then, since our PR CI contains A/B-tests, 10 | # we will compile a version of Firecracker that does not have this syscall 11 | # allowlisted using a toolchain that requires it, causing the A/B-test to 12 | # always fail. 13 | [toolchain] 14 | channel = "1.85.0" 15 | targets = ["x86_64-unknown-linux-musl", "aarch64-unknown-linux-musl"] 16 | profile = "minimal" 17 | 18 | -------------------------------------------------------------------------------- /src/acpi-tables/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "acpi_tables" 3 | version = "0.1.0" 4 | authors = [ 5 | "The Cloud Hypervisor Authors", 6 | "Amazon Firecracker team ", 7 | ] 8 | edition = "2024" 9 | license = "Apache-2.0" 10 | 11 | [lib] 12 | bench = false 13 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 14 | 15 | [dependencies] 16 | displaydoc = "0.2.5" 17 | thiserror = "2.0.12" 18 | vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-bitmap"] } 19 | zerocopy = { version = "0.8.25", features = ["derive"] } 20 | 21 | [lints] 22 | workspace = true 23 | -------------------------------------------------------------------------------- /src/clippy-tracing/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "clippy-tracing" 3 | version = "0.1.0" 4 | authors = ["Amazon Firecracker team "] 5 | edition = "2024" 6 | license = "Apache-2.0" 7 | 8 | [[bin]] 9 | name = "clippy-tracing" 10 | bench = false 11 | 12 | [dependencies] 13 | clap = { version = "4.5.38", features = ["derive"] } 14 | itertools = "0.14.0" 15 | proc-macro2 = { version = "1.0.95", features = ["span-locations"] } 16 | quote = "1.0.40" 17 | syn = { version = "2.0.101", features = ["full", "extra-traits", "visit", "visit-mut", "printing"] } 18 | walkdir = "2.5.0" 19 | 20 | [dev-dependencies] 21 | uuid = { version = "1.17.0", features = ["v4"] } 22 | 23 | [lints] 24 | workspace = true 25 | -------------------------------------------------------------------------------- /src/clippy-tracing/README.md: -------------------------------------------------------------------------------- 1 | # clippy-tracing 2 | 3 | A tool to add, remove and check for `log_instrument::instrument` in large 4 | projects where it is infeasible to manually add it to thousands of functions. 5 | 6 | ## Usage 7 | 8 | This is tested in the 9 | [`readme()` integration test](../clippy-tracing/tests/integration_tests.rs) . 10 | 11 | ```rust 12 | fn main() { 13 | println!("Hello World!"); 14 | } 15 | fn add(lhs: i32, rhs: i32) -> i32 { 16 | lhs + rhs 17 | } 18 | #[cfg(tests)] 19 | mod tests { 20 | fn sub(lhs: i32, rhs: i32) -> i32 { 21 | lhs - rhs 22 | } 23 | #[test] 24 | fn test_one() { 25 | assert_eq!(add(1,1), sub(2, 1)); 26 | } 27 | } 28 | ``` 29 | 30 | ```bash 31 | clippy-tracing --action check # Missing instrumentation at {path}:9:4.\n 32 | echo $? # 2 33 | clippy-tracing --action fix 34 | echo $? # 0 35 | ``` 36 | 37 | ```rust 38 | #[log_instrument::instrument(level = "trace", skip())] 39 | fn main() { 40 | println!("Hello World!"); 41 | } 42 | #[log_instrument::instrument(level = "trace", skip(lhs, rhs))] 43 | fn add(lhs: i32, rhs: i32) -> i32 { 44 | lhs + rhs 45 | } 46 | #[cfg(tests)] 47 | mod tests { 48 | #[log_instrument::instrument(level = "trace", skip(lhs, rhs))] 49 | fn sub(lhs: i32, rhs: i32) -> i32 { 50 | lhs - rhs 51 | } 52 | #[test] 53 | fn test_one() { 54 | assert_eq!(add(1,1), sub(2, 1)); 55 | } 56 | } 57 | ``` 58 | 59 | ```bash 60 | clippy-tracing --action check 61 | echo $? # 0 62 | clippy-tracing --action strip 63 | echo $? # 0 64 | ``` 65 | 66 | ```rust 67 | fn main() { 68 | println!("Hello World!"); 69 | } 70 | fn add(lhs: i32, rhs: i32) -> i32 { 71 | lhs + rhs 72 | } 73 | #[cfg(tests)] 74 | mod tests { 75 | fn sub(lhs: i32, rhs: i32) -> i32 { 76 | lhs - rhs 77 | } 78 | #[test] 79 | fn test_one() { 80 | assert_eq!(add(1,1), sub(2, 1)); 81 | } 82 | } 83 | ``` 84 | -------------------------------------------------------------------------------- /src/cpu-template-helper/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "cpu-template-helper" 3 | version = "1.13.0-dev" 4 | authors = ["Amazon Firecracker team "] 5 | edition = "2024" 6 | license = "Apache-2.0" 7 | 8 | [[bin]] 9 | name = "cpu-template-helper" 10 | bench = false 11 | 12 | [features] 13 | tracing = ["log-instrument", "vmm/tracing"] 14 | 15 | [dependencies] 16 | clap = { version = "4.5.38", features = ["derive", "string"] } 17 | displaydoc = "0.2.5" 18 | libc = "0.2.172" 19 | log-instrument = { path = "../log-instrument", optional = true } 20 | serde = { version = "1.0.219", features = ["derive"] } 21 | serde_json = "1.0.140" 22 | thiserror = "2.0.12" 23 | 24 | vmm = { path = "../vmm" } 25 | vmm-sys-util = "0.12.1" 26 | 27 | [lints] 28 | workspace = true 29 | -------------------------------------------------------------------------------- /src/cpu-template-helper/src/fingerprint/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use serde::{Deserialize, Serialize}; 5 | use vmm::cpu_config::templates::CustomCpuTemplate; 6 | 7 | pub mod compare; 8 | pub mod dump; 9 | 10 | macro_rules! declare_fingerprint_struct_and_enum { 11 | ($($field_name:ident : $field_type:ty),+) => { 12 | #[derive(Debug, Serialize, Deserialize)] 13 | pub struct Fingerprint { 14 | $(pub $field_name: $field_type),+ 15 | } 16 | 17 | #[allow(non_camel_case_types)] 18 | #[derive(clap::ValueEnum, Clone, Debug)] 19 | #[value(rename_all = "snake_case")] 20 | pub enum FingerprintField { 21 | $($field_name),+ 22 | } 23 | }; 24 | } 25 | 26 | // This macro is expanded as follows: 27 | // ```rs 28 | // #[derive(Serialize, Deserialize)] 29 | // pub struct Fingerprint { 30 | // pub firecracker_version: String, 31 | // pub kernel_version: String, 32 | // pub microcode_version: String, 33 | // pub bios_version: String, 34 | // pub bios_revision: String, 35 | // pub guest_cpu_config: CustomCpuTemplate, 36 | // } 37 | // 38 | // #[allow(non_camel_case_types)] 39 | // #[derive(clap::ValueEnum, Clone, Debug)] 40 | // #[value(rename_all = "snake_case")] 41 | // pub enum FingerprintField { 42 | // firecracker_version, 43 | // kernel_version, 44 | // microcode_version, 45 | // bios_version, 46 | // bios_revision, 47 | // guest_cpu_config, 48 | // } 49 | // ``` 50 | declare_fingerprint_struct_and_enum!( 51 | firecracker_version: String, 52 | kernel_version: String, 53 | microcode_version: String, 54 | bios_version: String, 55 | bios_revision: String, 56 | guest_cpu_config: CustomCpuTemplate 57 | ); 58 | -------------------------------------------------------------------------------- /src/cpu-template-helper/src/template/dump/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #[cfg(target_arch = "aarch64")] 5 | mod aarch64; 6 | #[cfg(target_arch = "x86_64")] 7 | mod x86_64; 8 | 9 | use std::sync::{Arc, Mutex}; 10 | 11 | use vmm::cpu_config::templates::CustomCpuTemplate; 12 | use vmm::{DumpCpuConfigError, Vmm}; 13 | 14 | #[cfg(target_arch = "aarch64")] 15 | use crate::template::dump::aarch64::config_to_template; 16 | #[cfg(target_arch = "x86_64")] 17 | use crate::template::dump::x86_64::config_to_template; 18 | 19 | #[derive(Debug, thiserror::Error, displaydoc::Display)] 20 | pub enum DumpError { 21 | /// Failed to dump CPU config: {0} 22 | DumpCpuConfig(#[from] DumpCpuConfigError), 23 | } 24 | 25 | pub fn dump(vmm: Arc>) -> Result { 26 | // Get CPU configuration. 27 | let cpu_configs = vmm.lock().unwrap().dump_cpu_config()?; 28 | 29 | // Convert CPU config to CPU template. 30 | Ok(config_to_template(&cpu_configs[0])) 31 | } 32 | 33 | #[cfg(test)] 34 | mod tests { 35 | use super::*; 36 | use crate::utils::build_microvm_from_config; 37 | 38 | #[test] 39 | fn test_dump() { 40 | let (vmm, _) = build_microvm_from_config(None, None).unwrap(); 41 | dump(vmm).unwrap(); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/cpu-template-helper/src/template/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod dump; 5 | pub mod strip; 6 | pub mod verify; 7 | -------------------------------------------------------------------------------- /src/cpu-template-helper/src/utils/mock_kernel/main.c: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | void _start() { 5 | while (1) ; 6 | } 7 | -------------------------------------------------------------------------------- /src/firecracker/examples/README.md: -------------------------------------------------------------------------------- 1 | ## Test Utilities 2 | 3 | The `examples` directory contains various small rust utilities that are used in 4 | firecracker's integration test suite. 5 | -------------------------------------------------------------------------------- /src/firecracker/examples/seccomp/harmless.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | fn main() { 4 | unsafe { 5 | // Harmless print to standard output. 6 | libc::syscall(libc::SYS_write, libc::STDOUT_FILENO, "Hello, world!\n", 14); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/firecracker/examples/seccomp/jailer.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | use std::env::args; 4 | use std::fs::File; 5 | use std::os::unix::process::CommandExt; 6 | use std::process::{Command, Stdio}; 7 | 8 | use vmm::seccomp::{apply_filter, deserialize_binary}; 9 | 10 | fn main() { 11 | let args: Vec = args().collect(); 12 | let exec_file = &args[1]; 13 | let bpf_path = &args[2]; 14 | 15 | let filter_file = File::open(bpf_path).unwrap(); 16 | let map = deserialize_binary(&filter_file).unwrap(); 17 | 18 | // Loads filters. 19 | apply_filter(map.get("main").unwrap()).unwrap(); 20 | 21 | let _ = Command::new(exec_file) 22 | .stdin(Stdio::inherit()) 23 | .stdout(Stdio::inherit()) 24 | .stderr(Stdio::inherit()) 25 | .exec(); 26 | } 27 | -------------------------------------------------------------------------------- /src/firecracker/examples/seccomp/malicious.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | fn main() { 4 | unsafe { 5 | // In this example, the malicious component is outputting to standard input. 6 | libc::syscall(libc::SYS_write, libc::STDIN_FILENO, "Hello, world!\n", 14); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/firecracker/examples/seccomp/panic.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | use std::env::args; 4 | use std::fs::File; 5 | 6 | use vmm::seccomp::{apply_filter, deserialize_binary}; 7 | 8 | fn main() { 9 | let args: Vec = args().collect(); 10 | let bpf_path = &args[1]; 11 | let filter_thread = &args[2]; 12 | 13 | let filter_file = File::open(bpf_path).unwrap(); 14 | let map = deserialize_binary(&filter_file).unwrap(); 15 | apply_filter(map.get(filter_thread).unwrap()).unwrap(); 16 | panic!("Expected panic."); 17 | } 18 | -------------------------------------------------------------------------------- /src/firecracker/examples/uffd/fault_all_handler.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! Provides functionality for a userspace page fault handler 5 | //! which loads the whole region from the backing memory file 6 | //! when a page fault occurs. 7 | 8 | mod uffd_utils; 9 | 10 | use std::fs::File; 11 | use std::os::unix::net::UnixListener; 12 | 13 | use uffd_utils::{Runtime, UffdHandler}; 14 | use utils::time::{ClockType, get_time_us}; 15 | 16 | fn main() { 17 | let mut args = std::env::args(); 18 | let uffd_sock_path = args.nth(1).expect("No socket path given"); 19 | let mem_file_path = args.next().expect("No memory file given"); 20 | 21 | let file = File::open(mem_file_path).expect("Cannot open memfile"); 22 | 23 | // Get Uffd from UDS. We'll use the uffd to handle PFs for Firecracker. 24 | let listener = UnixListener::bind(uffd_sock_path).expect("Cannot bind to socket path"); 25 | let (stream, _) = listener.accept().expect("Cannot listen on UDS socket"); 26 | 27 | let mut runtime = Runtime::new(stream, file); 28 | runtime.install_panic_hook(); 29 | runtime.run(|uffd_handler: &mut UffdHandler| { 30 | // Read an event from the userfaultfd. 31 | let event = uffd_handler 32 | .read_event() 33 | .expect("Failed to read uffd_msg") 34 | .expect("uffd_msg not ready"); 35 | 36 | match event { 37 | userfaultfd::Event::Pagefault { .. } => { 38 | let start = get_time_us(ClockType::Monotonic); 39 | for region in uffd_handler.mem_regions.clone() { 40 | uffd_handler.serve_pf(region.base_host_virt_addr as _, region.size); 41 | } 42 | let end = get_time_us(ClockType::Monotonic); 43 | 44 | println!("Finished Faulting All: {}us", end - start); 45 | } 46 | _ => panic!("Unexpected event on userfaultfd"), 47 | } 48 | }); 49 | } 50 | -------------------------------------------------------------------------------- /src/firecracker/examples/uffd/malicious_handler.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! Provides functionality for a malicious page fault handler 5 | //! which panics when a page fault occurs. 6 | 7 | mod uffd_utils; 8 | 9 | use std::fs::File; 10 | use std::os::unix::net::UnixListener; 11 | 12 | use uffd_utils::{Runtime, UffdHandler}; 13 | 14 | fn main() { 15 | let mut args = std::env::args(); 16 | let uffd_sock_path = args.nth(1).expect("No socket path given"); 17 | let mem_file_path = args.next().expect("No memory file given"); 18 | 19 | let file = File::open(mem_file_path).expect("Cannot open memfile"); 20 | 21 | // Get Uffd from UDS. We'll use the uffd to handle PFs for Firecracker. 22 | let listener = UnixListener::bind(uffd_sock_path).expect("Cannot bind to socket path"); 23 | let (stream, _) = listener.accept().expect("Cannot listen on UDS socket"); 24 | 25 | let mut runtime = Runtime::new(stream, file); 26 | runtime.run(|uffd_handler: &mut UffdHandler| { 27 | // Read an event from the userfaultfd. 28 | let event = uffd_handler 29 | .read_event() 30 | .expect("Failed to read uffd_msg") 31 | .expect("uffd_msg not ready"); 32 | 33 | if let userfaultfd::Event::Pagefault { .. } = event { 34 | panic!("Fear me! I am the malicious page fault handler.") 35 | } 36 | }); 37 | } 38 | -------------------------------------------------------------------------------- /src/firecracker/src/api_server/request/boot_source.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use vmm::logger::{IncMetric, METRICS}; 5 | use vmm::rpc_interface::VmmAction; 6 | use vmm::vmm_config::boot_source::BootSourceConfig; 7 | 8 | use super::super::parsed_request::{ParsedRequest, RequestError}; 9 | use super::Body; 10 | 11 | pub(crate) fn parse_put_boot_source(body: &Body) -> Result { 12 | METRICS.put_api_requests.boot_source_count.inc(); 13 | Ok(ParsedRequest::new_sync(VmmAction::ConfigureBootSource( 14 | serde_json::from_slice::(body.raw()).inspect_err(|_| { 15 | METRICS.put_api_requests.boot_source_fails.inc(); 16 | })?, 17 | ))) 18 | } 19 | 20 | #[cfg(test)] 21 | mod tests { 22 | use super::*; 23 | 24 | #[test] 25 | fn test_parse_boot_request() { 26 | parse_put_boot_source(&Body::new("invalid_payload")).unwrap_err(); 27 | 28 | let body = r#"{ 29 | "kernel_image_path": "/foo/bar", 30 | "initrd_path": "/bar/foo", 31 | "boot_args": "foobar" 32 | }"#; 33 | let same_body = BootSourceConfig { 34 | kernel_image_path: String::from("/foo/bar"), 35 | initrd_path: Some(String::from("/bar/foo")), 36 | boot_args: Some(String::from("foobar")), 37 | }; 38 | let parsed_req = parse_put_boot_source(&Body::new(body)).unwrap(); 39 | 40 | assert_eq!( 41 | parsed_req, 42 | ParsedRequest::new_sync(VmmAction::ConfigureBootSource(same_body)) 43 | ); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/firecracker/src/api_server/request/entropy.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use vmm::rpc_interface::VmmAction; 5 | use vmm::vmm_config::entropy::EntropyDeviceConfig; 6 | 7 | use super::super::parsed_request::{ParsedRequest, RequestError}; 8 | use super::Body; 9 | 10 | pub(crate) fn parse_put_entropy(body: &Body) -> Result { 11 | let cfg = serde_json::from_slice::(body.raw())?; 12 | Ok(ParsedRequest::new_sync(VmmAction::SetEntropyDevice(cfg))) 13 | } 14 | 15 | #[cfg(test)] 16 | mod tests { 17 | use super::*; 18 | 19 | #[test] 20 | fn test_parse_put_entropy_request() { 21 | parse_put_entropy(&Body::new("invalid_payload")).unwrap_err(); 22 | 23 | // PUT with invalid fields. 24 | let body = r#"{ 25 | "some_id": 4 26 | }"#; 27 | parse_put_entropy(&Body::new(body)).unwrap_err(); 28 | 29 | // PUT with valid fields. 30 | let body = r#"{}"#; 31 | parse_put_entropy(&Body::new(body)).unwrap(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /src/firecracker/src/api_server/request/instance_info.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use vmm::logger::{IncMetric, METRICS}; 5 | use vmm::rpc_interface::VmmAction; 6 | 7 | use super::super::parsed_request::{ParsedRequest, RequestError}; 8 | 9 | pub(crate) fn parse_get_instance_info() -> Result { 10 | METRICS.get_api_requests.instance_info_count.inc(); 11 | Ok(ParsedRequest::new_sync(VmmAction::GetVmInstanceInfo)) 12 | } 13 | 14 | #[cfg(test)] 15 | mod tests { 16 | use super::*; 17 | use crate::api_server::parsed_request::RequestAction; 18 | 19 | #[test] 20 | fn test_parse_get_instance_info_request() { 21 | match parse_get_instance_info().unwrap().into_parts() { 22 | (RequestAction::Sync(action), _) if *action == VmmAction::GetVmInstanceInfo => {} 23 | _ => panic!("Test failed."), 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/firecracker/src/api_server/request/metrics.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use vmm::logger::{IncMetric, METRICS}; 5 | use vmm::rpc_interface::VmmAction; 6 | use vmm::vmm_config::metrics::MetricsConfig; 7 | 8 | use super::super::parsed_request::{ParsedRequest, RequestError}; 9 | use super::Body; 10 | 11 | pub(crate) fn parse_put_metrics(body: &Body) -> Result { 12 | METRICS.put_api_requests.metrics_count.inc(); 13 | Ok(ParsedRequest::new_sync(VmmAction::ConfigureMetrics( 14 | serde_json::from_slice::(body.raw()).inspect_err(|_| { 15 | METRICS.put_api_requests.metrics_fails.inc(); 16 | })?, 17 | ))) 18 | } 19 | 20 | #[cfg(test)] 21 | mod tests { 22 | use std::path::PathBuf; 23 | 24 | use super::*; 25 | use crate::api_server::parsed_request::tests::vmm_action_from_request; 26 | 27 | #[test] 28 | fn test_parse_put_metrics_request() { 29 | let body = r#"{ 30 | "metrics_path": "metrics" 31 | }"#; 32 | let expected_config = MetricsConfig { 33 | metrics_path: PathBuf::from("metrics"), 34 | }; 35 | assert_eq!( 36 | vmm_action_from_request(parse_put_metrics(&Body::new(body)).unwrap()), 37 | VmmAction::ConfigureMetrics(expected_config) 38 | ); 39 | 40 | let invalid_body = r#"{ 41 | "invalid_field": "metrics" 42 | }"#; 43 | parse_put_metrics(&Body::new(invalid_body)).unwrap_err(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/firecracker/src/api_server/request/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod actions; 5 | pub mod balloon; 6 | pub mod boot_source; 7 | pub mod cpu_configuration; 8 | pub mod drive; 9 | pub mod entropy; 10 | pub mod instance_info; 11 | pub mod logger; 12 | pub mod machine_configuration; 13 | pub mod metrics; 14 | pub mod mmds; 15 | pub mod net; 16 | pub mod snapshot; 17 | pub mod version; 18 | pub mod vsock; 19 | pub use micro_http::{Body, Method, StatusCode}; 20 | -------------------------------------------------------------------------------- /src/firecracker/src/api_server/request/version.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use vmm::logger::{IncMetric, METRICS}; 5 | use vmm::rpc_interface::VmmAction; 6 | 7 | use super::super::parsed_request::{ParsedRequest, RequestError}; 8 | 9 | pub(crate) fn parse_get_version() -> Result { 10 | METRICS.get_api_requests.vmm_version_count.inc(); 11 | Ok(ParsedRequest::new_sync(VmmAction::GetVmmVersion)) 12 | } 13 | 14 | #[cfg(test)] 15 | mod tests { 16 | use super::super::super::parsed_request::RequestAction; 17 | use super::*; 18 | 19 | #[test] 20 | fn test_parse_get_version_request() { 21 | match parse_get_version().unwrap().into_parts() { 22 | (RequestAction::Sync(action), _) if *action == VmmAction::GetVmmVersion => {} 23 | _ => panic!("Test failed."), 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/firecracker/src/generated/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod prctl; 5 | -------------------------------------------------------------------------------- /src/firecracker/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod api_server; 5 | -------------------------------------------------------------------------------- /src/jailer/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "jailer" 3 | version = "1.13.0-dev" 4 | authors = ["Amazon Firecracker team "] 5 | edition = "2024" 6 | description = "Process for starting Firecracker in production scenarios; applies a cgroup/namespace isolation barrier and then drops privileges." 7 | homepage = "https://firecracker-microvm.github.io/" 8 | license = "Apache-2.0" 9 | 10 | [[bin]] 11 | name = "jailer" 12 | bench = false 13 | 14 | [features] 15 | tracing = ["log-instrument", "utils/tracing"] 16 | 17 | [dependencies] 18 | libc = "0.2.172" 19 | log-instrument = { path = "../log-instrument", optional = true } 20 | regex = { version = "1.11.1", default-features = false, features = ["std"] } 21 | thiserror = "2.0.12" 22 | vmm-sys-util = "0.12.1" 23 | 24 | utils = { path = "../utils" } 25 | 26 | [lints] 27 | workspace = true 28 | -------------------------------------------------------------------------------- /src/log-instrument-macros/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "log-instrument-macros" 3 | version = "0.1.0" 4 | authors = ["Amazon Firecracker team "] 5 | edition = "2024" 6 | description = "Offers an attribute procedural macro that adds `log::trace!` events at the start and end of attributed functions." 7 | license = "Apache-2.0" 8 | 9 | [lib] 10 | proc-macro = true 11 | bench = false 12 | 13 | [dependencies] 14 | proc-macro2 = "1.0.95" 15 | quote = "1.0.40" 16 | syn = { version = "2.0.101", features = ["full", "extra-traits"] } 17 | 18 | [lints] 19 | workspace = true 20 | -------------------------------------------------------------------------------- /src/log-instrument-macros/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #![warn(clippy::pedantic)] 5 | 6 | extern crate proc_macro; 7 | use quote::quote; 8 | use syn::parse_quote; 9 | 10 | /// Adds `log::trace!` events at the start and end of an attributed function. 11 | /// 12 | /// # Panics 13 | /// 14 | /// When applied to anything other than a function. 15 | #[proc_macro_attribute] 16 | pub fn instrument( 17 | _attr: proc_macro::TokenStream, 18 | item: proc_macro::TokenStream, 19 | ) -> proc_macro::TokenStream { 20 | let input = syn::parse_macro_input!(item as syn::Item); 21 | 22 | let syn::Item::Fn(mut item_fn) = input else { 23 | panic!("Instrument macro can only be on functions.") 24 | }; 25 | 26 | let clippy_attr: syn::Attribute = parse_quote! { 27 | #[allow(clippy::items_after_statements)] 28 | }; 29 | item_fn.attrs.push(clippy_attr); 30 | 31 | let item_fn_ident = item_fn.sig.ident.to_string(); 32 | let new_stmt: syn::Stmt = 33 | parse_quote! { let __ = log_instrument::__Instrument::new(#item_fn_ident); }; 34 | item_fn.block.stmts.insert(0, new_stmt); 35 | 36 | let out = quote! { #item_fn }; 37 | proc_macro::TokenStream::from(out) 38 | } 39 | -------------------------------------------------------------------------------- /src/log-instrument/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "log-instrument" 3 | version = "0.3.0" 4 | authors = ["Amazon Firecracker team "] 5 | edition = "2024" 6 | description = "Offers an attribute procedural macro that adds `log::trace!` events at the start and end of attributed functions." 7 | license = "Apache-2.0" 8 | 9 | [lib] 10 | bench = false 11 | 12 | [dependencies] 13 | log = "0.4.27" 14 | log-instrument-macros = { path = "../log-instrument-macros" } 15 | 16 | [dev-dependencies] 17 | env_logger = "0.11.8" 18 | 19 | [[example]] 20 | name = "one" 21 | 22 | [[example]] 23 | name = "two" 24 | 25 | [[example]] 26 | name = "three" 27 | 28 | [[example]] 29 | name = "four" 30 | 31 | [[example]] 32 | name = "five" 33 | 34 | [[example]] 35 | name = "six" 36 | 37 | [lints] 38 | workspace = true 39 | -------------------------------------------------------------------------------- /src/log-instrument/README.md: -------------------------------------------------------------------------------- 1 | # log-instrument 2 | 3 | Offers an attribute procedural macro that adds 4 | [`log::trace!`](https://docs.rs/log/latest/log/macro.trace.html) events at the 5 | start and end of attributed functions. 6 | 7 | ## Example 8 | 9 | ```rust 10 | use log::*; 11 | 12 | fn main() { 13 | env_logger::builder() 14 | .filter_level(LevelFilter::Trace) 15 | .init(); 16 | info!("{}", one(2)); 17 | info!("{}", one(3)); 18 | info!("{}", one(4)); 19 | } 20 | #[log_instrument::instrument] 21 | fn one(x: u32) -> u32 { 22 | let cmp = x == 2; 23 | debug!("cmp: {cmp}"); 24 | if cmp { 25 | return 4; 26 | } 27 | two(x + 3) 28 | } 29 | #[log_instrument::instrument] 30 | fn two(x: u32) -> u32 { 31 | let res = x % 2; 32 | debug!("res: {res}"); 33 | res 34 | } 35 | ``` 36 | 37 | Outputs: 38 | 39 | ``` 40 | [2023-10-12T16:38:00Z TRACE log_instrument] ThreadId(1)>>one 41 | [2023-10-12T16:38:00Z DEBUG six] cmp: true 42 | [2023-10-12T16:38:00Z TRACE log_instrument] ThreadId(1)<>one 45 | [2023-10-12T16:38:00Z DEBUG six] cmp: false 46 | [2023-10-12T16:38:00Z TRACE log_instrument] ThreadId(1)::one>>two 47 | [2023-10-12T16:38:00Z DEBUG six] res: 0 48 | [2023-10-12T16:38:00Z TRACE log_instrument] ThreadId(1)::one<>one 52 | [2023-10-12T16:38:00Z DEBUG six] cmp: false 53 | [2023-10-12T16:38:00Z TRACE log_instrument] ThreadId(1)::one>>two 54 | [2023-10-12T16:38:00Z DEBUG six] res: 1 55 | [2023-10-12T16:38:00Z TRACE log_instrument] ThreadId(1)::one<>); 18 | 19 | impl MyStruct { 20 | #[log_instrument::instrument] 21 | fn one(&mut self) -> Option<&mut [String]> { 22 | const SOMETHING: u32 = 23; 23 | match &mut self.0 { 24 | Some(y) => { 25 | debug!("{y:?}"); 26 | debug!("{SOMETHING}"); 27 | Some(y) 28 | } 29 | _ => None, 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /src/log-instrument/examples/four.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use log::*; 5 | 6 | fn main() { 7 | env_logger::builder() 8 | .filter_level(LevelFilter::Trace) 9 | .init(); 10 | let mut my_struct = MyStruct(None); 11 | info!("{:?}", my_struct.one()); 12 | let mut my_struct = MyStruct(Some(vec![String::from("a"), String::from("b")])); 13 | info!("{:?}", my_struct.one()); 14 | } 15 | struct MyStruct(Option>); 16 | 17 | impl MyStruct { 18 | #[log_instrument::instrument] 19 | fn one(&mut self) -> Option<&mut [String]> { 20 | match &mut self.0 { 21 | Some(y) => { 22 | debug!("{y:?}"); 23 | Some(y) 24 | } 25 | _ => None, 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/log-instrument/examples/one.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use log::*; 5 | 6 | fn main() { 7 | env_logger::builder() 8 | .filter_level(LevelFilter::Trace) 9 | .init(); 10 | info!("{}", one(2)); 11 | info!("{}", one(3)); 12 | info!("{}", one(4)); 13 | } 14 | #[log_instrument::instrument] 15 | fn one(x: u32) -> u32 { 16 | let cmp = x == 2; 17 | debug!("cmp: {cmp}"); 18 | if cmp { 19 | return 4; 20 | } 21 | x + 3 22 | } 23 | -------------------------------------------------------------------------------- /src/log-instrument/examples/six.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use log::*; 5 | 6 | fn main() { 7 | env_logger::builder() 8 | .filter_level(LevelFilter::Trace) 9 | .init(); 10 | info!("{}", one(2)); 11 | info!("{}", one(3)); 12 | info!("{}", one(4)); 13 | } 14 | #[log_instrument::instrument] 15 | fn one(x: u32) -> u32 { 16 | let cmp = x == 2; 17 | debug!("cmp: {cmp}"); 18 | if cmp { 19 | return 4; 20 | } 21 | two(x + 3) 22 | } 23 | #[log_instrument::instrument] 24 | fn two(x: u32) -> u32 { 25 | let res = x % 2; 26 | debug!("res: {res}"); 27 | res 28 | } 29 | -------------------------------------------------------------------------------- /src/log-instrument/examples/three.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use log::*; 5 | 6 | fn main() { 7 | env_logger::builder() 8 | .filter_level(LevelFilter::Trace) 9 | .init(); 10 | info!("{:?}", one(&mut None)); 11 | info!( 12 | "{:?}", 13 | one(&mut Some(vec![String::from("a"), String::from("b")])) 14 | ); 15 | } 16 | #[log_instrument::instrument] 17 | fn one(x: &mut Option>) -> Option<&mut [String]> { 18 | match x { 19 | Some(y) => { 20 | debug!("{y:?}"); 21 | Some(y) 22 | } 23 | _ => None, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/log-instrument/examples/two.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use log::*; 5 | 6 | fn main() { 7 | env_logger::builder() 8 | .filter_level(LevelFilter::Trace) 9 | .init(); 10 | info!("{:?}", one(&None)); 11 | info!( 12 | "{:?}", 13 | one(&Some(vec![String::from("a"), String::from("b")])) 14 | ); 15 | } 16 | #[log_instrument::instrument] 17 | fn one(x: &Option>) -> Option<&[String]> { 18 | match x { 19 | Some(y) => { 20 | debug!("{y:?}"); 21 | Some(y) 22 | } 23 | _ => None, 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /src/log-instrument/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use std::collections::HashMap; 5 | use std::fmt::Write; 6 | use std::sync::{Mutex, OnceLock}; 7 | 8 | pub use log_instrument_macros::*; 9 | 10 | type InnerPath = Mutex>>; 11 | static PATH: OnceLock = OnceLock::new(); 12 | fn path() -> &'static InnerPath { 13 | PATH.get_or_init(InnerPath::default) 14 | } 15 | 16 | #[allow(missing_debug_implementations)] 17 | pub struct __Instrument; 18 | 19 | impl __Instrument { 20 | pub fn new(s: &'static str) -> __Instrument { 21 | // Get log 22 | let mut guard = path().lock().unwrap(); 23 | let id = std::thread::current().id(); 24 | let prefix = if let Some(spans) = guard.get_mut(&id) { 25 | let out = spans.iter().fold(String::new(), |mut s, x| { 26 | let _ = write!(s, "::{x}"); 27 | s 28 | }); 29 | spans.push(s); 30 | out 31 | } else { 32 | guard.insert(id, vec![s]); 33 | String::new() 34 | }; 35 | 36 | // Write log 37 | log::trace!("{id:?}{prefix}>>{s}"); 38 | 39 | // Return exit struct 40 | __Instrument 41 | } 42 | } 43 | impl std::ops::Drop for __Instrument { 44 | fn drop(&mut self) { 45 | // Get log 46 | let mut guard = path().lock().unwrap(); 47 | let id = std::thread::current().id(); 48 | let spans = guard.get_mut(&id).unwrap(); 49 | let s = spans.pop().unwrap(); 50 | let out = spans.iter().fold(String::new(), |mut s, x| { 51 | let _ = write!(s, "::{x}"); 52 | s 53 | }); 54 | log::trace!("{id:?}{out}<<{s}"); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/rebase-snap/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rebase-snap" 3 | version = "1.13.0-dev" 4 | authors = ["Amazon Firecracker team "] 5 | edition = "2024" 6 | license = "Apache-2.0" 7 | 8 | [[bin]] 9 | name = "rebase-snap" 10 | bench = false 11 | 12 | [features] 13 | tracing = ["log-instrument", "utils/tracing"] 14 | 15 | [dependencies] 16 | displaydoc = "0.2.5" 17 | libc = "0.2.172" 18 | log-instrument = { path = "../log-instrument", optional = true } 19 | thiserror = "2.0.12" 20 | vmm-sys-util = "0.12.1" 21 | 22 | utils = { path = "../utils" } 23 | 24 | [lints] 25 | workspace = true 26 | -------------------------------------------------------------------------------- /src/seccompiler/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "seccompiler" 3 | version = "1.13.0-dev" 4 | authors = ["Amazon Firecracker team "] 5 | edition = "2024" 6 | description = "Program that compiles multi-threaded seccomp-bpf filters expressed as JSON into raw BPF programs, serializing them and outputting them to a file." 7 | homepage = "https://firecracker-microvm.github.io/" 8 | license = "Apache-2.0" 9 | 10 | [lib] 11 | bench = false 12 | 13 | [[bin]] 14 | name = "seccompiler-bin" 15 | path = "src/bin.rs" 16 | bench = false 17 | 18 | [dependencies] 19 | bincode = { version = "2.0.1", features = ["serde"] } 20 | clap = { version = "4.5.38", features = ["derive", "string"] } 21 | displaydoc = "0.2.5" 22 | libc = "0.2.172" 23 | serde = { version = "1.0.219", features = ["derive"] } 24 | serde_json = "1.0.140" 25 | thiserror = "2.0.12" 26 | zerocopy = { version = "0.8.25" } 27 | 28 | [lints] 29 | workspace = true 30 | -------------------------------------------------------------------------------- /src/seccompiler/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | fn main() { 5 | println!("cargo::rustc-link-search=/usr/local/lib"); 6 | println!("cargo::rustc-link-lib=seccomp"); 7 | } 8 | -------------------------------------------------------------------------------- /src/seccompiler/src/bin.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use clap::Parser; 5 | use seccompiler::{CompilationError, compile_bpf}; 6 | 7 | const DEFAULT_OUTPUT_FILENAME: &str = "seccomp_binary_filter.out"; 8 | 9 | #[derive(Debug, Parser)] 10 | #[command(version = format!("v{}", env!("CARGO_PKG_VERSION")))] 11 | struct Cli { 12 | #[arg( 13 | short, 14 | long, 15 | help = "The computer architecture where the BPF program runs. Supported architectures: \ 16 | x86_64, aarch64." 17 | )] 18 | target_arch: String, 19 | #[arg(short, long, help = "File path of the JSON input.")] 20 | input_file: String, 21 | #[arg(short, long, help = "Optional path of the output file.", default_value = DEFAULT_OUTPUT_FILENAME)] 22 | output_file: String, 23 | #[arg( 24 | short, 25 | long, 26 | help = "Deprecated! Transforms the filters into basic filters. Drops all argument checks \ 27 | and rule-level actions. Not recommended." 28 | )] 29 | basic: bool, 30 | } 31 | 32 | fn main() -> Result<(), CompilationError> { 33 | let cli = Cli::parse(); 34 | compile_bpf( 35 | &cli.input_file, 36 | &cli.target_arch, 37 | &cli.output_file, 38 | cli.basic, 39 | ) 40 | } 41 | -------------------------------------------------------------------------------- /src/snapshot-editor/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "snapshot-editor" 3 | version = "1.13.0-dev" 4 | authors = ["Amazon Firecracker team "] 5 | edition = "2024" 6 | license = "Apache-2.0" 7 | 8 | [[bin]] 9 | name = "snapshot-editor" 10 | bench = false 11 | 12 | [features] 13 | tracing = ["log-instrument", "fc_utils/tracing", "vmm/tracing"] 14 | 15 | [dependencies] 16 | clap = { version = "4.5.38", features = ["derive", "string"] } 17 | displaydoc = "0.2.5" 18 | 19 | fc_utils = { package = "utils", path = "../utils" } 20 | libc = "0.2.172" 21 | log-instrument = { path = "../log-instrument", optional = true } 22 | semver = "1.0.26" 23 | thiserror = "2.0.12" 24 | vmm = { path = "../vmm" } 25 | vmm-sys-util = "0.12.1" 26 | 27 | [target.'cfg(target_arch = "aarch64")'.dependencies] 28 | clap-num = "1.2.0" 29 | 30 | [lints] 31 | workspace = true 32 | -------------------------------------------------------------------------------- /src/snapshot-editor/src/utils.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use std::fs::{File, OpenOptions}; 5 | use std::path::PathBuf; 6 | 7 | use semver::Version; 8 | use vmm::persist::MicrovmState; 9 | use vmm::snapshot::Snapshot; 10 | use vmm::utils::u64_to_usize; 11 | 12 | // Some errors are only used in aarch64 code 13 | #[allow(unused)] 14 | #[derive(Debug, thiserror::Error, displaydoc::Display)] 15 | pub enum UtilsError { 16 | /// Can not open snapshot file: {0} 17 | VmStateFileOpen(std::io::Error), 18 | /// Can not retrieve metadata for snapshot file: {0} 19 | VmStateFileMeta(std::io::Error), 20 | /// Can not load snapshot: {0} 21 | VmStateLoad(vmm::snapshot::SnapshotError), 22 | /// Can not open output file: {0} 23 | OutputFileOpen(std::io::Error), 24 | /// Can not save snapshot: {0} 25 | VmStateSave(vmm::snapshot::SnapshotError), 26 | } 27 | 28 | #[allow(unused)] 29 | pub fn open_vmstate(snapshot_path: &PathBuf) -> Result<(MicrovmState, Version), UtilsError> { 30 | let mut snapshot_reader = File::open(snapshot_path).map_err(UtilsError::VmStateFileOpen)?; 31 | let metadata = std::fs::metadata(snapshot_path).map_err(UtilsError::VmStateFileMeta)?; 32 | let snapshot_len = u64_to_usize(metadata.len()); 33 | Snapshot::load(&mut snapshot_reader, snapshot_len).map_err(UtilsError::VmStateLoad) 34 | } 35 | 36 | // This method is used only in aarch64 code so far 37 | #[allow(unused)] 38 | pub fn save_vmstate( 39 | microvm_state: MicrovmState, 40 | output_path: &PathBuf, 41 | version: Version, 42 | ) -> Result<(), UtilsError> { 43 | let mut output_file = OpenOptions::new() 44 | .create(true) 45 | .write(true) 46 | .truncate(true) 47 | .open(output_path) 48 | .map_err(UtilsError::OutputFileOpen)?; 49 | let mut snapshot = Snapshot::new(version); 50 | snapshot 51 | .save(&mut output_file, µvm_state) 52 | .map_err(UtilsError::VmStateSave)?; 53 | Ok(()) 54 | } 55 | -------------------------------------------------------------------------------- /src/utils/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "utils" 3 | version = "0.1.0" 4 | authors = ["Amazon Firecracker team "] 5 | edition = "2024" 6 | license = "Apache-2.0" 7 | 8 | [lib] 9 | bench = false 10 | 11 | [features] 12 | tracing = ["log-instrument"] 13 | 14 | [dependencies] 15 | displaydoc = "0.2.5" 16 | libc = "0.2.172" 17 | log-instrument = { path = "../log-instrument", optional = true } 18 | thiserror = "2.0.12" 19 | 20 | [lints] 21 | workspace = true 22 | -------------------------------------------------------------------------------- /src/utils/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod arg_parser; 5 | pub mod time; 6 | pub mod validators; 7 | -------------------------------------------------------------------------------- /src/vmm/benches/block_request.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | // Benchmarking cases: 5 | // * `Queue.pop` 6 | // * `Queue.add_used` 7 | // * `DescriptorChain.next_descriptor` 8 | 9 | use criterion::{Criterion, criterion_group, criterion_main}; 10 | use vm_memory::GuestAddress; 11 | use vmm::devices::virtio::block::virtio::test_utils::RequestDescriptorChain; 12 | use vmm::devices::virtio::block::virtio::{Request, RequestHeader, VIRTIO_BLK_T_IN}; 13 | use vmm::devices::virtio::test_utils::VirtQueue; 14 | use vmm::test_utils::single_region_mem; 15 | 16 | pub fn block_request_benchmark(c: &mut Criterion) { 17 | let mem = single_region_mem(65562); 18 | let virt_queue = VirtQueue::new(GuestAddress(0), &mem, 16); 19 | 20 | // We don't really care about what request is. We just 21 | // need it to be valid. 22 | let chain = RequestDescriptorChain::new(&virt_queue); 23 | let request_header = RequestHeader::new(VIRTIO_BLK_T_IN, 99); 24 | chain.set_header(request_header); 25 | 26 | let mut queue = virt_queue.create_queue(); 27 | let desc = queue.pop().unwrap(); 28 | 29 | c.bench_function("request_parse", |b| { 30 | b.iter(|| { 31 | let desc = std::hint::black_box(&desc); 32 | _ = Request::parse(desc, &mem, 1024); 33 | }) 34 | }); 35 | } 36 | 37 | criterion_group! { 38 | name = block_request_benches; 39 | config = Criterion::default().sample_size(1000).noise_threshold(0.05); 40 | targets = block_request_benchmark 41 | } 42 | 43 | criterion_main! { 44 | block_request_benches 45 | } 46 | -------------------------------------------------------------------------------- /src/vmm/benches/cpu_templates.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | // Benchmarking cases: 5 | // * `CustomCpuTemplate` JSON deserialization 6 | // * `CustomCpuTemplate` JSON serialization 7 | 8 | use std::mem::size_of_val; 9 | 10 | use criterion::{Criterion, criterion_group, criterion_main}; 11 | use vmm::cpu_config::templates::CustomCpuTemplate; 12 | use vmm::cpu_config::templates::test_utils::{TEST_TEMPLATE_JSON, build_test_template}; 13 | 14 | #[inline] 15 | pub fn bench_serialize_cpu_template(cpu_template: &CustomCpuTemplate) { 16 | let _ = serde_json::to_string(cpu_template); 17 | } 18 | 19 | #[inline] 20 | pub fn bench_deserialize_cpu_template(cpu_template_str: &str) { 21 | let _ = serde_json::from_str::(cpu_template_str); 22 | } 23 | 24 | pub fn cpu_template_benchmark(c: &mut Criterion) { 25 | println!( 26 | "Deserialization test - Template size (JSON string): [{}] bytes.", 27 | TEST_TEMPLATE_JSON.len() 28 | ); 29 | 30 | let test_cpu_template = build_test_template(); 31 | println!( 32 | "Serialization test - Template size: [{}] bytes.", 33 | size_of_val(&test_cpu_template) 34 | ); 35 | 36 | c.bench_function("deserialize_cpu_template", |b| { 37 | b.iter(|| bench_deserialize_cpu_template(TEST_TEMPLATE_JSON)) 38 | }); 39 | 40 | c.bench_function("serialize_cpu_template", |b| { 41 | b.iter(|| bench_serialize_cpu_template(&test_cpu_template)) 42 | }); 43 | } 44 | 45 | criterion_group! { 46 | name = cpu_template_benches; 47 | config = Criterion::default().sample_size(200).noise_threshold(0.05); 48 | targets = cpu_template_benchmark 49 | } 50 | 51 | criterion_main! { 52 | cpu_template_benches 53 | } 54 | -------------------------------------------------------------------------------- /src/vmm/src/acpi/x86_64.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use std::mem::size_of; 5 | 6 | use acpi_tables::fadt::{ 7 | IAPC_BOOT_ARG_FLAGS_MSI_NOT_PRESENT, IAPC_BOOT_ARG_FLAGS_PCI_ASPM, 8 | IAPC_BOOT_ARG_FLAGS_VGA_NOT_PRESENT, 9 | }; 10 | use acpi_tables::madt::{IoAPIC, LocalAPIC}; 11 | use acpi_tables::{Fadt, aml}; 12 | use vm_memory::GuestAddress; 13 | use zerocopy::IntoBytes; 14 | 15 | use crate::arch::x86_64::layout; 16 | use crate::device_manager::legacy::PortIODeviceManager; 17 | 18 | #[inline(always)] 19 | pub(crate) fn setup_interrupt_controllers(nr_vcpus: u8) -> Vec { 20 | let mut ic = 21 | Vec::with_capacity(size_of::() + (nr_vcpus as usize) * size_of::()); 22 | 23 | ic.extend_from_slice(IoAPIC::new(0, layout::IOAPIC_ADDR).as_bytes()); 24 | for i in 0..nr_vcpus { 25 | ic.extend_from_slice(LocalAPIC::new(i).as_bytes()); 26 | } 27 | ic 28 | } 29 | 30 | #[inline(always)] 31 | pub(crate) fn setup_arch_fadt(fadt: &mut Fadt) { 32 | // Let the guest kernel know that there is not VGA hardware present 33 | // neither do we support ASPM, or MSI type of interrupts. 34 | // More info here: 35 | // https://uefi.org/specs/ACPI/6.5/05_ACPI_Software_Programming_Model.html?highlight=0a06#ia-pc-boot-architecture-flags 36 | fadt.setup_iapc_flags( 37 | (1 << IAPC_BOOT_ARG_FLAGS_VGA_NOT_PRESENT) 38 | | (1 << IAPC_BOOT_ARG_FLAGS_PCI_ASPM) 39 | | (1 << IAPC_BOOT_ARG_FLAGS_MSI_NOT_PRESENT), 40 | ); 41 | } 42 | 43 | #[inline(always)] 44 | pub(crate) fn setup_arch_dsdt(dsdt_data: &mut Vec) -> Result<(), aml::AmlError> { 45 | PortIODeviceManager::append_aml_bytes(dsdt_data) 46 | } 47 | 48 | pub(crate) const fn apic_addr() -> u32 { 49 | layout::APIC_ADDR 50 | } 51 | 52 | pub(crate) const fn rsdp_addr() -> GuestAddress { 53 | GuestAddress(layout::RSDP_ADDR) 54 | } 55 | -------------------------------------------------------------------------------- /src/vmm/src/arch/aarch64/kvm.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use std::convert::Infallible; 5 | 6 | use kvm_ioctls::Kvm as KvmFd; 7 | 8 | use crate::cpu_config::templates::KvmCapability; 9 | 10 | /// ['Kvm'] initialization can't fail for Aarch64 11 | pub type KvmArchError = Infallible; 12 | 13 | /// Optional capabilities. 14 | #[derive(Debug, Default)] 15 | pub struct OptionalCapabilities { 16 | /// KVM_CAP_COUNTER_OFFSET 17 | pub counter_offset: bool, 18 | } 19 | 20 | /// Struct with kvm fd and kvm associated parameters. 21 | #[derive(Debug)] 22 | pub struct Kvm { 23 | /// KVM fd. 24 | pub fd: KvmFd, 25 | /// Additional capabilities that were specified in cpu template. 26 | pub kvm_cap_modifiers: Vec, 27 | } 28 | 29 | impl Kvm { 30 | pub(crate) const DEFAULT_CAPABILITIES: [u32; 7] = [ 31 | kvm_bindings::KVM_CAP_IOEVENTFD, 32 | kvm_bindings::KVM_CAP_IRQFD, 33 | kvm_bindings::KVM_CAP_USER_MEMORY, 34 | kvm_bindings::KVM_CAP_ARM_PSCI_0_2, 35 | kvm_bindings::KVM_CAP_DEVICE_CTRL, 36 | kvm_bindings::KVM_CAP_MP_STATE, 37 | kvm_bindings::KVM_CAP_ONE_REG, 38 | ]; 39 | 40 | /// Initialize [`Kvm`] type for Aarch64 architecture 41 | pub fn init_arch( 42 | fd: KvmFd, 43 | kvm_cap_modifiers: Vec, 44 | ) -> Result { 45 | Ok(Self { 46 | fd, 47 | kvm_cap_modifiers, 48 | }) 49 | } 50 | 51 | /// Returns struct with optional capabilities statuses. 52 | pub fn optional_capabilities(&self) -> OptionalCapabilities { 53 | OptionalCapabilities { 54 | counter_offset: self 55 | .fd 56 | .check_extension_raw(kvm_bindings::KVM_CAP_COUNTER_OFFSET.into()) 57 | != 0, 58 | } 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/vmm/src/arch/aarch64/output_GICv2.dtb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/src/vmm/src/arch/aarch64/output_GICv2.dtb -------------------------------------------------------------------------------- /src/vmm/src/arch/aarch64/output_GICv3.dtb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/src/vmm/src/arch/aarch64/output_GICv3.dtb -------------------------------------------------------------------------------- /src/vmm/src/arch/aarch64/output_initrd_GICv2.dtb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/src/vmm/src/arch/aarch64/output_initrd_GICv2.dtb -------------------------------------------------------------------------------- /src/vmm/src/arch/aarch64/output_initrd_GICv3.dtb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/src/vmm/src/arch/aarch64/output_initrd_GICv3.dtb -------------------------------------------------------------------------------- /src/vmm/src/arch/x86_64/generated/arch_prctl.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // automatically generated by tools/bindgen.sh 5 | 6 | #![allow( 7 | non_camel_case_types, 8 | non_upper_case_globals, 9 | dead_code, 10 | non_snake_case, 11 | clippy::ptr_as_ptr, 12 | clippy::undocumented_unsafe_blocks, 13 | missing_debug_implementations, 14 | clippy::tests_outside_test_module, 15 | unsafe_op_in_unsafe_fn 16 | )] 17 | 18 | pub const ARCH_SET_GS: u32 = 4097; 19 | pub const ARCH_SET_FS: u32 = 4098; 20 | pub const ARCH_GET_FS: u32 = 4099; 21 | pub const ARCH_GET_GS: u32 = 4100; 22 | pub const ARCH_GET_CPUID: u32 = 4113; 23 | pub const ARCH_SET_CPUID: u32 = 4114; 24 | pub const ARCH_GET_XCOMP_SUPP: u32 = 4129; 25 | pub const ARCH_GET_XCOMP_PERM: u32 = 4130; 26 | pub const ARCH_REQ_XCOMP_PERM: u32 = 4131; 27 | pub const ARCH_GET_XCOMP_GUEST_PERM: u32 = 4132; 28 | pub const ARCH_REQ_XCOMP_GUEST_PERM: u32 = 4133; 29 | pub const ARCH_XCOMP_TILECFG: u32 = 17; 30 | pub const ARCH_XCOMP_TILEDATA: u32 = 18; 31 | pub const ARCH_MAP_VDSO_X32: u32 = 8193; 32 | pub const ARCH_MAP_VDSO_32: u32 = 8194; 33 | pub const ARCH_MAP_VDSO_64: u32 = 8195; 34 | pub const ARCH_GET_UNTAG_MASK: u32 = 16385; 35 | pub const ARCH_ENABLE_TAGGED_ADDR: u32 = 16386; 36 | pub const ARCH_GET_MAX_TAG_BITS: u32 = 16387; 37 | pub const ARCH_FORCE_TAGGED_SVA: u32 = 16388; 38 | pub const ARCH_SHSTK_ENABLE: u32 = 20481; 39 | pub const ARCH_SHSTK_DISABLE: u32 = 20482; 40 | pub const ARCH_SHSTK_LOCK: u32 = 20483; 41 | pub const ARCH_SHSTK_UNLOCK: u32 = 20484; 42 | pub const ARCH_SHSTK_STATUS: u32 = 20485; 43 | pub const ARCH_SHSTK_SHSTK: u32 = 1; 44 | pub const ARCH_SHSTK_WRSS: u32 = 2; 45 | -------------------------------------------------------------------------------- /src/vmm/src/arch/x86_64/generated/hyperv.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // automatically generated by tools/bindgen.sh 5 | 6 | #![allow( 7 | non_camel_case_types, 8 | non_upper_case_globals, 9 | dead_code, 10 | non_snake_case, 11 | clippy::ptr_as_ptr, 12 | clippy::undocumented_unsafe_blocks, 13 | missing_debug_implementations, 14 | clippy::tests_outside_test_module, 15 | unsafe_op_in_unsafe_fn 16 | )] 17 | 18 | pub const HV_X64_MSR_SYNDBG_CONTROL: u32 = 0x400000f1; 19 | pub const HV_X64_MSR_SYNDBG_STATUS: u32 = 0x400000f2; 20 | pub const HV_X64_MSR_SYNDBG_SEND_BUFFER: u32 = 0x400000f3; 21 | pub const HV_X64_MSR_SYNDBG_RECV_BUFFER: u32 = 0x400000f4; 22 | pub const HV_X64_MSR_SYNDBG_PENDING_BUFFER: u32 = 0x400000f5; 23 | pub const HV_X64_MSR_SYNDBG_OPTIONS: u32 = 0x400000ff; 24 | -------------------------------------------------------------------------------- /src/vmm/src/arch/x86_64/generated/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. 5 | // Use of this source code is governed by a BSD-style license that can be 6 | // found in the THIRD-PARTY file. 7 | 8 | pub mod arch_prctl; 9 | pub mod hyperv; 10 | pub mod hyperv_tlfs; 11 | pub mod mpspec; 12 | pub mod msr_index; 13 | pub mod perf_event; 14 | -------------------------------------------------------------------------------- /src/vmm/src/arch/x86_64/generated/perf_event.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // automatically generated by tools/bindgen.sh 5 | 6 | #![allow( 7 | non_camel_case_types, 8 | non_upper_case_globals, 9 | dead_code, 10 | non_snake_case, 11 | clippy::ptr_as_ptr, 12 | clippy::undocumented_unsafe_blocks, 13 | missing_debug_implementations, 14 | clippy::tests_outside_test_module, 15 | unsafe_op_in_unsafe_fn 16 | )] 17 | 18 | pub const MSR_ARCH_PERFMON_PERFCTR0: u32 = 0xc1; 19 | pub const MSR_ARCH_PERFMON_PERFCTR1: u32 = 0xc2; 20 | pub const MSR_ARCH_PERFMON_EVENTSEL0: u32 = 0x186; 21 | pub const MSR_ARCH_PERFMON_EVENTSEL1: u32 = 0x187; 22 | pub const MSR_ARCH_PERFMON_FIXED_CTR_CTRL: u32 = 0x38d; 23 | pub const MSR_ARCH_PERFMON_FIXED_CTR0: u32 = 0x309; 24 | pub const MSR_ARCH_PERFMON_FIXED_CTR1: u32 = 0x30a; 25 | pub const MSR_ARCH_PERFMON_FIXED_CTR2: u32 = 0x30b; 26 | pub const MSR_ARCH_PERFMON_FIXED_CTR3: u32 = 0x30c; 27 | -------------------------------------------------------------------------------- /src/vmm/src/cpu_config/aarch64/static_cpu_templates/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use serde::{Deserialize, Serialize}; 5 | 6 | /// Module with V1N1 CPU template for aarch64 7 | pub mod v1n1; 8 | 9 | /// Templates available for configuring the supported ARM CPU types. 10 | #[derive(Debug, Default, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] 11 | pub enum StaticCpuTemplate { 12 | /// Template to mask Neoverse-V1 as Neoverse-N1 13 | V1N1, 14 | /// No CPU template is used. 15 | #[default] 16 | None, 17 | } 18 | 19 | impl StaticCpuTemplate { 20 | /// Check if no template specified 21 | pub fn is_none(&self) -> bool { 22 | self == &StaticCpuTemplate::None 23 | } 24 | } 25 | 26 | impl std::fmt::Display for StaticCpuTemplate { 27 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { 28 | match self { 29 | StaticCpuTemplate::V1N1 => write!(f, "V1N1"), 30 | StaticCpuTemplate::None => write!(f, "None"), 31 | } 32 | } 33 | } 34 | 35 | #[cfg(test)] 36 | mod tests { 37 | use super::*; 38 | use crate::cpu_config::test_utils::get_json_template; 39 | 40 | #[test] 41 | fn verify_consistency_with_json_templates() { 42 | let static_templates = [(v1n1::v1n1(), "V1N1.json")]; 43 | 44 | for (hardcoded_template, filename) in static_templates { 45 | let json_template = get_json_template(filename); 46 | assert_eq!(hardcoded_template, json_template); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/vmm/src/cpu_config/aarch64/test_utils.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use crate::arch::aarch64::regs::{ID_AA64ISAR0_EL1, ID_AA64PFR0_EL1}; 5 | use crate::cpu_config::aarch64::custom_cpu_template::RegisterModifier; 6 | use crate::cpu_config::templates::{CustomCpuTemplate, RegisterValueFilter}; 7 | 8 | /// Test CPU template in JSON format 9 | pub const TEST_TEMPLATE_JSON: &str = r#"{ 10 | "reg_modifiers": [ 11 | { 12 | "addr": "0x0030000000000011", 13 | "bitmap": "0b1xx1" 14 | }, 15 | { 16 | "addr": "0x0030000000000022", 17 | "bitmap": "0b1x00" 18 | } 19 | ] 20 | }"#; 21 | 22 | /// Test CPU template in JSON format but has an invalid field for the architecture. 23 | /// "msr_modifiers" is the field name for the model specific registers for 24 | /// defined by x86 CPUs. 25 | pub const TEST_INVALID_TEMPLATE_JSON: &str = r#"{ 26 | "msr_modifiers": [ 27 | { 28 | "addr": "0x0AAC", 29 | "bitmap": "0b1xx1" 30 | } 31 | ] 32 | }"#; 33 | 34 | /// Builds a sample custom CPU template 35 | pub fn build_test_template() -> CustomCpuTemplate { 36 | CustomCpuTemplate { 37 | reg_modifiers: vec![ 38 | RegisterModifier { 39 | addr: ID_AA64PFR0_EL1, 40 | bitmap: RegisterValueFilter { 41 | filter: 0b100010001, 42 | value: 0b100000001, 43 | }, 44 | }, 45 | RegisterModifier { 46 | addr: ID_AA64ISAR0_EL1, 47 | bitmap: RegisterValueFilter { 48 | filter: 0b1110, 49 | value: 0b0110, 50 | }, 51 | }, 52 | ], 53 | ..Default::default() 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/vmm/src/cpu_config/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | /// Module with types used for custom CPU templates 5 | pub mod templates; 6 | /// Module with ser/de utils for custom CPU templates 7 | pub mod templates_serde; 8 | 9 | /// Module containing type implementations needed for x86 CPU configuration 10 | #[cfg(target_arch = "x86_64")] 11 | pub mod x86_64; 12 | 13 | /// Module containing type implementations needed for aarch64 (ARM) CPU configuration 14 | #[cfg(target_arch = "aarch64")] 15 | pub mod aarch64; 16 | 17 | #[cfg(test)] 18 | pub(crate) mod test_utils; 19 | -------------------------------------------------------------------------------- /src/vmm/src/cpu_config/test_utils.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use std::path::PathBuf; 5 | 6 | use crate::cpu_config::templates::CustomCpuTemplate; 7 | 8 | /// Get a static CPU template stored as a JSON file. 9 | pub fn get_json_template(filename: &str) -> CustomCpuTemplate { 10 | let json_path = [ 11 | env!("CARGO_MANIFEST_DIR"), 12 | "../../tests/data/custom_cpu_templates", 13 | filename, 14 | ] 15 | .iter() 16 | .collect::(); 17 | 18 | serde_json::from_str(&std::fs::read_to_string(json_path).unwrap()).unwrap() 19 | } 20 | -------------------------------------------------------------------------------- /src/vmm/src/device_manager/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. 5 | // Use of this source code is governed by a BSD-style license that can be 6 | // found in the THIRD-PARTY file. 7 | 8 | /// ACPI device manager. 9 | pub mod acpi; 10 | /// Legacy Device Manager. 11 | pub mod legacy; 12 | /// Memory Mapped I/O Manager. 13 | pub mod mmio; 14 | /// Device managers (de)serialization support. 15 | pub mod persist; 16 | /// Resource manager for devices. 17 | pub mod resources; 18 | -------------------------------------------------------------------------------- /src/vmm/src/devices/acpi/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod vmgenid; 5 | -------------------------------------------------------------------------------- /src/vmm/src/devices/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. 5 | // Use of this source code is governed by a BSD-style license that can be 6 | // found in the THIRD-PARTY file. 7 | 8 | //! Emulates virtual and hardware devices. 9 | 10 | use std::io; 11 | 12 | pub mod acpi; 13 | pub mod bus; 14 | pub mod legacy; 15 | pub mod pseudo; 16 | pub mod virtio; 17 | 18 | pub use bus::{Bus, BusDevice, BusError}; 19 | use log::error; 20 | 21 | use crate::devices::virtio::net::metrics::NetDeviceMetrics; 22 | use crate::devices::virtio::queue::QueueError; 23 | use crate::devices::virtio::vsock::VsockError; 24 | use crate::logger::IncMetric; 25 | 26 | // Function used for reporting error in terms of logging 27 | // but also in terms of metrics of net event fails. 28 | // network metrics is reported per device so we need a handle to each net device's 29 | // metrics `net_iface_metrics` to report metrics for that device. 30 | pub(crate) fn report_net_event_fail(net_iface_metrics: &NetDeviceMetrics, err: DeviceError) { 31 | error!("{:?}", err); 32 | net_iface_metrics.event_fails.inc(); 33 | } 34 | 35 | #[derive(Debug, thiserror::Error, displaydoc::Display)] 36 | pub enum DeviceError { 37 | /// Failed to read from the TAP device. 38 | FailedReadTap, 39 | /// Failed to signal irq: {0} 40 | FailedSignalingIrq(io::Error), 41 | /// IO error: {0} 42 | IoError(io::Error), 43 | /// Device received malformed payload. 44 | MalformedPayload, 45 | /// Device received malformed descriptor. 46 | MalformedDescriptor, 47 | /// Error during queue processing: {0} 48 | QueueError(QueueError), 49 | /// Vsock device error: {0} 50 | VsockError(VsockError), 51 | } 52 | -------------------------------------------------------------------------------- /src/vmm/src/devices/pseudo/boot_timer.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use utils::time::TimestampUs; 5 | 6 | use crate::logger::info; 7 | 8 | const MAGIC_VALUE_SIGNAL_GUEST_BOOT_COMPLETE: u8 = 123; 9 | 10 | /// Pseudo device to record the kernel boot time. 11 | #[derive(Debug)] 12 | pub struct BootTimer { 13 | start_ts: TimestampUs, 14 | } 15 | 16 | impl BootTimer { 17 | pub fn bus_write(&mut self, offset: u64, data: &[u8]) { 18 | // Only handle byte length instructions at a zero offset. 19 | if data.len() != 1 || offset != 0 { 20 | return; 21 | } 22 | 23 | if data[0] == MAGIC_VALUE_SIGNAL_GUEST_BOOT_COMPLETE { 24 | let now_tm_us = TimestampUs::default(); 25 | 26 | let boot_time_us = now_tm_us.time_us - self.start_ts.time_us; 27 | let boot_time_cpu_us = now_tm_us.cputime_us - self.start_ts.cputime_us; 28 | info!( 29 | "Guest-boot-time = {:>6} us {} ms, {:>6} CPU us {} CPU ms", 30 | boot_time_us, 31 | boot_time_us / 1000, 32 | boot_time_cpu_us, 33 | boot_time_cpu_us / 1000 34 | ); 35 | } 36 | } 37 | pub fn bus_read(&mut self, _offset: u64, _data: &[u8]) {} 38 | } 39 | 40 | impl BootTimer { 41 | /// Create a device at a certain point in time. 42 | pub fn new(start_ts: TimestampUs) -> BootTimer { 43 | BootTimer { start_ts } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/vmm/src/devices/pseudo/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! Implements Firecracker specific devices (e.g. signal when boot is completed). 5 | mod boot_timer; 6 | 7 | pub use self::boot_timer::BootTimer; 8 | -------------------------------------------------------------------------------- /src/vmm/src/devices/virtio/balloon/test_utils.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #![doc(hidden)] 5 | 6 | use crate::devices::virtio::test_utils::VirtQueue; 7 | #[cfg(test)] 8 | use crate::devices::virtio::{balloon::BALLOON_NUM_QUEUES, balloon::Balloon}; 9 | 10 | #[cfg(test)] 11 | pub fn invoke_handler_for_queue_event(b: &mut Balloon, queue_index: usize) { 12 | use crate::devices::virtio::balloon::{DEFLATE_INDEX, INFLATE_INDEX, STATS_INDEX}; 13 | use crate::devices::virtio::device::IrqType; 14 | 15 | assert!(queue_index < BALLOON_NUM_QUEUES); 16 | // Trigger the queue event. 17 | b.queue_evts[queue_index].write(1).unwrap(); 18 | // Handle event. 19 | match queue_index { 20 | INFLATE_INDEX => b.process_inflate_queue_event().unwrap(), 21 | DEFLATE_INDEX => b.process_deflate_queue_event().unwrap(), 22 | STATS_INDEX => b.process_stats_queue_event().unwrap(), 23 | _ => unreachable!(), 24 | }; 25 | // Validate the queue operation finished successfully. 26 | assert!(b.irq_trigger.has_pending_irq(IrqType::Vring)); 27 | } 28 | 29 | pub fn set_request(queue: &VirtQueue, idx: u16, addr: u64, len: u32, flags: u16) { 30 | // Set the index of the next request. 31 | queue.avail.idx.set(idx + 1); 32 | // Set the current descriptor table entry index. 33 | queue.avail.ring[idx as usize].set(idx); 34 | // Set the current descriptor table entry. 35 | queue.dtable[idx as usize].set(addr, len, flags, 1); 36 | } 37 | 38 | pub fn check_request_completion(queue: &VirtQueue, idx: usize) { 39 | // Check that the next used will be idx + 1. 40 | assert_eq!(queue.used.idx.get() as usize, idx + 1); 41 | // Check that the current used is idx. 42 | assert_eq!(queue.used.ring[idx].get().id as usize, idx); 43 | // The length of the completed request is 0. 44 | assert_eq!(queue.used.ring[idx].get().len, 0); 45 | } 46 | -------------------------------------------------------------------------------- /src/vmm/src/devices/virtio/block/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | use serde::{Deserialize, Serialize}; 4 | 5 | use self::vhost_user::VhostUserBlockError; 6 | use self::virtio::VirtioBlockError; 7 | 8 | pub mod device; 9 | pub mod persist; 10 | pub mod vhost_user; 11 | pub mod virtio; 12 | 13 | /// Configuration options for disk caching. 14 | #[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Deserialize, Serialize)] 15 | pub enum CacheType { 16 | /// Flushing mechanic not will be advertised to the guest driver 17 | #[default] 18 | Unsafe, 19 | /// Flushing mechanic will be advertised to the guest driver and 20 | /// flush requests coming from the guest will be performed using 21 | /// `fsync`. 22 | Writeback, 23 | } 24 | 25 | /// Errors the block device can trigger. 26 | #[derive(Debug, thiserror::Error, displaydoc::Display)] 27 | pub enum BlockError { 28 | /// Invalid block config. 29 | InvalidBlockConfig, 30 | /// Running method expected different backend. 31 | InvalidBlockBackend, 32 | /// Can not restore any backend. 33 | BackendRestore, 34 | /// Virtio backend error: {0} 35 | VirtioBackend(VirtioBlockError), 36 | /// Vhost user backend error: {0} 37 | VhostUserBackend(VhostUserBlockError), 38 | } 39 | -------------------------------------------------------------------------------- /src/vmm/src/devices/virtio/block/persist.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use serde::{Deserialize, Serialize}; 5 | 6 | use super::vhost_user::persist::VhostUserBlockState; 7 | use super::virtio::persist::VirtioBlockState; 8 | use crate::vstate::memory::GuestMemoryMmap; 9 | 10 | /// Block device state. 11 | #[derive(Debug, Clone, Serialize, Deserialize)] 12 | pub enum BlockState { 13 | Virtio(VirtioBlockState), 14 | VhostUser(VhostUserBlockState), 15 | } 16 | 17 | /// Auxiliary structure for creating a device when resuming from a snapshot. 18 | #[derive(Debug)] 19 | pub struct BlockConstructorArgs { 20 | pub mem: GuestMemoryMmap, 21 | } 22 | -------------------------------------------------------------------------------- /src/vmm/src/devices/virtio/block/vhost_user/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod device; 5 | pub mod event_handler; 6 | pub mod persist; 7 | 8 | use self::device::VhostUserBlock; 9 | use crate::devices::virtio::vhost_user::VhostUserError; 10 | 11 | /// Number of queues for the vhost-user block device. 12 | pub const NUM_QUEUES: u64 = 1; 13 | 14 | /// Queue size for the vhost-user block device. 15 | pub const QUEUE_SIZE: u16 = 256; 16 | 17 | /// Vhost-user block device error. 18 | #[derive(Debug, thiserror::Error, displaydoc::Display)] 19 | pub enum VhostUserBlockError { 20 | /// Cannot create config 21 | Config, 22 | /// Snapshotting of vhost-user-blk devices is not supported 23 | SnapshottingNotSupported, 24 | /// Vhost-user error: {0} 25 | VhostUser(VhostUserError), 26 | /// Vhost error: {0} 27 | Vhost(vhost::Error), 28 | /// Error opening eventfd: {0} 29 | EventFd(std::io::Error), 30 | /// Error creating irqfd: {0} 31 | IrqTrigger(std::io::Error), 32 | } 33 | -------------------------------------------------------------------------------- /src/vmm/src/devices/virtio/block/vhost_user/persist.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! Defines the structures needed for saving/restoring block devices. 5 | 6 | use serde::{Deserialize, Serialize}; 7 | 8 | use super::VhostUserBlockError; 9 | use super::device::VhostUserBlock; 10 | use crate::devices::virtio::block::CacheType; 11 | use crate::devices::virtio::block::persist::BlockConstructorArgs; 12 | use crate::devices::virtio::persist::VirtioDeviceState; 13 | use crate::snapshot::Persist; 14 | 15 | /// vhost-user block device state. 16 | #[derive(Debug, Clone, Serialize, Deserialize)] 17 | pub struct VhostUserBlockState { 18 | id: String, 19 | partuuid: Option, 20 | cache_type: CacheType, 21 | root_device: bool, 22 | socket_path: String, 23 | vu_acked_protocol_features: u64, 24 | config_space: Vec, 25 | virtio_state: VirtioDeviceState, 26 | } 27 | 28 | impl Persist<'_> for VhostUserBlock { 29 | type State = VhostUserBlockState; 30 | type ConstructorArgs = BlockConstructorArgs; 31 | type Error = VhostUserBlockError; 32 | 33 | fn save(&self) -> Self::State { 34 | unimplemented!("VhostUserBlock does not support snapshotting yet"); 35 | } 36 | 37 | fn restore( 38 | _constructor_args: Self::ConstructorArgs, 39 | _state: &Self::State, 40 | ) -> Result { 41 | Err(VhostUserBlockError::SnapshottingNotSupported) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /src/vmm/src/devices/virtio/generated/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. 5 | // Use of this source code is governed by a BSD-style license that can be 6 | // found in the THIRD-PARTY file. 7 | 8 | #![allow(clippy::all)] 9 | #![allow(non_upper_case_globals)] 10 | #![allow(non_camel_case_types)] 11 | #![allow(non_snake_case)] 12 | 13 | pub mod virtio_blk; 14 | pub mod virtio_config; 15 | pub mod virtio_net; 16 | pub mod virtio_ring; 17 | -------------------------------------------------------------------------------- /src/vmm/src/devices/virtio/generated/virtio_config.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // automatically generated by tools/bindgen.sh 5 | 6 | #![allow( 7 | non_camel_case_types, 8 | non_upper_case_globals, 9 | dead_code, 10 | non_snake_case, 11 | clippy::ptr_as_ptr, 12 | clippy::undocumented_unsafe_blocks, 13 | missing_debug_implementations, 14 | clippy::tests_outside_test_module, 15 | unsafe_op_in_unsafe_fn 16 | )] 17 | 18 | pub const VIRTIO_F_NOTIFY_ON_EMPTY: u32 = 24; 19 | pub const VIRTIO_F_ANY_LAYOUT: u32 = 27; 20 | pub const VIRTIO_F_VERSION_1: u32 = 32; 21 | pub const VIRTIO_F_ACCESS_PLATFORM: u32 = 33; 22 | pub const VIRTIO_F_IOMMU_PLATFORM: u32 = 33; 23 | pub const VIRTIO_F_RING_PACKED: u32 = 34; 24 | pub const VIRTIO_F_IN_ORDER: u32 = 35; 25 | pub const VIRTIO_F_ORDER_PLATFORM: u32 = 36; 26 | pub const VIRTIO_F_SR_IOV: u32 = 37; 27 | pub const VIRTIO_F_NOTIFICATION_DATA: u32 = 38; 28 | pub const VIRTIO_F_NOTIF_CONFIG_DATA: u32 = 39; 29 | pub const VIRTIO_F_RING_RESET: u32 = 40; 30 | pub const VIRTIO_F_ADMIN_VQ: u32 = 41; 31 | -------------------------------------------------------------------------------- /src/vmm/src/devices/virtio/generated/virtio_ring.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // automatically generated by tools/bindgen.sh 5 | 6 | #![allow( 7 | non_camel_case_types, 8 | non_upper_case_globals, 9 | dead_code, 10 | non_snake_case, 11 | clippy::ptr_as_ptr, 12 | clippy::undocumented_unsafe_blocks, 13 | missing_debug_implementations, 14 | clippy::tests_outside_test_module, 15 | unsafe_op_in_unsafe_fn 16 | )] 17 | 18 | pub const VIRTIO_RING_F_EVENT_IDX: u32 = 29; 19 | -------------------------------------------------------------------------------- /src/vmm/src/devices/virtio/net/generated/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright TUNTAP, 2017 The Chromium OS Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style license that can be 3 | // found in the THIRD-PARTY file. 4 | 5 | #![allow(clippy::all)] 6 | #![allow(non_upper_case_globals)] 7 | #![allow(non_camel_case_types)] 8 | #![allow(non_snake_case)] 9 | 10 | // generated with bindgen /usr/include/linux/if.h --no-unstable-rust 11 | // --constified-enum '*' --with-derive-default -- -D __UAPI_DEF_IF_IFNAMSIZ -D 12 | // __UAPI_DEF_IF_NET_DEVICE_FLAGS -D __UAPI_DEF_IF_IFREQ -D __UAPI_DEF_IF_IFMAP 13 | // Name is "iff" to avoid conflicting with "if" keyword. 14 | // Generated against Linux 4.11 to include fix "uapi: fix linux/if.h userspace 15 | // compilation errors". 16 | // Manual fixup of ifrn_name to be of type c_uchar instead of c_char. 17 | pub mod iff; 18 | // generated with bindgen /usr/include/linux/if_tun.h --no-unstable-rust 19 | // --constified-enum '*' --with-derive-default 20 | pub mod if_tun; 21 | // generated with bindgen /usr/include/linux/sockios.h --no-unstable-rust 22 | // --constified-enum '*' --with-derive-default 23 | pub mod sockios; 24 | pub use if_tun::*; 25 | pub use iff::*; 26 | -------------------------------------------------------------------------------- /src/vmm/src/devices/virtio/net/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! Implements a virtio network device. 5 | 6 | use std::io; 7 | 8 | /// Maximum size of the queue for network device. 9 | pub const NET_QUEUE_MAX_SIZE: u16 = 256; 10 | /// Maximum size of the frame buffers handled by this device. 11 | pub const MAX_BUFFER_SIZE: usize = 65562; 12 | /// The number of queues of the network device. 13 | pub const NET_NUM_QUEUES: usize = 2; 14 | pub const NET_QUEUE_SIZES: [u16; NET_NUM_QUEUES] = [NET_QUEUE_MAX_SIZE; NET_NUM_QUEUES]; 15 | /// The index of the rx queue from Net device queues/queues_evts vector. 16 | pub const RX_INDEX: usize = 0; 17 | /// The index of the tx queue from Net device queues/queues_evts vector. 18 | pub const TX_INDEX: usize = 1; 19 | 20 | pub mod device; 21 | mod event_handler; 22 | pub mod metrics; 23 | pub mod persist; 24 | mod tap; 25 | pub mod test_utils; 26 | 27 | mod generated; 28 | 29 | pub use tap::{Tap, TapError}; 30 | use vm_memory::VolatileMemoryError; 31 | 32 | pub use self::device::Net; 33 | use super::iovec::IoVecError; 34 | 35 | /// Enum representing the Net device queue types 36 | #[derive(Debug)] 37 | pub enum NetQueue { 38 | /// The RX queue 39 | Rx, 40 | /// The TX queue 41 | Tx, 42 | } 43 | 44 | /// Errors the network device can trigger. 45 | #[derive(Debug, thiserror::Error, displaydoc::Display)] 46 | pub enum NetError { 47 | /// Open tap device failed: {0} 48 | TapOpen(TapError), 49 | /// Setting vnet header size failed: {0} 50 | TapSetVnetHdrSize(TapError), 51 | /// EventFd error: {0} 52 | EventFd(io::Error), 53 | /// IO error: {0} 54 | IO(io::Error), 55 | /// Error writing in guest memory: {0} 56 | GuestMemoryError(#[from] VolatileMemoryError), 57 | /// The VNET header is missing from the frame 58 | VnetHeaderMissing, 59 | /// IoVecBuffer(Mut) error: {0} 60 | IoVecError(#[from] IoVecError), 61 | } 62 | -------------------------------------------------------------------------------- /src/vmm/src/devices/virtio/rng/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod device; 5 | mod event_handler; 6 | pub mod metrics; 7 | pub mod persist; 8 | 9 | pub use self::device::{Entropy, EntropyError}; 10 | 11 | pub(crate) const RNG_NUM_QUEUES: usize = 1; 12 | 13 | pub(crate) const RNG_QUEUE: usize = 0; 14 | -------------------------------------------------------------------------------- /src/vmm/src/gdb/arch/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | 5 | #[cfg(target_arch = "aarch64")] 6 | mod aarch64; 7 | #[cfg(target_arch = "aarch64")] 8 | pub use aarch64::*; 9 | 10 | #[cfg(target_arch = "x86_64")] 11 | mod x86; 12 | #[cfg(target_arch = "x86_64")] 13 | pub use x86::*; 14 | -------------------------------------------------------------------------------- /src/vmm/src/io_uring/operation/sqe.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use std::fmt::{self}; 5 | 6 | use crate::io_uring::generated::io_uring_sqe; 7 | use crate::vstate::memory::ByteValued; 8 | 9 | // SAFETY: Struct is POD and contains no references or niches. 10 | unsafe impl ByteValued for io_uring_sqe {} 11 | 12 | /// Newtype wrapper over a raw sqe. 13 | pub(crate) struct Sqe(pub(crate) io_uring_sqe); 14 | 15 | impl fmt::Debug for Sqe { 16 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { 17 | f.debug_struct("Sqe").finish() 18 | } 19 | } 20 | 21 | impl Sqe { 22 | /// Construct a new sqe. 23 | pub(crate) fn new(inner: io_uring_sqe) -> Self { 24 | Self(inner) 25 | } 26 | 27 | /// Return the key to the `user_data` stored in slab. 28 | pub(crate) fn user_data(&self) -> u64 { 29 | self.0.user_data 30 | } 31 | } 32 | 33 | #[cfg(test)] 34 | mod tests { 35 | #![allow(clippy::undocumented_unsafe_blocks)] 36 | use super::*; 37 | #[test] 38 | fn test_user_data() { 39 | let user_data = 10_u64; 40 | let mut inner: io_uring_sqe = unsafe { std::mem::zeroed() }; 41 | inner.user_data = user_data; 42 | 43 | let sqe: Sqe = Sqe::new(inner); 44 | assert_eq!(sqe.user_data(), 10); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/vmm/src/io_uring/probe.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use vmm_sys_util::fam::{FamStruct, FamStructWrapper}; 5 | use vmm_sys_util::generate_fam_struct_impl; 6 | 7 | use crate::io_uring::generated::{io_uring_probe, io_uring_probe_op}; 8 | 9 | // There is no max for the number of operations returned by probing. So we fallback to using the 10 | // number of values representable in a u8; 11 | pub(crate) const PROBE_LEN: usize = u8::MAX as usize + 1; 12 | 13 | generate_fam_struct_impl!( 14 | io_uring_probe, 15 | io_uring_probe_op, 16 | ops, 17 | u8, 18 | ops_len, 19 | PROBE_LEN 20 | ); 21 | 22 | pub(crate) type ProbeWrapper = FamStructWrapper; 23 | -------------------------------------------------------------------------------- /src/vmm/src/io_uring/queue/mmap.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use std::io::Error as IOError; 5 | use std::os::unix::io::RawFd; 6 | 7 | use vm_memory::mmap::MmapRegionError; 8 | 9 | use crate::vstate::memory::MmapRegion; 10 | 11 | #[derive(Debug, thiserror::Error, displaydoc::Display)] 12 | pub enum MmapError { 13 | /// Os: {0} 14 | Os(IOError), 15 | /// BuildMmapRegion: {0} 16 | BuildMmapRegion(MmapRegionError), 17 | } 18 | 19 | pub(crate) fn mmap(size: usize, fd: RawFd, offset: i64) -> Result { 20 | let prot = libc::PROT_READ | libc::PROT_WRITE; 21 | let flags = libc::MAP_SHARED | libc::MAP_POPULATE; 22 | 23 | // SAFETY: Safe because values are valid and we check the return value. 24 | let ptr = unsafe { libc::mmap(std::ptr::null_mut(), size, prot, flags, fd, offset) }; 25 | if (ptr as isize) < 0 { 26 | return Err(MmapError::Os(IOError::last_os_error())); 27 | } 28 | 29 | // SAFETY: Safe because the mmap did not return error. 30 | unsafe { 31 | MmapRegion::build_raw(ptr.cast::(), size, prot, flags) 32 | .map_err(MmapError::BuildMmapRegion) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /src/vmm/src/io_uring/queue/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod completion; 5 | mod mmap; 6 | pub mod submission; 7 | -------------------------------------------------------------------------------- /src/vmm/src/io_uring/restriction.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! Seccomp-like restrictions for the allowed operations on an IoUring instance. 5 | //! 6 | //! One can configure the restrictions to only allow certain operations and/or allow only ops on 7 | //! registered files. 8 | //! If passed to the [`IoUring`] constructor, they take effect immediately and can never be 9 | //! deactivated. 10 | //! 11 | //! [`IoUring`]: ../struct.IoUring.html 12 | 13 | use std::convert::From; 14 | 15 | use crate::io_uring::generated; 16 | use crate::io_uring::operation::OpCode; 17 | 18 | /// Adds support for restricting the operations allowed by io_uring. 19 | #[derive(Debug)] 20 | pub enum Restriction { 21 | /// Allow an operation. 22 | AllowOpCode(OpCode), 23 | /// Only allow operations on pre-registered fds. 24 | RequireFixedFds, 25 | } 26 | 27 | impl From<&Restriction> for generated::io_uring_restriction { 28 | fn from(restriction: &Restriction) -> Self { 29 | use Restriction::*; 30 | 31 | // SAFETY: Safe because it only contains integer values. 32 | let mut instance: Self = unsafe { std::mem::zeroed() }; 33 | 34 | match restriction { 35 | AllowOpCode(opcode) => { 36 | instance.opcode = u16::try_from(generated::IORING_RESTRICTION_SQE_OP).unwrap(); 37 | instance.__bindgen_anon_1.sqe_op = *opcode as u8; 38 | } 39 | RequireFixedFds => { 40 | instance.opcode = 41 | u16::try_from(generated::IORING_RESTRICTION_SQE_FLAGS_REQUIRED).unwrap(); 42 | instance.__bindgen_anon_1.sqe_flags = 1 << generated::IOSQE_FIXED_FILE_BIT; 43 | } 44 | }; 45 | 46 | instance 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/vmm/src/logger/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! Crate that implements Firecracker specific functionality as far as logging and metrics 5 | //! collecting. 6 | 7 | mod logging; 8 | mod metrics; 9 | 10 | pub use log::{Level, debug, error, info, log_enabled, trace, warn}; 11 | pub use logging::{ 12 | DEFAULT_INSTANCE_ID, DEFAULT_LEVEL, INSTANCE_ID, LOGGER, LevelFilter, LevelFilterFromStrError, 13 | LoggerConfig, LoggerInitError, LoggerUpdateError, 14 | }; 15 | pub use metrics::{ 16 | IncMetric, LatencyAggregateMetrics, METRICS, MetricsError, ProcessTimeReporter, 17 | SharedIncMetric, SharedStoreMetric, StoreMetric, 18 | }; 19 | use utils::time::{ClockType, get_time_us}; 20 | 21 | /// Alias for `std::io::LineWriter`. 22 | pub type FcLineWriter = std::io::LineWriter; 23 | 24 | /// Prefix to be used in log lines for functions/modules in Firecracker 25 | /// that are not generally available. 26 | const DEV_PREVIEW_LOG_PREFIX: &str = "[DevPreview]"; 27 | 28 | /// Log a standard warning message indicating a given feature name 29 | /// is in development preview. 30 | pub fn log_dev_preview_warning(feature_name: &str, msg_opt: Option) { 31 | match msg_opt { 32 | None => warn!("{DEV_PREVIEW_LOG_PREFIX} {feature_name} is in development preview."), 33 | Some(msg) => { 34 | warn!("{DEV_PREVIEW_LOG_PREFIX} {feature_name} is in development preview - {msg}") 35 | } 36 | } 37 | } 38 | 39 | /// Helper function for updating the value of a store metric with elapsed time since some time in a 40 | /// past. 41 | pub fn update_metric_with_elapsed_time(metric: &SharedStoreMetric, start_time_us: u64) -> u64 { 42 | let delta_us = get_time_us(ClockType::Monotonic) - start_time_us; 43 | metric.store(delta_us); 44 | delta_us 45 | } 46 | -------------------------------------------------------------------------------- /src/vmm/src/snapshot/persist.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | //! Defines an abstract interface for saving/restoring a component from state. 5 | 6 | /// An abstract interface for saving/restoring a component using a specific state. 7 | pub trait Persist<'a> 8 | where 9 | Self: Sized, 10 | { 11 | /// The type of the object representing the state of the component. 12 | type State; 13 | /// The type of the object holding the constructor arguments. 14 | type ConstructorArgs; 15 | /// The type of the error that can occur while constructing the object. 16 | type Error; 17 | 18 | /// Returns the current state of the component. 19 | fn save(&self) -> Self::State; 20 | /// Constructs a component from a specified state. 21 | fn restore( 22 | constructor_args: Self::ConstructorArgs, 23 | state: &Self::State, 24 | ) -> std::result::Result; 25 | } 26 | -------------------------------------------------------------------------------- /src/vmm/src/test_utils/mock_resources/dirtying_init.tgz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/src/vmm/src/test_utils/mock_resources/dirtying_init.tgz -------------------------------------------------------------------------------- /src/vmm/src/test_utils/mock_resources/test_elf.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/src/vmm/src/test_utils/mock_resources/test_elf.bin -------------------------------------------------------------------------------- /src/vmm/src/test_utils/mock_resources/test_noisy_elf.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/src/vmm/src/test_utils/mock_resources/test_noisy_elf.bin -------------------------------------------------------------------------------- /src/vmm/src/test_utils/mock_resources/test_pe.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/firecracker-microvm/firecracker/fbf24fe7a88f521da1df4ed5fc7e30d7996bc7b2/src/vmm/src/test_utils/mock_resources/test_pe.bin -------------------------------------------------------------------------------- /src/vmm/src/utils/net/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | // 4 | // Portions Copyright 2017 The Chromium OS Authors. All rights reserved. 5 | // Use of this source code is governed by a BSD-style license that can be 6 | // found in the THIRD-PARTY file. 7 | 8 | #![warn(missing_docs)] 9 | //! # Network-related utilities 10 | //! 11 | //! Provides tools for representing and handling network related concepts like MAC addresses and 12 | //! network interfaces. 13 | 14 | /// Provides IPv4 address utility methods. 15 | pub mod ipv4addr; 16 | pub mod mac; 17 | -------------------------------------------------------------------------------- /src/vmm/src/utils/signal.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use libc::c_int; 5 | pub use vmm_sys_util::signal::*; 6 | 7 | // SAFETY: these are valid libc functions 8 | unsafe extern "C" { 9 | // SAFETY: Function has no invariants that can be broken. 10 | safe fn __libc_current_sigrtmin() -> c_int; 11 | 12 | // SAFETY: Function has no invariants that can be broken. 13 | safe fn __libc_current_sigrtmax() -> c_int; 14 | } 15 | 16 | /// Sigrtmin 17 | pub fn sigrtmin() -> c_int { 18 | __libc_current_sigrtmin() 19 | } 20 | 21 | /// Sigrtmax 22 | pub fn sigrtmax() -> c_int { 23 | __libc_current_sigrtmax() 24 | } 25 | -------------------------------------------------------------------------------- /src/vmm/src/vmm_config/instance_info.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | use std::fmt::{self, Display, Formatter}; 4 | 5 | use serde::{Serialize, ser}; 6 | 7 | /// Enumerates microVM runtime states. 8 | #[derive(Clone, Debug, Default, PartialEq, Eq)] 9 | pub enum VmState { 10 | /// Vm not started (yet) 11 | #[default] 12 | NotStarted, 13 | /// Vm is Paused 14 | Paused, 15 | /// Vm is running 16 | Running, 17 | } 18 | 19 | impl Display for VmState { 20 | fn fmt(&self, f: &mut Formatter) -> fmt::Result { 21 | match *self { 22 | VmState::NotStarted => write!(f, "Not started"), 23 | VmState::Paused => write!(f, "Paused"), 24 | VmState::Running => write!(f, "Running"), 25 | } 26 | } 27 | } 28 | 29 | impl ser::Serialize for VmState { 30 | fn serialize(&self, serializer: S) -> Result 31 | where 32 | S: ser::Serializer, 33 | { 34 | self.to_string().serialize(serializer) 35 | } 36 | } 37 | 38 | /// Serializable struct that contains general information about the microVM. 39 | #[derive(Clone, Debug, Default, PartialEq, Eq, Serialize)] 40 | pub struct InstanceInfo { 41 | /// The ID of the microVM. 42 | pub id: String, 43 | /// Whether the microVM is not started/running/paused. 44 | pub state: VmState, 45 | /// The version of the VMM that runs the microVM. 46 | pub vmm_version: String, 47 | /// The name of the application that runs the microVM. 48 | pub app_name: String, 49 | } 50 | -------------------------------------------------------------------------------- /src/vmm/src/vmm_config/mmds.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | use std::net::Ipv4Addr; 4 | 5 | use serde::{Deserialize, Serialize}; 6 | 7 | use crate::mmds::data_store; 8 | use crate::mmds::data_store::MmdsVersion; 9 | 10 | /// Keeps the MMDS configuration. 11 | #[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)] 12 | #[serde(deny_unknown_fields)] 13 | pub struct MmdsConfig { 14 | /// MMDS version. 15 | #[serde(default)] 16 | pub version: MmdsVersion, 17 | /// Network interfaces that allow forwarding packets to MMDS. 18 | pub network_interfaces: Vec, 19 | /// MMDS IPv4 configured address. 20 | pub ipv4_address: Option, 21 | } 22 | 23 | impl MmdsConfig { 24 | /// Returns the MMDS version configured. 25 | pub fn version(&self) -> MmdsVersion { 26 | self.version 27 | } 28 | 29 | /// Returns the network interfaces that accept MMDS requests. 30 | pub fn network_interfaces(&self) -> Vec { 31 | self.network_interfaces.clone() 32 | } 33 | 34 | /// Returns the MMDS IPv4 address if one was configured. 35 | /// Otherwise returns None. 36 | pub fn ipv4_addr(&self) -> Option { 37 | self.ipv4_address 38 | } 39 | } 40 | 41 | /// MMDS configuration related errors. 42 | #[rustfmt::skip] 43 | #[derive(Debug, thiserror::Error, displaydoc::Display)] 44 | pub enum MmdsConfigError { 45 | /// The list of network interface IDs that allow forwarding MMDS requests is empty. 46 | EmptyNetworkIfaceList, 47 | /// The MMDS IPv4 address is not link local. 48 | InvalidIpv4Addr, 49 | /// The list of network interface IDs provided contains at least one ID that does not correspond to any existing network interface. 50 | InvalidNetworkInterfaceId, 51 | /// The MMDS could not be configured to version {0}: {1} 52 | MmdsVersion(MmdsVersion, data_store::MmdsDatastoreError), 53 | } 54 | -------------------------------------------------------------------------------- /src/vmm/src/vstate/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | /// Module with Kvm implementation. 5 | pub mod kvm; 6 | /// Module with GuestMemory implementation. 7 | pub mod memory; 8 | /// Module with Vcpu implementation. 9 | pub mod vcpu; 10 | /// Module with Vm implementation. 11 | pub mod vm; 12 | -------------------------------------------------------------------------------- /tests/data/custom_cpu_templates/AARCH64_WITH_SVE_AND_PAC.json: -------------------------------------------------------------------------------- 1 | { 2 | "kvm_capabilities": ["170", "171", "172"], 3 | "vcpu_features": [{ "index": 0, "bitmap": "0b111xxxx" }] 4 | } 5 | -------------------------------------------------------------------------------- /tests/data/custom_cpu_templates/C3.json: -------------------------------------------------------------------------------- 1 | { 2 | "cpuid_modifiers": [ 3 | { 4 | "leaf": "0x1", 5 | "subleaf": "0x0", 6 | "flags": 0, 7 | "modifiers": [ 8 | { 9 | "register": "eax", 10 | "bitmap": "0bxxxx000000000011xx00011011100100" 11 | }, 12 | { 13 | "register": "ecx", 14 | "bitmap": "0bxxxxxxxxx0xxxxxx00x000x0xx0000xx" 15 | }, 16 | { 17 | "register": "edx", 18 | "bitmap": "0b0x0x0xxxx00xx0xxxxx1xxxx1xxxxxxx" 19 | } 20 | ] 21 | }, 22 | { 23 | "leaf": "0x7", 24 | "subleaf": "0x0", 25 | "flags": 1, 26 | "modifiers": [ 27 | { 28 | "register": "ebx", 29 | "bitmap": "0b000000000x0x000000x000x0xx0000xx" 30 | }, 31 | { 32 | "register": "ecx", 33 | "bitmap": "0bx0xxxxxxx0xxxxx0x0xx0xxxxxx0000x" 34 | }, 35 | { 36 | "register": "edx", 37 | "bitmap": "0bxxxxxxxxxxxxxxxxxxxxxxxxxxxx00xx" 38 | } 39 | ] 40 | }, 41 | { 42 | "leaf": "0xd", 43 | "subleaf": "0x0", 44 | "flags": 1, 45 | "modifiers": [ 46 | { 47 | "register": "eax", 48 | "bitmap": "0bxxxxxxxxxxxxxxxxxxxxxx0x00000xxx" 49 | } 50 | ] 51 | }, 52 | { 53 | "leaf": "0xd", 54 | "subleaf": "0x1", 55 | "flags": 1, 56 | "modifiers": [ 57 | { 58 | "register": "eax", 59 | "bitmap": "0bxxxxxxxxxxxxxxxxxxxxxxxxxxxx000x" 60 | } 61 | ] 62 | }, 63 | { 64 | "leaf": "0x80000001", 65 | "subleaf": "0x0", 66 | "flags": 0, 67 | "modifiers": [ 68 | { 69 | "register": "ecx", 70 | "bitmap": "0bxxxxxxxxxxxxxxxxxxxxxxx0xx0xxxxx" 71 | }, 72 | { 73 | "register": "edx", 74 | "bitmap": "0bxxxxx0xxxxxxxxxxxxxxxxxxxxxxxxxx" 75 | } 76 | ] 77 | } 78 | ], 79 | "msr_modifiers": [] 80 | } 81 | -------------------------------------------------------------------------------- /tests/data/custom_cpu_templates/V1N1.json: -------------------------------------------------------------------------------- 1 | { 2 | "reg_modifiers": [ 3 | { 4 | "addr": "0x603000000013c020", 5 | "bitmap": "0bxxxxxxxxxxxx0000xxxxxxxxxxxx0000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 6 | }, 7 | { 8 | "addr": "0x603000000013c030", 9 | "bitmap": "0b0000xxxx00000000xxxx000000000000xxxxxxxxxxxxxxxx0001xxxxxxxxxxxx" 10 | }, 11 | { 12 | "addr": "0x603000000013c031", 13 | "bitmap": "0bxxxxxxxx000000000000xxxxxxxxxxxxxxxxxxxx000100000000xxxxxxxx0001" 14 | }, 15 | { 16 | "addr": "0x603000000013c03a", 17 | "bitmap": "0bxxxxxxxxxxxxxxxxxxxxxxxxxxxx0000xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" 18 | } 19 | ] 20 | } 21 | -------------------------------------------------------------------------------- /tests/data/metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "latest": { 3 | "meta-data": "Lorem ipsum dolor sit amet, consectetur adipiscing elit", 4 | "user-data": "userdata 1 2 3 4" 5 | }, 6 | "2016-09-02": { 7 | "meta-data": "Lorem ipsum dolor sit amet" 8 | }, 9 | "2019-08-01": { 10 | "some-data": { 11 | "field1": "val1", 12 | "field2": [1,2,3,4] 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /tests/data/metadata_invalid.json: -------------------------------------------------------------------------------- 1 | { 2 | "latest": { 3 | "meta-data": "Lorem ipsum dolor sit amet, consectetur adipiscing elit", 4 | "user-data": "userdata 1 2 3 4" 5 | 6 | -------------------------------------------------------------------------------- /tests/data/msr/msr_reader.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # SPDX-License-Identifier: Apache-2.0 5 | 6 | # Helper script used to read MSR values from ranges known to contain MSRs. 7 | 8 | print_msr() { 9 | local msr_hex=$(printf "%#x" $1) 10 | # Record only when the given MSR index is implemented. 11 | if output=$(rdmsr $msr_hex 2>> /dev/null); then 12 | echo "$msr_hex,0x$output" 13 | fi 14 | } 15 | 16 | # Header 17 | echo "MSR_ADDR,VALUE" 18 | 19 | # 0x0..0xFFF 20 | for((msr=16#0;msr<=16#FFF;msr++)) 21 | do 22 | print_msr $msr 23 | done 24 | 25 | # 0x10000..0x10FFF 26 | for((msr=16#10000;msr<=16#10FFF;msr++)) 27 | do 28 | print_msr $msr 29 | done 30 | 31 | # 0xC0000000..0xC0011030 32 | for((msr=16#C0000000;msr<=16#C0011030;msr++)) 33 | do 34 | print_msr $msr 35 | done 36 | 37 | # extra MSRs we want to test for 38 | print_msr 0x400000000 39 | print_msr 0x2000000000 40 | print_msr 0x4000000000 41 | print_msr 0x8000000000 42 | print_msr 0x1000000000000 43 | print_msr 0x3c000000000000 44 | print_msr 0x80000000000000 45 | print_msr 0x40000000000000 46 | -------------------------------------------------------------------------------- /tests/data/msr/msr_writer.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # SPDX-License-Identifier: Apache-2.0 5 | 6 | # Helper script used to write MSR values from a text file 7 | 8 | set -eu 9 | 10 | input_file=$1 11 | 12 | if [ -z "${input_file}" ] ; then 13 | >&2 echo "Usage: ${0} " 14 | exit 1 15 | fi 16 | 17 | if [ ! -f "${input_file}" ] ; then 18 | >&2 echo "File ${input_file} does not exist" 19 | exit 1 20 | fi 21 | 22 | while read -r reg val ; do 23 | wrmsr ${reg} ${val} 24 | done < ${input_file} 25 | -------------------------------------------------------------------------------- /tests/data/msr/wrmsr_list.txt: -------------------------------------------------------------------------------- 1 | 0x1b 0xfee00c00 2 | 0x174 0x11 3 | 0x17a 0x1 4 | 0x1a0 0x0 5 | 0x250 0x1 6 | 0x258 0x1 7 | 0x259 0x1 8 | 0x268 0x1 9 | 0x269 0x1 10 | 0x26a 0x1 11 | 0x26b 0x1 12 | 0x26c 0x1 13 | 0x26d 0x1 14 | 0x26e 0x1 15 | 0x26f 0x1 16 | 0x2ff 0x1 17 | 0x402 0x1 18 | 0x403 0x1 19 | 0x406 0x1 20 | 0x407 0x1 21 | 0x40a 0x1 22 | 0x40b 0x1 23 | 0x40e 0x1 24 | 0x40f 0x1 25 | 0x412 0x1 26 | 0x413 0x1 27 | 0x416 0x1 28 | 0x417 0x1 29 | 0x41a 0x1 30 | 0x41b 0x1 31 | 0x41e 0x1 32 | 0x41f 0x1 33 | 0x422 0x1 34 | 0x423 0x1 35 | 0x426 0x1 36 | 0x427 0x1 37 | 0x42a 0x1 38 | 0x42b 0x1 39 | 0x42e 0x1 40 | 0x42f 0x1 41 | 0x432 0x1 42 | 0x433 0x1 43 | 0x436 0x1 44 | 0x437 0x1 45 | 0x43a 0x1 46 | 0x43b 0x1 47 | 0x43e 0x1 48 | 0x43f 0x1 49 | 0x442 0x1 50 | 0x443 0x1 51 | 0x446 0x1 52 | 0x447 0x1 53 | 0x44a 0x1 54 | 0x44b 0x1 55 | 0x44e 0x1 56 | 0x44f 0x1 57 | 0x452 0x1 58 | 0x453 0x1 59 | 0x456 0x1 60 | 0x457 0x1 61 | 0x45a 0x1 62 | 0x45b 0x1 63 | 0x45e 0x1 64 | 0x45f 0x1 65 | 0x462 0x1 66 | 0x463 0x1 67 | 0x466 0x1 68 | 0x467 0x1 69 | 0x46a 0x1 70 | 0x46b 0x1 71 | 0x46e 0x1 72 | 0x46f 0x1 73 | 0x472 0x1 74 | 0x473 0x1 75 | 0x476 0x1 76 | 0x477 0x1 77 | 0x47a 0x1 78 | 0x47b 0x1 79 | 0x47e 0x1 80 | 0x47f 0x1 81 | 0x808 0x1 82 | 0x80f 0x1fe 83 | 0xc0000081 0x23001000000001 84 | 0xc0000084 0x47701 85 | 0xc0000103 0x1 86 | 0xc0010015 0x40000 87 | -------------------------------------------------------------------------------- /tests/fmt.toml: -------------------------------------------------------------------------------- 1 | comment_width=100 2 | wrap_comments=true 3 | format_code_in_doc_comments=true 4 | format_strings=true 5 | imports_granularity=Module 6 | normalize_comments=true 7 | normalize_doc_attributes=true 8 | group_imports=StdExternalCrate -------------------------------------------------------------------------------- /tests/framework/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | """Are you happy pylint?""" 5 | -------------------------------------------------------------------------------- /tests/framework/defs.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Some common defines used in different modules of the testing framework.""" 4 | 5 | import platform 6 | from pathlib import Path 7 | 8 | # Firecracker's binary name 9 | FC_BINARY_NAME = "firecracker" 10 | 11 | # The Firecracker sources workspace dir 12 | FC_WORKSPACE_DIR = Path(__file__).parent.parent.parent.resolve() 13 | 14 | # Folder containing JSON seccomp filters 15 | SECCOMP_JSON_DIR = FC_WORKSPACE_DIR / "resources/seccomp" 16 | 17 | # Maximum accepted duration of an API call, in milliseconds 18 | MAX_API_CALL_DURATION_MS = 700 19 | 20 | # Default test session root directory path 21 | DEFAULT_TEST_SESSION_ROOT_PATH = "/srv" 22 | 23 | # Default test session artifacts path 24 | LOCAL_BUILD_PATH = FC_WORKSPACE_DIR / "build/" 25 | 26 | DEFAULT_BINARY_DIR = ( 27 | LOCAL_BUILD_PATH 28 | / "cargo_target" 29 | / f"{platform.machine()}-unknown-linux-musl" 30 | / "release" 31 | ) 32 | 33 | SUPPORTED_HOST_KERNELS = ["5.10", "6.1"] 34 | 35 | IMG_DIR = Path(DEFAULT_TEST_SESSION_ROOT_PATH) / "img" 36 | 37 | # fall-back to the local directory 38 | if not IMG_DIR.exists(): 39 | IMG_DIR = LOCAL_BUILD_PATH / "img" 40 | 41 | ARTIFACT_DIR = IMG_DIR / platform.machine() 42 | -------------------------------------------------------------------------------- /tests/framework/state_machine.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Defines a stream based string matcher and a generic state object.""" 4 | 5 | 6 | class MatchStaticString: 7 | """Match a static string versus input.""" 8 | 9 | # Prevent state objects from being collected by pytest. 10 | __test__ = False 11 | 12 | def __init__(self, match_string): 13 | """Initialize using specified match string.""" 14 | self._string = match_string 15 | self._input = "" 16 | 17 | def match(self, input_char) -> bool: 18 | """ 19 | Check if `_input` matches the match `_string`. 20 | 21 | Process one char at a time and build `_input` string. 22 | Preserve built `_input` if partially matches `_string`. 23 | Return True when `_input` is the same as `_string`. 24 | """ 25 | if input_char == "": 26 | return False 27 | self._input += str(input_char) 28 | if self._input == self._string[: len(self._input)]: 29 | if len(self._input) == len(self._string): 30 | self._input = "" 31 | return True 32 | return False 33 | 34 | self._input = self._input[1:] 35 | return False 36 | 37 | 38 | class TestState(MatchStaticString): 39 | """Generic test state object.""" 40 | 41 | # Prevent state objects from being collected by pytest. 42 | __test__ = False 43 | 44 | def __init__(self, match_string=""): 45 | """Initialize state fields.""" 46 | MatchStaticString.__init__(self, match_string) 47 | print("\n*** Current test state: ", str(self), end="") 48 | 49 | def handle_input(self, serial, input_char): 50 | """Handle input event and return next state.""" 51 | 52 | def __repr__(self): 53 | """Leverages the __str__ method to describe the TestState.""" 54 | return self.__str__() 55 | 56 | def __str__(self): 57 | """Return state name.""" 58 | return self.__class__.__name__ 59 | -------------------------------------------------------------------------------- /tests/framework/utils_ftrace.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Utilities for interacting with the kernel's ftrace subsystem""" 4 | import contextlib 5 | 6 | from framework.utils import check_output 7 | 8 | 9 | @contextlib.contextmanager 10 | def ftrace_events(events: str = "*:*"): 11 | """Temporarily enables the kernel's tracing functionality for the specified events 12 | 13 | Assumes that the caller is the only test executing on the host""" 14 | 15 | # We have to do system-wide tracing because inside docker we live in a pidns, but trace-cmd does not know about 16 | # this. We don't know how to translate the pidns PID to one ftrace would understand, so we use the fact that only 17 | # one vm is running at the same time, and thus we can attribute all KVM events to this one VM 18 | check_output("mount -t tracefs nodev /sys/kernel/tracing") 19 | check_output("echo > /sys/kernel/tracing/trace") # clear the trace buffers 20 | check_output(f"echo {events} > /sys/kernel/tracing/set_event") 21 | check_output("echo nop > /sys/kernel/tracing/current_tracer") 22 | check_output("echo 1 > /sys/kernel/tracing/tracing_on") 23 | 24 | try: 25 | yield 26 | finally: 27 | check_output("echo 0 > /sys/kernel/tracing/tracing_on") 28 | check_output("umount /sys/kernel/tracing") 29 | -------------------------------------------------------------------------------- /tests/framework/utils_repo.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | """Utilities to deal with the git repo.""" 5 | 6 | import subprocess 7 | from fnmatch import fnmatch 8 | from pathlib import Path 9 | 10 | 11 | def git_repo_files(root: str = ".", glob: str = "*"): 12 | """ 13 | Return a list of files in the git repo from a given path 14 | 15 | :param root: path where to look for files, defaults to the current dir 16 | :param glob: what pattern to apply to file names 17 | :return: list of found files 18 | """ 19 | files = subprocess.check_output( 20 | ["git", "ls-files", root], 21 | encoding="ascii", 22 | ).splitlines() 23 | for file in files: 24 | if fnmatch(file, glob): 25 | yield Path(file) 26 | -------------------------------------------------------------------------------- /tests/framework/vm_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "vmlinux.bin", 4 | "boot_args": "console=ttyS0 reboot=k panic=1 pci=off", 5 | "initrd_path": null 6 | }, 7 | "drives": [ 8 | { 9 | "drive_id": "rootfs", 10 | "partuuid": null, 11 | "is_root_device": true, 12 | "cache_type": "Unsafe", 13 | "is_read_only": false, 14 | "path_on_host": "bionic.rootfs.ext4", 15 | "io_engine": "Sync", 16 | "rate_limiter": null, 17 | "socket": null 18 | } 19 | ], 20 | "machine-config": { 21 | "vcpu_count": 2, 22 | "mem_size_mib": 1024, 23 | "smt": false, 24 | "track_dirty_pages": false, 25 | "huge_pages": "None" 26 | }, 27 | "cpu-config": null, 28 | "balloon": null, 29 | "network-interfaces": [], 30 | "vsock": null, 31 | "logger": null, 32 | "metrics": null, 33 | "mmds-config": null, 34 | "entropy": null 35 | } 36 | -------------------------------------------------------------------------------- /tests/framework/vm_config_cpu_template_C3.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "vmlinux.bin", 4 | "boot_args": "console=ttyS0 reboot=k panic=1 pci=off" 5 | }, 6 | "drives": [ 7 | { 8 | "drive_id": "rootfs", 9 | "path_on_host": "bionic.rootfs.ext4", 10 | "is_root_device": true, 11 | "is_read_only": false 12 | } 13 | ], 14 | "machine-config": { 15 | "vcpu_count": 2, 16 | "mem_size_mib": 1024, 17 | "cpu_template": "C3" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/framework/vm_config_missing_mem_size_mib.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "vmlinux.bin", 4 | "boot_args": "console=ttyS0 reboot=k panic=1 pci=off" 5 | }, 6 | "drives": [ 7 | { 8 | "drive_id": "rootfs", 9 | "path_on_host": "bionic.rootfs.ext4", 10 | "is_root_device": true, 11 | "is_read_only": false 12 | } 13 | ], 14 | "machine-config": { 15 | "vcpu_count": 2, 16 | "smt": false, 17 | "track_dirty_pages": false 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/framework/vm_config_missing_vcpu_count.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "vmlinux.bin", 4 | "boot_args": "console=ttyS0 reboot=k panic=1 pci=off" 5 | }, 6 | "drives": [ 7 | { 8 | "drive_id": "rootfs", 9 | "path_on_host": "bionic.rootfs.ext4", 10 | "is_root_device": true, 11 | "is_read_only": false 12 | } 13 | ], 14 | "machine-config": { 15 | "mem_size_mib": 1024, 16 | "smt": false, 17 | "track_dirty_pages": false 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tests/framework/vm_config_network.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "vmlinux.bin", 4 | "boot_args": "console=ttyS0 reboot=k panic=1 pci=off", 5 | "initrd_path": null 6 | }, 7 | "drives": [ 8 | { 9 | "drive_id": "rootfs", 10 | "path_on_host": "bionic.rootfs.ext4", 11 | "is_root_device": true, 12 | "partuuid": null, 13 | "is_read_only": false, 14 | "cache_type": "Unsafe", 15 | "io_engine": "Sync", 16 | "rate_limiter": null 17 | } 18 | ], 19 | "machine-config": { 20 | "vcpu_count": 2, 21 | "mem_size_mib": 1024, 22 | "smt": false, 23 | "track_dirty_pages": false 24 | }, 25 | "cpu-config": null, 26 | "balloon": null, 27 | "network-interfaces": [ 28 | { 29 | "iface_id": "eth0", 30 | "host_dev_name": "tap0", 31 | "guest_mac": "06:00:c0:a8:00:02", 32 | "rx_rate_limiter": null, 33 | "tx_rate_limiter": null 34 | } 35 | ], 36 | "vsock": null, 37 | "logger": null, 38 | "metrics": null, 39 | "mmds-config": null, 40 | "entropy": null 41 | } 42 | -------------------------------------------------------------------------------- /tests/framework/vm_config_smt_true.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "vmlinux.bin", 4 | "boot_args": "console=ttyS0 reboot=k panic=1 pci=off" 5 | }, 6 | "drives": [ 7 | { 8 | "drive_id": "rootfs", 9 | "path_on_host": "bionic.rootfs.ext4", 10 | "is_root_device": true, 11 | "is_read_only": false 12 | } 13 | ], 14 | "machine-config": { 15 | "vcpu_count": 2, 16 | "mem_size_mib": 1024, 17 | "smt": true 18 | } 19 | } -------------------------------------------------------------------------------- /tests/framework/vm_config_with_mmdsv1.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "vmlinux.bin", 4 | "boot_args": "console=ttyS0 reboot=k panic=1 pci=off", 5 | "initrd_path": null 6 | }, 7 | "drives": [ 8 | { 9 | "drive_id": "rootfs", 10 | "partuuid": null, 11 | "is_root_device": true, 12 | "cache_type": "Unsafe", 13 | "is_read_only": false, 14 | "path_on_host": "bionic.rootfs.ext4", 15 | "io_engine": "Sync", 16 | "rate_limiter": null, 17 | "socket": null 18 | } 19 | ], 20 | "machine-config": { 21 | "vcpu_count": 2, 22 | "mem_size_mib": 1024, 23 | "track_dirty_pages": false 24 | }, 25 | "balloon": null, 26 | "network-interfaces": [ 27 | { 28 | "iface_id": "1", 29 | "host_dev_name": "tap0", 30 | "guest_mac": "06:00:c0:a8:00:02", 31 | "rx_rate_limiter": null, 32 | "tx_rate_limiter": null 33 | } 34 | ], 35 | "vsock": null, 36 | "logger": null, 37 | "metrics": null, 38 | "mmds-config": { 39 | "network_interfaces": ["1"] 40 | }, 41 | "entropy": null 42 | } 43 | -------------------------------------------------------------------------------- /tests/framework/vm_config_with_mmdsv2.json: -------------------------------------------------------------------------------- 1 | { 2 | "boot-source": { 3 | "kernel_image_path": "vmlinux.bin", 4 | "boot_args": "console=ttyS0 reboot=k panic=1 pci=off", 5 | "initrd_path": null 6 | }, 7 | "drives": [ 8 | { 9 | "drive_id": "rootfs", 10 | "partuuid": null, 11 | "is_root_device": true, 12 | "cache_type": "Unsafe", 13 | "is_read_only": false, 14 | "path_on_host": "bionic.rootfs.ext4", 15 | "io_engine": "Sync", 16 | "rate_limiter": null, 17 | "socket": null 18 | } 19 | ], 20 | "machine-config": { 21 | "vcpu_count": 2, 22 | "mem_size_mib": 1024, 23 | "smt": false, 24 | "track_dirty_pages": false 25 | }, 26 | "balloon": null, 27 | "network-interfaces": [ 28 | { 29 | "iface_id": "1", 30 | "host_dev_name": "tap0", 31 | "guest_mac": "06:00:c0:a8:00:02", 32 | "rx_rate_limiter": null, 33 | "tx_rate_limiter": null 34 | } 35 | ], 36 | "vsock": null, 37 | "logger": null, 38 | "metrics": null, 39 | "mmds-config": { 40 | "network_interfaces": ["1"], 41 | "ipv4_address": "169.254.169.250", 42 | "version": "V2" 43 | }, 44 | "entropy": null 45 | } 46 | -------------------------------------------------------------------------------- /tests/framework/with_filelock.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | """Simple decorator so that only one process is running the decorated function 5 | at any one time. 6 | 7 | Caveat: two functions sharing the same name and using this decorator will use 8 | the same lock, which may be unintended, but safe. 9 | 10 | TBD disambiguate with the module name in that case. 11 | """ 12 | 13 | 14 | import functools 15 | import tempfile 16 | from pathlib import Path 17 | 18 | from filelock import FileLock 19 | 20 | 21 | def with_filelock(func): 22 | """Decorator so that only one process is running the decorated function at 23 | any one time. 24 | """ 25 | 26 | tmp_dir = Path(tempfile.gettempdir()) 27 | 28 | @functools.wraps(func) 29 | def wrapper(*args, **kwargs): 30 | lock_path = (tmp_dir / func.__name__).with_suffix(".lock") 31 | lock = FileLock(lock_path) 32 | with lock: 33 | return func(*args, **kwargs) 34 | 35 | return wrapper 36 | -------------------------------------------------------------------------------- /tests/host_tools/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | """Are you happy pylint?""" 5 | -------------------------------------------------------------------------------- /tests/host_tools/proc.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Utility functions for interacting with the processor.""" 4 | import re 5 | 6 | from framework import utils 7 | 8 | 9 | def proc_type(): 10 | """Obtain the model processor on a Linux system.""" 11 | cmd = "cat /proc/cpuinfo" 12 | result = utils.check_output(cmd) 13 | lines = result.stdout.strip().splitlines() 14 | for line in lines: 15 | if "model name" in line: 16 | return re.sub(".*model name.*:", "", line, count=1) 17 | 18 | cmd = "uname -m" 19 | result = utils.check_output(cmd).stdout.strip() 20 | if "aarch64" in result: 21 | return "ARM" 22 | return "" 23 | -------------------------------------------------------------------------------- /tests/host_tools/udp_offload.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """ 4 | A utility for sending a UDP message with UDP oflload enabled. 5 | 6 | Inspired by the "TUN_F_CSUM is a must" chapter 7 | in https://blog.cloudflare.com/fr-fr/virtual-networking-101-understanding-tap/ 8 | by Cloudflare. 9 | """ 10 | 11 | import socket 12 | import sys 13 | 14 | 15 | def eprint(*args, **kwargs): 16 | """Print to stderr""" 17 | print(*args, file=sys.stderr, **kwargs) 18 | 19 | 20 | # Define SOL_UDP and UDP_SEGMENT if not defined in the system headers 21 | try: 22 | from socket import SOL_UDP, UDP_SEGMENT 23 | except ImportError: 24 | SOL_UDP = 17 # Protocol number for UDP 25 | UDP_SEGMENT = 103 # Option code for UDP segmentation (non-standard) 26 | 27 | 28 | if __name__ == "__main__": 29 | # Get the IP and port from command-line arguments 30 | if len(sys.argv) != 3: 31 | eprint("Usage: python3 udp_offload.py ") 32 | sys.exit(1) 33 | 34 | ip_address = sys.argv[1] 35 | port = int(sys.argv[2]) 36 | 37 | # Create a UDP socket 38 | sockfd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 39 | 40 | # Set the UDP segmentation option (UDP_SEGMENT) to 1400 bytes 41 | OPTVAL = 1400 42 | try: 43 | sockfd.setsockopt(SOL_UDP, UDP_SEGMENT, OPTVAL) 44 | except (AttributeError, PermissionError): 45 | eprint("Unable to set UDP_SEGMENT option") 46 | sys.exit(1) 47 | 48 | # Set the destination address and port 49 | servaddr = (ip_address, port) 50 | 51 | # Send the message to the destination address 52 | MESSAGE = b"x" 53 | try: 54 | sockfd.sendto(MESSAGE, servaddr) 55 | print("Message sent successfully") 56 | except socket.error as e: 57 | eprint(f"Error sending message: {e}") 58 | sys.exit(1) 59 | 60 | sockfd.close() 61 | -------------------------------------------------------------------------------- /tests/host_tools/waitpkg.c: -------------------------------------------------------------------------------- 1 | // Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // This is a sample code to attempt to use WAITPKG (UMONITOR / UWAIT / TPAUSE 5 | // instructions). It is used to test that attemping to use it generates #UD. 6 | 7 | #include 8 | #include 9 | #include 10 | 11 | void umwait(volatile int *addr) { 12 | _umonitor((void *)addr); 13 | printf("address monitoring hardware armed\n"); 14 | uint64_t timeout = 1000000000ULL; 15 | uint32_t control = 0; 16 | uint8_t cflag = _umwait(control, timeout); 17 | printf("cflag = %d\n", cflag); 18 | } 19 | 20 | int main() { 21 | int a = 0; 22 | umwait(&a); 23 | return 0; 24 | } 25 | -------------------------------------------------------------------------------- /tests/integration_tests/build/test_clippy.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Tests ensuring codebase style compliance for Rust and Python.""" 4 | 5 | 6 | import platform 7 | 8 | import pytest 9 | 10 | from host_tools.cargo_build import cargo 11 | 12 | SUCCESS_CODE = 0 13 | MACHINE = platform.machine() 14 | TARGETS = [ 15 | "{}-unknown-linux-gnu".format(MACHINE), 16 | "{}-unknown-linux-musl".format(MACHINE), 17 | ] 18 | 19 | 20 | @pytest.mark.parametrize("target", TARGETS) 21 | def test_rust_clippy(target): 22 | """ 23 | Test that clippy does not generate any errors/warnings. 24 | """ 25 | cargo("clippy", f"--target {target} --all --profile test", "-D warnings") 26 | -------------------------------------------------------------------------------- /tests/integration_tests/build/test_dependencies.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Enforces controls over dependencies.""" 4 | 5 | from host_tools.cargo_build import cargo 6 | 7 | 8 | def test_unused_dependencies(): 9 | """ 10 | Test that there are no unused dependencies. 11 | """ 12 | cargo("udeps", "--all", nightly=True) 13 | -------------------------------------------------------------------------------- /tests/integration_tests/build/test_gdb.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """A test that ensures that firecracker builds with GDB feature enabled at integration time.""" 4 | 5 | import platform 6 | 7 | import host_tools.cargo_build as host 8 | 9 | MACHINE = platform.machine() 10 | TARGET = "{}-unknown-linux-musl".format(MACHINE) 11 | 12 | 13 | def test_gdb_compiles(): 14 | """Checks that Firecracker compiles with GDB enabled""" 15 | 16 | host.cargo("build", f"--features gdb --target {TARGET}") 17 | -------------------------------------------------------------------------------- /tests/integration_tests/build/test_seccomp_no_redundant_rules.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """A test that fails if it can definitely prove a seccomp rule redundant 4 | (although it passing does not guarantee the converse, that all rules are definitely needed). 5 | """ 6 | import platform 7 | from pathlib import Path 8 | 9 | from framework import utils 10 | from framework.static_analysis import ( 11 | determine_unneeded_seccomp_rules, 12 | find_syscalls_in_binary, 13 | load_seccomp_rules, 14 | ) 15 | 16 | 17 | def test_redundant_seccomp_rules(): 18 | """Test that fails if static analysis determines redundant seccomp rules""" 19 | arch = platform.processor() 20 | 21 | nightly_toolchain = utils.check_output( 22 | "rustup toolchain list | grep nightly" 23 | ).stdout.strip() 24 | target = f"{arch}-unknown-linux-musl" 25 | 26 | utils.check_output( 27 | f'RUSTFLAGS="-C relocation-model=static -C link-args=-no-pie" cargo +{nightly_toolchain} -Zbuild-std=panic_abort,std build --release --target {target} -p firecracker' 28 | ) 29 | 30 | found_syscalls = find_syscalls_in_binary( 31 | Path(f"../build/cargo_target/{target}/release/firecracker") 32 | ) 33 | 34 | seccomp_rules = load_seccomp_rules(Path(f"../resources/seccomp/{target}.json")) 35 | 36 | redundant_rules = determine_unneeded_seccomp_rules(seccomp_rules, found_syscalls) 37 | 38 | assert not redundant_rules, f"Found redundant seccomp rules! {redundant_rules}" 39 | -------------------------------------------------------------------------------- /tests/integration_tests/build/test_unittests.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """A test that ensures that all unit tests pass at integration time.""" 4 | 5 | import platform 6 | 7 | import pytest 8 | 9 | import host_tools.cargo_build as host # pylint:disable=import-error 10 | 11 | MACHINE = platform.machine() 12 | # Currently profiling with `aarch64-unknown-linux-musl` is unsupported (see 13 | # https://github.com/rust-lang/rustup/issues/3095#issuecomment-1280705619) therefore we profile and 14 | # run coverage with the `gnu` toolchains and run unit tests with the `musl` toolchains. 15 | TARGET = "{}-unknown-linux-musl".format(MACHINE) 16 | 17 | 18 | @pytest.mark.timeout(600) 19 | def test_unittests(test_fc_session_root_path): 20 | """ 21 | Run unit and doc tests for all supported targets. 22 | """ 23 | 24 | extra_args = f"--target {TARGET}" 25 | host.cargo_test(test_fc_session_root_path, extra_args=extra_args) 26 | host.cargo_test(test_fc_session_root_path, extra_args=extra_args + " --examples") 27 | 28 | 29 | def test_benchmarks_compile(): 30 | """Checks that all benchmarks compile""" 31 | 32 | host.cargo("bench", f"--all --no-run --target {TARGET}") 33 | -------------------------------------------------------------------------------- /tests/integration_tests/functional/conftest.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | """Imported by pytest when running tests in this directory""" 5 | 6 | import pytest 7 | 8 | from framework.artifacts import firecracker_artifacts 9 | 10 | 11 | # This fixture forces a Firecracker build, even if it doesn't get used. 12 | # By placing it here instead of the top-level conftest.py we skip the build. 13 | @pytest.fixture(params=firecracker_artifacts()) 14 | def firecracker_release(request, record_property): 15 | """Return all supported firecracker binaries.""" 16 | firecracker = request.param 17 | record_property("firecracker_release", firecracker.name) 18 | return firecracker 19 | -------------------------------------------------------------------------------- /tests/integration_tests/functional/test_api_server.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Tests scenario exercising api server functionality.""" 4 | 5 | import socket 6 | 7 | from framework.utils import check_output 8 | 9 | 10 | def test_api_socket_in_use(uvm_plain): 11 | """ 12 | Test error message when api socket is already in use. 13 | 14 | This is a very frequent scenario when Firecracker cannot 15 | start due to the socket being left open from previous runs. 16 | Check that the error message is a fixed one and that it also 17 | contains the name of the path. 18 | """ 19 | microvm = uvm_plain 20 | 21 | cmd = "mkdir {}/run".format(microvm.chroot()) 22 | check_output(cmd) 23 | 24 | sock = socket.socket(socket.AF_UNIX) 25 | sock.bind(microvm.jailer.api_socket_path()) 26 | microvm.spawn(log_level="warn") 27 | msg = "Failed to open the API socket at: /run/firecracker.socket. Check that it is not already used." 28 | microvm.check_log_message(msg) 29 | 30 | microvm.mark_killed() 31 | -------------------------------------------------------------------------------- /tests/integration_tests/functional/test_binary_size.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Tests that check if the release binary sizes fall within expected size. 4 | 5 | This is not representative of the actual memory overhead of Firecracker. 6 | 7 | A more representative test is file:../performance/test_memory_overhead.py 8 | """ 9 | 10 | import platform 11 | 12 | import pytest 13 | 14 | MACHINE = platform.machine() 15 | 16 | 17 | @pytest.mark.timeout(500) 18 | def test_firecracker_binary_size(record_property, metrics, microvm_factory): 19 | """ 20 | Test if the size of the firecracker binary is within expected ranges. 21 | """ 22 | fc_binary = microvm_factory.fc_binary_path 23 | result = fc_binary.stat().st_size 24 | record_property("firecracker_binary_size", f"{result}B") 25 | metrics.set_dimensions({"cpu_arch": MACHINE}) 26 | metrics.put_metric("firecracker_binary_size", result, unit="Bytes") 27 | 28 | 29 | @pytest.mark.timeout(500) 30 | def test_jailer_binary_size(record_property, metrics, microvm_factory): 31 | """ 32 | Test if the size of the jailer binary is within expected ranges. 33 | """ 34 | jailer_binary = microvm_factory.jailer_binary_path 35 | result = jailer_binary.stat().st_size 36 | record_property("jailer_binary_size", f"{result}B") 37 | metrics.set_dimensions({"cpu_arch": MACHINE}) 38 | metrics.put_metric("jailer_binary_size", result, unit="Bytes") 39 | -------------------------------------------------------------------------------- /tests/integration_tests/functional/test_concurrency.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Ensure multiple microVMs work correctly when spawned simultaneously.""" 4 | 5 | from concurrent.futures import ThreadPoolExecutor 6 | 7 | NO_OF_MICROVMS = 20 8 | 9 | 10 | def test_run_concurrency(microvm_factory, guest_kernel, rootfs): 11 | """ 12 | Check we can spawn multiple microvms. 13 | """ 14 | 15 | def launch1(): 16 | microvm = microvm_factory.build(guest_kernel, rootfs) 17 | microvm.time_api_requests = False # is flaky because of parallelism 18 | microvm.spawn() 19 | microvm.basic_config(vcpu_count=1, mem_size_mib=128) 20 | microvm.add_net_iface() 21 | microvm.start() 22 | 23 | with ThreadPoolExecutor(max_workers=NO_OF_MICROVMS) as tpe: 24 | for _ in range(NO_OF_MICROVMS): 25 | tpe.submit(launch1) 26 | -------------------------------------------------------------------------------- /tests/integration_tests/functional/test_cpu_all.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | """ 5 | Test all vCPUs are configured correctly and work properly. 6 | 7 | This test suite aims to catch bugs of Firecracker's vCPU configuration and 8 | CPU templates especially under multi-vCPU setup, by checking that all vCPUs 9 | are operating identically, except for the expected differences. 10 | """ 11 | 12 | import pytest 13 | 14 | # Use the maximum number of vCPUs supported by Firecracker 15 | MAX_VCPUS = 32 16 | 17 | 18 | @pytest.mark.parametrize("vcpu_count", [MAX_VCPUS]) 19 | def test_all_vcpus_online(uvm_any): 20 | """Check all vCPUs are online inside guest""" 21 | assert ( 22 | uvm_any.ssh.check_output("cat /sys/devices/system/cpu/online").stdout.strip() 23 | == f"0-{uvm_any.vcpus_count - 1}" 24 | ) 25 | 26 | 27 | @pytest.mark.parametrize("vcpu_count", [MAX_VCPUS]) 28 | def test_all_vcpus_have_same_features(uvm_any): 29 | """ 30 | Check all vCPUs have the same features inside guest. 31 | 32 | This test ensures Firecracker or CPU templates don't configure CPU features 33 | differently between vCPUs. 34 | 35 | Note that whether the shown CPU features are expected or not should be 36 | tested in (arch-specific) test_cpu_features_*.py only for vCPU 0. Thus, we 37 | only test the equivalence of all CPUs in the same guest. 38 | """ 39 | # Get a feature set for each CPU and deduplicate them. 40 | unique_feature_lists = uvm_any.ssh.check_output( 41 | 'grep -E "^(flags|Features)" /proc/cpuinfo | uniq' 42 | ).stdout.splitlines() 43 | assert len(unique_feature_lists) == 1 44 | -------------------------------------------------------------------------------- /tests/integration_tests/functional/test_dirty_pages_in_full_snapshot.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Test scenario for reseting dirty pages after making a full snapshot.""" 4 | 5 | 6 | def test_dirty_pages_after_full_snapshot(uvm_plain): 7 | """ 8 | Test if dirty pages are erased after making a full snapshot of a VM 9 | """ 10 | 11 | vm_mem_size = 128 12 | uvm = uvm_plain 13 | uvm.spawn() 14 | uvm.basic_config(mem_size_mib=vm_mem_size, track_dirty_pages=True) 15 | uvm.add_net_iface() 16 | uvm.start() 17 | 18 | snap_full = uvm.snapshot_full(vmstate_path="vmstate_full", mem_path="mem_full") 19 | snap_diff = uvm.snapshot_diff(vmstate_path="vmstate_diff", mem_path="mem_diff") 20 | snap_diff2 = uvm.snapshot_diff(vmstate_path="vmstate_diff2", mem_path="mem_diff2") 21 | 22 | # file size is the same, but the `diff` snapshot is actually a sparse file 23 | assert snap_full.mem.stat().st_size == snap_diff.mem.stat().st_size 24 | 25 | # full -> diff: full should have more things in it 26 | # Diff snapshots will contain some pages, because we always mark 27 | # pages used for virt queues as dirty. 28 | assert snap_diff.mem.stat().st_blocks < snap_full.mem.stat().st_blocks 29 | assert snap_diff2.mem.stat().st_blocks < snap_full.mem.stat().st_blocks 30 | 31 | # diff -> diff: there should be no differences 32 | assert snap_diff.mem.stat().st_blocks == snap_diff2.mem.stat().st_blocks 33 | -------------------------------------------------------------------------------- /tests/integration_tests/functional/test_error_code.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Tests scenarios for Firecracker kvm exit handling.""" 4 | 5 | import platform 6 | 7 | import pytest 8 | 9 | 10 | @pytest.mark.skipif( 11 | platform.machine() != "aarch64", 12 | reason="The error code returned on aarch64 will not be returned on x86 " 13 | "under the same conditions.", 14 | ) 15 | def test_enosys_error_code(uvm_plain): 16 | """ 17 | Test that ENOSYS error is caught and firecracker exits gracefully. 18 | """ 19 | # On aarch64 we trigger this error by running a C program that 20 | # maps a file into memory and then tries to load the content from an 21 | # offset in the file bigger than its length into a register asm volatile 22 | # ("ldr %0, [%1], 4" : "=r" (ret), "+r" (buf)); 23 | vm = uvm_plain 24 | vm.spawn() 25 | vm.memory_monitor = None 26 | vm.basic_config( 27 | vcpu_count=1, 28 | boot_args="reboot=k panic=1 pci=off init=/usr/local/bin/devmemread", 29 | ) 30 | vm.start() 31 | 32 | # Check if FC process is closed 33 | vm.mark_killed() 34 | 35 | vm.check_log_message( 36 | "Received ENOSYS error because KVM failed to emulate an instruction." 37 | ) 38 | vm.check_log_message("Vmm is stopping.") 39 | -------------------------------------------------------------------------------- /tests/integration_tests/functional/test_kernel_cmdline.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | """Test kernel commandline behavior.""" 5 | 6 | from framework.microvm import Serial 7 | 8 | 9 | def test_init_params(uvm_plain): 10 | """Correct propagation of boot args to the kernel's command line. 11 | 12 | Test that init's parameters (the ones present after "--") do not get 13 | altered or misplaced. 14 | """ 15 | vm = uvm_plain 16 | vm.help.enable_console() 17 | vm.spawn() 18 | vm.memory_monitor = None 19 | 20 | # We will override the init with /bin/cat so that we try to read the 21 | # Ubuntu version from the /etc/issue file. 22 | vm.basic_config( 23 | vcpu_count=1, 24 | boot_args="console=ttyS0 reboot=k panic=1 pci=off" 25 | " init=/bin/cat -- /etc/issue", 26 | ) 27 | 28 | vm.start() 29 | serial = Serial(vm) 30 | serial.open() 31 | # If the string does not show up, the test will fail. 32 | serial.rx(token="Ubuntu 24.04") 33 | -------------------------------------------------------------------------------- /tests/integration_tests/functional/test_kvm_ptp.py: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | """Check that the kvm_ptp device works""" 5 | 6 | import pytest 7 | 8 | 9 | def test_kvm_ptp(uvm_any_booted): 10 | """Test kvm_ptp is usable""" 11 | 12 | vm = uvm_any_booted 13 | if vm.guest_kernel_version[:2] < (6, 1): 14 | pytest.skip("Only supported in kernel 6.1 and after") 15 | 16 | _, dmesg, _ = vm.ssh.check_output("dmesg |grep -i ptp") 17 | assert "PTP clock support registered" in dmesg 18 | 19 | # wait up to 5s to see the PTP device 20 | vm.ssh.check_output("udevadm wait -t 5 /dev/ptp0") 21 | 22 | # phc_ctl[14515.127]: clock time is 1697545854.728335694 or Tue Oct 17 12:30:54 2023 23 | vm.ssh.check_output("phc_ctl /dev/ptp0 -- get") 24 | -------------------------------------------------------------------------------- /tests/integration_tests/functional/test_pvtime.py: -------------------------------------------------------------------------------- 1 | # Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | """Tests for verifying the PVTime device is enabled on aarch64.""" 5 | 6 | import pytest 7 | 8 | from framework.properties import global_props 9 | 10 | 11 | @pytest.mark.skipif( 12 | global_props.cpu_architecture != "aarch64", reason="Only run in aarch64" 13 | ) 14 | def test_guest_has_pvtime_enabled(uvm_plain): 15 | """ 16 | Check that the guest kernel has enabled PV steal time. 17 | """ 18 | vm = uvm_plain 19 | vm.spawn() 20 | vm.basic_config() 21 | vm.add_net_iface() 22 | vm.start() 23 | 24 | _, stdout, _ = vm.ssh.run("dmesg | grep 'stolen time PV'") 25 | assert ( 26 | "stolen time PV" in stdout 27 | ), "Guest kernel did not report PV steal time enabled" 28 | -------------------------------------------------------------------------------- /tests/integration_tests/functional/test_rtc.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Check the well functioning af the RTC device on aarch64 platforms.""" 4 | import platform 5 | import re 6 | 7 | import pytest 8 | 9 | from framework import utils 10 | 11 | DMESG_LOG_REGEX = r"rtc-pl031\s+(\d+).rtc: setting system clock to" 12 | 13 | 14 | @pytest.mark.skipif( 15 | platform.machine() != "aarch64", reason="RTC exists only on aarch64." 16 | ) 17 | def test_rtc(uvm_plain_any): 18 | """ 19 | Test RTC functionality on aarch64. 20 | """ 21 | vm = uvm_plain_any 22 | vm.spawn() 23 | vm.memory_monitor = None 24 | vm.basic_config() 25 | vm.add_net_iface() 26 | vm.start() 27 | # check that the kernel creates an rtcpl031 base device. 28 | _, stdout, _ = vm.ssh.run("dmesg") 29 | rtc_log = re.findall(DMESG_LOG_REGEX, stdout) 30 | assert rtc_log is not None 31 | 32 | _, stdout, _ = vm.ssh.run("stat /dev/rtc0") 33 | assert "character special file" in stdout 34 | 35 | _, host_stdout, _ = utils.check_output("date +%s") 36 | _, guest_stdout, _ = vm.ssh.run("date +%s") 37 | assert abs(int(guest_stdout) - int(host_stdout)) < 5 38 | -------------------------------------------------------------------------------- /tests/integration_tests/functional/test_shut_down.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Tests scenarios for shutting down Firecracker/VM.""" 4 | 5 | import platform 6 | 7 | from packaging import version 8 | 9 | from framework import utils 10 | 11 | 12 | def test_reboot(uvm_plain_any): 13 | """ 14 | Test reboot from guest. 15 | """ 16 | vm = uvm_plain_any 17 | vm.spawn() 18 | 19 | # We don't need to monitor the memory for this test because we are 20 | # just rebooting and the process dies before pmap gets the RSS. 21 | vm.memory_monitor = None 22 | 23 | # Set up the microVM with 4 vCPUs, 256 MiB of RAM, 0 network ifaces, and 24 | # a root file system with the rw permission. The network interfaces is 25 | # added after we get a unique MAC and IP. 26 | vm.basic_config(vcpu_count=4) 27 | vm.add_net_iface() 28 | vm.start() 29 | 30 | # Consume existing metrics 31 | lines = vm.get_all_metrics() 32 | assert len(lines) == 1 33 | # Rebooting Firecracker sends an exit event and should gracefully kill. 34 | # the instance. 35 | vm.ssh.run("reboot") 36 | 37 | vm.mark_killed() 38 | 39 | # Consume existing metrics 40 | datapoints = vm.get_all_metrics() 41 | assert len(datapoints) == 2 42 | 43 | if platform.machine() != "x86_64": 44 | message = ( 45 | "Received KVM_SYSTEM_EVENT: type: 2, event: [0]" 46 | if version.parse(utils.get_kernel_version()) >= version.parse("5.18") 47 | else "Received KVM_SYSTEM_EVENT: type: 2, event: []" 48 | ) 49 | vm.check_log_message(message) 50 | vm.check_log_message("Vmm is stopping.") 51 | 52 | # Make sure that the FC process was not killed by a seccomp fault 53 | assert datapoints[-1]["seccomp"]["num_faults"] == 0 54 | -------------------------------------------------------------------------------- /tests/integration_tests/functional/test_snapshot_editor.py: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Tests for snapshot-editor tool.""" 4 | 5 | import platform 6 | 7 | import pytest 8 | 9 | import host_tools.cargo_build as host 10 | from framework import utils 11 | 12 | PLATFORM = platform.machine() 13 | MIDR_EL1 = hex(0x603000000013C000) 14 | 15 | 16 | @pytest.mark.skipif( 17 | PLATFORM != "aarch64", 18 | reason="This is aarch64 specific test.", 19 | ) 20 | def test_remove_regs(uvm_nano, microvm_factory): 21 | """ 22 | This test verifies `remove-regs` method of `snapshot-editor`. 23 | Here we create snapshot and try to romeve MIDR_EL1 register 24 | from it. Then we try to restore uVM from the snapshot. 25 | """ 26 | 27 | vm = uvm_nano 28 | vm.add_net_iface() 29 | vm.start() 30 | 31 | snapshot = vm.snapshot_full() 32 | 33 | snap_editor = host.get_binary("snapshot-editor") 34 | 35 | # Test that MIDR_EL1 is in the snapshot 36 | cmd = [ 37 | str(snap_editor), 38 | "info-vmstate", 39 | "vcpu-states", 40 | "--vmstate-path", 41 | str(snapshot.vmstate), 42 | ] 43 | _, stdout, _ = utils.check_output(cmd) 44 | assert MIDR_EL1 in stdout 45 | 46 | # Remove MIDR_EL1 register from the snapshot 47 | cmd = [ 48 | str(snap_editor), 49 | "edit-vmstate", 50 | "remove-regs", 51 | "--vmstate-path", 52 | str(snapshot.vmstate), 53 | "--output-path", 54 | str(snapshot.vmstate), 55 | str(MIDR_EL1), 56 | ] 57 | utils.check_output(cmd) 58 | 59 | # Test that MIDR_EL1 is not in the snapshot 60 | cmd = [ 61 | str(snap_editor), 62 | "info-vmstate", 63 | "vcpu-states", 64 | "--vmstate-path", 65 | str(snapshot.vmstate), 66 | ] 67 | _, stdout, _ = utils.check_output(cmd) 68 | assert MIDR_EL1 not in stdout 69 | 70 | # test that we can restore from a snapshot 71 | _ = microvm_factory.build_from_snapshot(snapshot) 72 | -------------------------------------------------------------------------------- /tests/integration_tests/performance/test_initrd.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Tests for initrd.""" 4 | import pytest 5 | 6 | from framework.microvm import HugePagesConfig, Serial 7 | 8 | INITRD_FILESYSTEM = "rootfs" 9 | 10 | 11 | @pytest.fixture 12 | def uvm_with_initrd(microvm_factory, guest_kernel, record_property, artifact_dir): 13 | """ 14 | See file:../docs/initrd.md 15 | """ 16 | fs = artifact_dir / "initramfs.cpio" 17 | record_property("rootfs", fs.name) 18 | uvm = microvm_factory.build(guest_kernel) 19 | uvm.initrd_file = fs 20 | yield uvm 21 | 22 | 23 | @pytest.mark.parametrize("huge_pages", HugePagesConfig) 24 | def test_microvm_initrd_with_serial(uvm_with_initrd, huge_pages): 25 | """ 26 | Test that a boot using initrd successfully loads the root filesystem. 27 | """ 28 | vm = uvm_with_initrd 29 | vm.help.enable_console() 30 | vm.spawn() 31 | vm.memory_monitor = None 32 | 33 | vm.basic_config( 34 | add_root_device=False, 35 | vcpu_count=1, 36 | boot_args="console=ttyS0 reboot=k panic=1 pci=off", 37 | use_initrd=True, 38 | huge_pages=huge_pages, 39 | ) 40 | 41 | vm.start() 42 | serial = Serial(vm) 43 | serial.open() 44 | serial.rx(token="# ") 45 | serial.tx("mount |grep rootfs") 46 | serial.rx(token=f"rootfs on / type {INITRD_FILESYSTEM}") 47 | -------------------------------------------------------------------------------- /tests/integration_tests/security/conftest.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | """Fixtures for security tests""" 5 | 6 | import json 7 | from pathlib import Path 8 | 9 | import pytest 10 | 11 | from host_tools.cargo_build import run_seccompiler_bin 12 | 13 | 14 | @pytest.fixture() 15 | def seccompiler(tmp_path): 16 | "A seccompiler helper fixture" 17 | 18 | class Seccompiler: 19 | "A seccompiler helper class" 20 | 21 | def compile(self, data: dict, basic=False) -> Path: 22 | "Use seccompiler-bin to compile a filter from a dict" 23 | inp = tmp_path / "input.json" 24 | inp.write_text(json.dumps(data)) 25 | bpf = tmp_path / "output.bpfmap" 26 | run_seccompiler_bin(bpf_path=bpf, json_path=inp, basic=basic) 27 | return bpf 28 | 29 | return Seccompiler() 30 | -------------------------------------------------------------------------------- /tests/integration_tests/security/test_nv.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | """Tests ensuring nested virtualization is not present when using CPU templates. 5 | 6 | We have tests that ensure CPU templates provide a consistent set of features in 7 | the guest: 8 | 9 | - file:../functional/test_cpu_features.py 10 | - file:../functional/test_feat_parity.py 11 | - Commit: 681e781f999e3390b6d46422a3c7b1a7e36e1b24 12 | 13 | These already include the absence of VMX/SVM in the guest. 14 | 15 | This test is a safety-net to make the test explicit and catch cases where we 16 | start providing the feature by mistake. 17 | """ 18 | 19 | 20 | def test_no_nested_virtualization(uvm_any_booted): 21 | """Validate that guests don't have Nested Virtualization enabled.""" 22 | uvm_any_booted.ssh.check_output("[ ! -e /dev/kvm ]") 23 | -------------------------------------------------------------------------------- /tests/integration_tests/security/test_sec_audit.py: -------------------------------------------------------------------------------- 1 | # Copyright 2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Tests ensuring security vulnerabilities are not present in dependencies.""" 4 | import json 5 | 6 | import pytest 7 | 8 | from framework.ab_test import ( 9 | git_ab_test_host_command_if_pr, 10 | set_did_not_grow_comparator, 11 | ) 12 | from framework.utils import CommandReturn 13 | from framework.utils_cpuid import CpuVendor, get_cpu_vendor 14 | 15 | 16 | @pytest.mark.skipif( 17 | get_cpu_vendor() != CpuVendor.INTEL, 18 | reason="The audit is based on cargo.lock which is identical on all platforms", 19 | ) 20 | def test_cargo_audit(): 21 | """ 22 | Run cargo audit to check for crates with security vulnerabilities. 23 | """ 24 | 25 | def set_of_vulnerabilities(output: CommandReturn): 26 | output = json.loads(output.stdout) 27 | 28 | return set( 29 | frozenset(vulnerability) 30 | for vulnerability in output["vulnerabilities"]["list"] 31 | ).union( 32 | frozenset(warning) 33 | for warning_kind, warnings in output["warnings"].items() 34 | for warning in warnings 35 | ) 36 | 37 | git_ab_test_host_command_if_pr( 38 | "cargo audit --deny warnings -q --json", 39 | comparator=set_did_not_grow_comparator(set_of_vulnerabilities), 40 | ) 41 | -------------------------------------------------------------------------------- /tests/integration_tests/style/test_gitlint.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Tests ensuring desired style for commit messages.""" 4 | 5 | import os 6 | 7 | from framework import utils 8 | from framework.ab_test import DEFAULT_A_REVISION 9 | 10 | 11 | def test_gitlint(): 12 | """ 13 | Test that all commit messages pass the gitlint rules. 14 | """ 15 | os.environ["LC_ALL"] = "C.UTF-8" 16 | os.environ["LANG"] = "C.UTF-8" 17 | 18 | rc, _, stderr = utils.run_cmd( 19 | f"gitlint --commits origin/{DEFAULT_A_REVISION}..HEAD -C ../.gitlint --extra-path framework/gitlint_rules.py", 20 | ) 21 | assert rc == 0, "Commit message violates gitlint rules: {}".format(stderr) 22 | -------------------------------------------------------------------------------- /tests/integration_tests/style/test_markdown.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Tests for markdown style checks.""" 4 | 5 | import re 6 | 7 | from framework import utils, utils_repo 8 | 9 | 10 | def test_markdown_style(): 11 | """ 12 | Test that markdown files adhere to the style rules. 13 | """ 14 | # Get all *.md files from the project 15 | md_files = list(utils_repo.git_repo_files(root="..", glob="*.md")) 16 | 17 | # Assert if somehow no markdown files were found. 18 | assert len(md_files) != 0 19 | 20 | needs_format = False 21 | 22 | # Run commands 23 | for md_file in md_files: 24 | rc, output, _ = utils.run_cmd( 25 | f"bash -c 'diff -u --color {md_file} <(mdformat - < {md_file})'", 26 | ) 27 | if rc != 0: 28 | print(output) 29 | needs_format = True 30 | 31 | assert ( 32 | not needs_format 33 | ), "Some markdown files need formatting. Either run `./tools/devtool sh mdformat .` in the repository root, or apply the above diffs manually." 34 | 35 | 36 | def test_markdown_internal_links(): 37 | """Make sure markdown internal links work""" 38 | 39 | for md_file in utils_repo.git_repo_files(root="..", glob="*.md"): 40 | txt = md_file.read_text(encoding="utf-8") 41 | for link in re.findall(r"\[.+?\]\((?P.+?)\)", txt, re.DOTALL): 42 | if not re.match("(mailto:|https?://)", link): 43 | # internal link, ignore anchors (#) and query (?) 44 | parts = link.split("#", maxsplit=1) 45 | parts = parts[0].split("?", maxsplit=1) 46 | path = md_file.parent / parts[0] 47 | assert path.exists(), f"{md_file} {link} {path}" 48 | -------------------------------------------------------------------------------- /tests/integration_tests/style/test_python.py: -------------------------------------------------------------------------------- 1 | # Copyright 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Tests ensuring codebase style compliance for Python.""" 4 | 5 | import sys 6 | from subprocess import run 7 | 8 | import pytest 9 | 10 | 11 | @pytest.mark.parametrize("formatter", ["black --config tests/pyproject.toml", "isort"]) 12 | def test_python_style(formatter): 13 | """ 14 | Test that python code passes `formatter` 15 | """ 16 | run( 17 | f"{formatter} --check --diff tests tools .buildkite", 18 | stdout=sys.stdout, 19 | stderr=sys.stderr, 20 | shell=True, 21 | cwd="..", 22 | check=True, 23 | ) 24 | 25 | 26 | def test_python_pylint(): 27 | """ 28 | Test that python code passes linter checks. 29 | """ 30 | # List of linter commands that should be executed for each file 31 | linter_cmd = "pylint --rcfile tests/pyproject.toml --output-format=colorized tests/ tools/ .buildkite/*.py" 32 | run( 33 | linter_cmd, 34 | # we let pytest capture stdout/stderr for us 35 | stdout=sys.stdout, 36 | stderr=sys.stderr, 37 | shell=True, 38 | cwd="..", 39 | check=True, 40 | ) 41 | -------------------------------------------------------------------------------- /tests/integration_tests/style/test_repo.py: -------------------------------------------------------------------------------- 1 | # Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | 4 | """Tests enforcing git repository structure""" 5 | 6 | import re 7 | import subprocess 8 | from pathlib import Path 9 | 10 | import yaml 11 | 12 | from framework import utils_repo 13 | 14 | 15 | def test_repo_no_spaces_in_paths(): 16 | """ 17 | Ensure there are no spaces in paths. 18 | """ 19 | # pylint: disable-next=subprocess-run-check 20 | res = subprocess.run( 21 | "git ls-files | grep '[[:space:]]'", 22 | cwd="..", 23 | capture_output=True, 24 | shell=True, 25 | ) 26 | # If grep doesn't find any, it will exit with status 1. Otherwise 0 27 | assert res.returncode == 1, "Some files have spaces:\n" + res.stdout.decode() 28 | 29 | 30 | def test_repo_validate_yaml(): 31 | """ 32 | Ensure all YAML files are valid 33 | """ 34 | 35 | for path in utils_repo.git_repo_files(root="..", glob="*.y*ml"): 36 | yaml.safe_load(path.open(encoding="utf-8")) 37 | 38 | 39 | def test_repo_validate_changelog(): 40 | """Make sure the CHANGELOG.md file follows the Keep a Changelog format""" 41 | 42 | changelog_path = Path("../CHANGELOG.md") 43 | changelog = changelog_path.read_text(encoding="utf-8").splitlines() 44 | errors = [] 45 | for lineno, line in enumerate(changelog, start=1): 46 | if line.startswith("## "): 47 | if not re.match(r"^## \[.+\]$", line): 48 | msg = "Level 2 headings (versions) should be wrapped in []" 49 | errors.append((lineno, msg, line)) 50 | if line.startswith("### "): 51 | if not re.match(r"^### (Added|Changed|Deprecated|Removed|Fixed)$", line): 52 | msg = "Unknown Level 3 heading" 53 | errors.append((lineno, msg, line)) 54 | 55 | for lineno, msg, line in errors: 56 | print(msg) 57 | print(f"\t{lineno}:{line}") 58 | assert len(errors) == 0 59 | -------------------------------------------------------------------------------- /tests/integration_tests/style/test_rust.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Tests ensuring codebase style compliance for Rust.""" 4 | 5 | from framework import utils 6 | 7 | 8 | def test_rust_order(): 9 | """Tests that `Cargo.toml` dependencies are alphabetically ordered.""" 10 | 11 | # Runs `cargo-sort` with the current working directory (`cwd`) as the repository root. 12 | _, _, _ = utils.check_output( 13 | cmd="cargo-sort --workspace --check --grouped", cwd=".." 14 | ) 15 | 16 | 17 | def test_rust_style(): 18 | """Test that rust code passes style checks.""" 19 | 20 | # ../src/io_uring/src/bindings.rs 21 | config = open("fmt.toml", encoding="utf-8").read().replace("\n", ",") 22 | # Check that the output is empty. 23 | _, stdout, _ = utils.check_output(f"cargo fmt --all -- --check --config {config}") 24 | 25 | # rustfmt prepends `"Diff in"` to the reported output. 26 | assert "Diff in" not in stdout 27 | -------------------------------------------------------------------------------- /tests/integration_tests/style/test_swagger.py: -------------------------------------------------------------------------------- 1 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """Tests ensuring codebase style compliance for the OpenAPI specification.""" 4 | 5 | from pathlib import Path 6 | 7 | from openapi_spec_validator import validate 8 | from openapi_spec_validator.readers import read_from_filename 9 | 10 | 11 | def validate_swagger(swagger_spec): 12 | """Fail if OpenAPI spec is not followed.""" 13 | spec_dict, _ = read_from_filename(swagger_spec) 14 | validate(spec_dict) 15 | 16 | 17 | def test_firecracker_swagger(): 18 | """ 19 | Test that Firecracker swagger specification is valid. 20 | """ 21 | swagger_spec = Path("../src/firecracker/swagger/firecracker.yaml") 22 | validate_swagger(swagger_spec) 23 | -------------------------------------------------------------------------------- /tests/integration_tests/test_kani.py: -------------------------------------------------------------------------------- 1 | # Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 2 | # SPDX-License-Identifier: Apache-2.0 3 | """ 4 | Proofs ensuring memory safety properties, user-defined assertions, 5 | absence of panics and some types of unexpected behavior (e.g., arithmetic overflows). 6 | """ 7 | import os 8 | import platform 9 | 10 | import pytest 11 | 12 | from framework import utils 13 | 14 | PLATFORM = platform.machine() 15 | 16 | TIMEOUT = 3600 17 | 18 | 19 | # The `check_output` timeout will always fire before this one, but we need to 20 | # set a timeout here to override the default pytest timeout of 180s. 21 | @pytest.mark.timeout(TIMEOUT) 22 | @pytest.mark.skipif( 23 | os.environ.get("BUILDKITE") != "true", 24 | reason="Kani's memory requirements likely cannot be satisfied locally", 25 | ) 26 | def test_kani(results_dir): 27 | """ 28 | Test all Kani proof harnesses. 29 | """ 30 | # -Z stubbing is required to enable the stubbing feature 31 | # -Z function-contracts is required to enable the function contracts feature 32 | # -Z restrict-vtable is required for some virtio queue proofs, which go out of memory otherwise 33 | # -j enables kani harnesses to be verified in parallel (required to keep CI time low) 34 | # --output-format terse is required by -j 35 | # -Z unstable-options is needed to enable the other `-Z` flags 36 | _, stdout, _ = utils.check_output( 37 | "cargo kani -Z unstable-options -Z stubbing -Z function-contracts -Z restrict-vtable -j --output-format terse", 38 | timeout=TIMEOUT, 39 | ) 40 | 41 | (results_dir / "kani_log").write_text(stdout, encoding="utf-8") 42 | -------------------------------------------------------------------------------- /tests/pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | ; Omit verbose tracebacks, since they tend to pollute the output. 3 | addopts = 4 | --tb=short 5 | -vv 6 | --durations=10 7 | --showlocals 8 | -m 'not nonci and not no_block_pr' 9 | --json-report --json-report-file=../test_results/test-report.json 10 | 11 | markers = 12 | no_block_pr: tests whose failure does not block PR merging. 13 | nonci: mark test as nonci. 14 | 15 | ; Overwrite the default norecursedirs, which includes 'build'. 16 | norecursedirs = .* 17 | 18 | ; Default timeout for tests. can be overwritten at finer grained levels. 19 | timeout = 300 20 | 21 | ; Set the cache dir location to our build dir, so we don't litter the source 22 | ; tree. 23 | cache_dir = ../build/pytest_cache 24 | 25 | ; Set logger format and level 26 | log_level = INFO 27 | log_format = %(asctime)s.%(msecs)03d %(name)s: %(levelname)s %(message)s 28 | 29 | log_cli_level = ERROR 30 | log_cli = true 31 | 32 | ; make those errors, not warnings 33 | filterwarnings = 34 | error::pytest.PytestUnraisableExceptionWarning 35 | error::pytest.PytestUnhandledThreadExceptionWarning 36 | -------------------------------------------------------------------------------- /tools/bindgen-patches/0001-change-c_char-to-c_uchar-in-ifrn_name.patch: -------------------------------------------------------------------------------- 1 | diff --git a/src/vmm/src/devices/virtio/net/generated/iff.rs b/src/vmm/src/devices/virtio/net/generated/iff.rs 2 | index 04e38396..54111c6b 100644 3 | --- a/src/vmm/src/devices/virtio/net/generated/iff.rs 4 | +++ b/src/vmm/src/devices/virtio/net/generated/iff.rs 5 | @@ -325,7 +325,7 @@ 6 | #[repr(C)] 7 | #[derive(Copy, Clone)] 8 | pub union ifreq__bindgen_ty_1 { 9 | - pub ifrn_name: [::std::os::raw::c_char; 16usize], 10 | + pub ifrn_name: [::std::os::raw::c_uchar; 16usize], 11 | } 12 | #[allow(clippy::unnecessary_operation, clippy::identity_op)] 13 | const _: () = { 14 | -- 15 | 2.40.1 16 | 17 | -------------------------------------------------------------------------------- /tools/bump-version.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # SPDX-License-Identifier: Apache-2.0 5 | 6 | set -eu -o pipefail 7 | shopt -s lastpipe 8 | 9 | FC_TOOLS_DIR=$(dirname $(realpath $0)) 10 | source "$FC_TOOLS_DIR/functions" 11 | FC_ROOT_DIR=$FC_TOOLS_DIR/.. 12 | 13 | 14 | if [ $# -ne 1 ]; then 15 | cat < 17 | 18 | Example: $0 1.4.0-dev 19 | 20 | Bump Firecracker release version: 21 | 1. Updates Cargo.toml / Cargo.lock 22 | EOF 23 | exit 1 24 | fi 25 | version=$1 26 | 27 | 28 | # Get current version from the swagger spec. 29 | prev_ver=$(get_swagger_version) 30 | 31 | say "Updating from $prev_ver to $version ..." 32 | # Update version in files. 33 | files_to_change=( 34 | "$FC_ROOT_DIR/src/firecracker/swagger/firecracker.yaml" 35 | "$FC_ROOT_DIR/src/firecracker/Cargo.toml" 36 | "$FC_ROOT_DIR/src/jailer/Cargo.toml" 37 | "$FC_ROOT_DIR/src/rebase-snap/Cargo.toml" 38 | "$FC_ROOT_DIR/src/seccompiler/Cargo.toml" 39 | "$FC_ROOT_DIR/src/cpu-template-helper/Cargo.toml" 40 | "$FC_ROOT_DIR/src/snapshot-editor/Cargo.toml" 41 | ) 42 | say "Updating source files:" 43 | for file in "${files_to_change[@]}"; do 44 | say "- $file" 45 | if [[ "$file" =~ .+\.toml$ ]]; then 46 | # For TOML 47 | sed -i "s/^version = \"$prev_ver\"/version = \"$version\"/" "$file" 48 | elif [[ "$file" =~ .+\.yaml$ ]]; then 49 | # For YAML 50 | sed -i "s/version: $prev_ver/version: $version/" "$file" 51 | else 52 | echo "ERROR: Unrecognized file '$file'" 53 | exit 1 54 | fi 55 | done 56 | 57 | # Run `cargo check` to update firecracker and jailer versions in all 58 | # `Cargo.lock`. 59 | # NOTE: This will break if it finds paths with spaces in them 60 | find . -path ./build -prune -o -name Cargo.lock -print |while read -r cargo_lock; do 61 | say "Updating $cargo_lock ..." 62 | (cd "$(dirname "$cargo_lock")"; cargo check) 63 | done 64 | -------------------------------------------------------------------------------- /tools/devctr/ctr_gitconfig: -------------------------------------------------------------------------------- 1 | # Add the root firecracker git folder as a safe directory in .gitconfig. 2 | # Firecracker root git folder in the container is 3 | # bind-mounted to a folder on the host which is mapped to a 4 | # user that is different from the user which runs the integ tests. 5 | # This difference in ownership is validated against by git. 6 | # https://github.blog/2022-04-12-git-security-vulnerability-announced/ 7 | 8 | [safe] 9 | directory = * 10 | -------------------------------------------------------------------------------- /tools/devctr/pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "tool.poetry" 3 | version = "0.1.0" 4 | description = "Firecracker python dependencies" 5 | authors = ["Your Name "] 6 | package-mode = false 7 | 8 | [tool.poetry.dependencies] 9 | aws-embedded-metrics = "^3.1.0" 10 | black = "^24.3.0" 11 | # Gitlint locks this to 8.1.3. Lock from our side too to prevent different versions 12 | click = "8.1.3" 13 | filelock = "^3.13.4" 14 | gitlint = "^0.19.1" 15 | ipython = "^8.15.0" 16 | isort = "^5.12.0" 17 | mdformat = "^0.7.17" 18 | mdformat-gfm = "^0.3.5" 19 | mdformat-footnote = "^0.1.1" 20 | mdformat-frontmatter = "^2.0.8" 21 | openapi-spec-validator = "^0.7.1" 22 | psutil = "^6.0.0" 23 | pylint = "^3" 24 | pytest = "^8" 25 | pytest-json-report = "^1.5.0" 26 | pytest-rerunfailures = "^14" 27 | pytest-repeat = "^0.9.4" 28 | pytest-timeout = "^2.3.1" 29 | pytest-xdist = "^3.5" 30 | python = "^3.10.0" 31 | PyYAML = "^6.0" 32 | requests = "^2.32.2" 33 | requests-unixsocket2 = "^0.4.0" 34 | scipy = "^1.11.2" 35 | setproctitle = "^1.3.2" 36 | tenacity = "^8.2.2" 37 | 38 | 39 | [tool.poetry.group.dev.dependencies] 40 | 41 | [build-system] 42 | requires = ["poetry-core>=1.0.0"] 43 | build-backend = "poetry.core.masonry.api" 44 | -------------------------------------------------------------------------------- /tools/release-notes.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | # pylint:disable=invalid-name 6 | 7 | """Print changelog of specified version with markdown stripped""" 8 | 9 | import sys 10 | from pathlib import Path 11 | 12 | if __name__ == "__main__": 13 | cur_version = sys.argv[1] 14 | 15 | with Path(__file__).parent.joinpath("../CHANGELOG.md").open(encoding="UTF-8") as f: 16 | changelog_lines = f.readlines() 17 | 18 | # Skip first 7 lines because they contain the "keep a changelog" metadata 19 | changelog_lines = changelog_lines[7:] 20 | 21 | iterator = iter(changelog_lines) 22 | 23 | for line in iterator: 24 | if line.startswith(f"## [{cur_version}]"): 25 | break 26 | else: 27 | print(f"Could not find changelog entry for version {cur_version}!") 28 | sys.exit(1) 29 | 30 | for line in iterator: 31 | if line.startswith("## ["): 32 | break 33 | 34 | if line.startswith("#"): 35 | line = line.lstrip("#").lstrip() 36 | 37 | if line.startswith("-"): 38 | line = line.replace("-", "*", 1) 39 | 40 | print(line, end="") 41 | -------------------------------------------------------------------------------- /tools/release-tag.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2022 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # SPDX-License-Identifier: Apache-2.0 5 | 6 | set -eu -o pipefail 7 | 8 | FC_TOOLS_DIR=$(dirname $(realpath $0)) 9 | source "$FC_TOOLS_DIR/functions" 10 | FC_ROOT_DIR=$FC_TOOLS_DIR/.. 11 | 12 | # Create a tag for the specified release. 13 | # The tag text will be composed from the changelog contents enclosed between the 14 | # specified release number and the previous one. 15 | function create_local_tag { 16 | version="$1" 17 | branch="$2" 18 | 19 | say "Obtaining tag description for local tag v$version..." 20 | tag_text=$($FC_TOOLS_DIR/release-notes.py "$version") 21 | say "Tag description for v$version:" 22 | echo "$tag_text" 23 | # Create tag. 24 | git tag -a v"$version" "$branch" -m "$tag_text" || die "Could not create local tag v$version." 25 | say "Local tag v$version created." 26 | } 27 | 28 | 29 | # # # # MAIN # # # # 30 | 31 | if [ $# -ne 1 ]; then 32 | cat < 34 | 35 | Example: $0 1.1.2 36 | 37 | It will create a local git tag and push it to the upstream 38 | EOF 39 | exit 1 40 | fi 41 | version=$1 42 | validate_version "$version" 43 | 44 | LOCAL_BRANCH=$(git rev-parse --abbrev-ref HEAD) 45 | RELEASE_BRANCH=firecracker-v$(echo "$version" |cut -d. -f-2) 46 | UPSTREAM=upstream 47 | UPSTREAM_URL=$(git remote get-url $UPSTREAM) 48 | check_local_branch_is_release_branch 49 | 50 | # Start by creating a local tag and associate to it a description. 51 | say "Creating local tag..." 52 | create_local_tag "$version" "$LOCAL_BRANCH" 53 | 54 | # pretty print a warning 55 | function warn { 56 | # reset reverse yellow 57 | echo "$(SGR 0 7 33)$*$(SGR 0)" 58 | } 59 | 60 | warn "!WARNING! The next step will modify upstream: $UPSTREAM_URL by running:" 61 | echo " git push $UPSTREAM v$version" 62 | echo " git push $UPSTREAM $RELEASE_BRANCH" 63 | get_user_confirmation || die "Cancelling tag push" 64 | git push --atomic $UPSTREAM "v$version" 65 | git push --atomic $UPSTREAM "$RELEASE_BRANCH" 66 | -------------------------------------------------------------------------------- /tools/setup-ci-artifacts.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Copyright 2024 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | # fail if we encounter an error, uninitialized variable or a pipe breaks 6 | set -eu -o pipefail 7 | 8 | TOOLS_DIR=$(dirname $0) 9 | source "$TOOLS_DIR/functions" 10 | 11 | say "Setup CI artifacts" 12 | cd build/img/$(uname -m) 13 | 14 | say "Fix executable permissions" 15 | find "firecracker" -type f |xargs chmod -c 755 16 | 17 | say "Generate SSH key to connect from host" 18 | if [ ! -s id_rsa ]; then 19 | ssh-keygen -f id_rsa -N "" 20 | fi 21 | 22 | for SQUASHFS in *.squashfs; do 23 | say "Include SSH key in $SQUASHFS" 24 | RSA=$(basename $SQUASHFS .squashfs).id_rsa 25 | EXT4=$(basename $SQUASHFS .squashfs).ext4 26 | [ -s $SQUASHFS.orig ] && continue 27 | unsquashfs $SQUASHFS 28 | mkdir -pv squashfs-root/root/.ssh 29 | # copy the SSH key into the rootfs 30 | if [ ! -s $RSA ]; then 31 | # append SSH key to the squashfs image 32 | cp -v id_rsa.pub squashfs-root/root/.ssh/authorized_keys 33 | cp -v id_rsa $RSA 34 | fi 35 | # re-squash 36 | mv -v $SQUASHFS $SQUASHFS.orig 37 | mksquashfs squashfs-root $SQUASHFS -all-root -noappend -comp zstd 38 | 39 | # Create rw ext4 image from ro squashfs 40 | [ -f $EXT4 ] && continue 41 | say "Converting $SQUASHFS to $EXT4" 42 | truncate -s 400M $EXT4 43 | mkfs.ext4 -F $EXT4 -d squashfs-root 44 | rm -rf squashfs-root 45 | done 46 | 47 | say "Uncompress debuginfo files" 48 | find . -name "*.debug.gz" -print0 | xargs -P4 -0 -t -n1 gunzip 49 | -------------------------------------------------------------------------------- /tools/test-popular-containers/fcnet.start: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | # Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | # SPDX-License-Identifier: Apache-2.0 4 | mount -t sysfs sysfs /sys 5 | devs=$(ls /sys/class/net | grep -v lo) 6 | for dev in $devs; do 7 | ip=$(printf "%d.%d.%d.%d" $(echo -n 0x; cut -d: -f3- -O ' 0x' /sys/class/net/$dev/address)) 8 | ip addr add "$ip/30" dev $dev 9 | ip link set $dev up 10 | done 11 | -------------------------------------------------------------------------------- /tools/test-popular-containers/test-docker-rootfs.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 3 | # SPDX-License-Identifier: Apache-2.0 4 | 5 | # pylint:disable=invalid-name 6 | 7 | """ 8 | Test all the ext4 rootfs in the current directory 9 | """ 10 | 11 | import os 12 | import sys 13 | from pathlib import Path 14 | 15 | # Hack to be able to import testing framework functions. 16 | sys.path.append(os.path.join(os.getcwd(), "tests")) 17 | 18 | # pylint: disable=wrong-import-position 19 | from framework.artifacts import kernels 20 | from framework.defs import DEFAULT_BINARY_DIR 21 | from framework.microvm import MicroVMFactory 22 | 23 | # pylint: enable=wrong-import-position 24 | 25 | kernels = list(kernels("vmlinux-*")) 26 | # Use the latest guest kernel 27 | kernel = kernels[-1] 28 | 29 | vmfcty = MicroVMFactory(DEFAULT_BINARY_DIR) 30 | # (may take a while to compile Firecracker...) 31 | 32 | for rootfs in Path(".").glob("*.ext4"): 33 | print(f">>>> Testing {rootfs}") 34 | uvm = vmfcty.build(kernel, rootfs) 35 | uvm.spawn() 36 | uvm.add_net_iface() 37 | uvm.basic_config() 38 | uvm.start() 39 | rc, stdout, stderr = uvm.ssh.run("cat /etc/issue") 40 | print(rc, stdout, stderr) 41 | -------------------------------------------------------------------------------- /tools/test.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Copyright 2023 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # SPDX-License-Identifier: Apache-2.0 5 | 6 | # fail if we encounter an error, uninitialized variable or a pipe breaks 7 | set -eu -o pipefail 8 | 9 | TOOLS_DIR=$(dirname $0) 10 | source "$TOOLS_DIR/functions" 11 | 12 | # Set our TMPDIR inside /srv, so all files created in the session end up in one 13 | # place 14 | say "Create TMPDIR in /srv" 15 | export TMPDIR=/srv/tmp 16 | mkdir -pv $TMPDIR 17 | 18 | # Some of the security tests need this (test_jail.py) 19 | # Convert the Docker created cgroup so we can create cgroup children 20 | # From https://github.com/containerd/containerd/issues/6659 21 | say "cgroups v2: enable nesting" 22 | CGROUP=/sys/fs/cgroup 23 | if [ -f $CGROUP/cgroup.controllers -a -e $CGROUP/cgroup.type ]; then 24 | # move the processes from the root group to the /init group, 25 | # otherwise writing subtree_control fails with EBUSY. 26 | # An error during moving non-existent process (i.e., "cat") is ignored. 27 | mkdir -p $CGROUP/init 28 | xargs -rn1 < $CGROUP/cgroup.procs > $CGROUP/init/cgroup.procs || : 29 | # enable controllers 30 | sed -e 's/ / +/g' -e 's/^/+/' < $CGROUP/cgroup.controllers \ 31 | > $CGROUP/cgroup.subtree_control 32 | fi 33 | 34 | say "Copy CI artifacts to /srv, so hardlinks work" 35 | cp -ruvf build/img /srv 36 | 37 | cd tests 38 | export PYTEST_ADDOPTS="${PYTEST_ADDOPTS:-} --pdbcls=IPython.terminal.debugger:TerminalPdb" 39 | 40 | { 41 | # disable errexit momentarily so we can capture the exit status 42 | set +e 43 | pytest "$@" 44 | ret=$? 45 | set -e 46 | } 47 | 48 | # if the tests failed and we are running in CI, print some disk usage stats 49 | # to help troubleshooting 50 | if [ $ret != 0 ] && [ "$BUILDKITE" == "true" ]; then 51 | df -ih 52 | df -h 53 | du -h / 2>/dev/null |sort -h |tail -32 54 | fi 55 | 56 | exit $ret 57 | -------------------------------------------------------------------------------- /tools/update-credits.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. 4 | # SPDX-License-Identifier: Apache-2.0 5 | 6 | set -e 7 | 8 | cd "$(dirname "$BASH_SOURCE")/.." 9 | 10 | # see also ".mailmap" for how email addresses and names are deduplicated 11 | 12 | { 13 | cat <<-'EOH' 14 | 15 | # Firecracker Credits and Thanks 16 | 17 | (This file is autogenerated using [update-credits.sh](tools/update-credits.sh).) 18 | 19 | Firecracker started with the code from the Chrome OS Virtual Machine Monitor 20 | ([crosvm](https://github.com/google/crosvm)), a VMM written in Rust with a focus 21 | on safety and security. Thanks go to: 22 | 23 | - [Zach Reizner](https://github.com/zachreizner) 24 | - [Dylan Reid](https://github.com/dgreid) 25 | - [Daniel Verkamp](https://github.com/danielverkamp) 26 | - [Stephen Barber](https://github.com/smibarber) 27 | - [Chirantan Ekbote](https://github.com/jynnantonix) 28 | - [Jason D. Clinton](https://github.com/jclinton) 29 | - Sonny Rao 30 | 31 | Contributors to the Firecracker repository: 32 | EOH 33 | echo 34 | git log --format='- %aN <%aE>' | LC_ALL=C.UTF-8 sort -uf | grep -v "dependabot" 35 | } > CREDITS.md 36 | --------------------------------------------------------------------------------