microsoft/openvmm
Publicmirrored fromhttps://github.com/microsoft/openvmmAvailable
.github/copilot-instructions.md
157lines · modecode
| 1 | # OpenVMM Repository |
| 2 | |
| 3 | OpenVMM is a modular, cross-platform Virtual Machine Monitor (VMM) written in Rust. |
| 4 | This repository is home to both OpenVMM and OpenHCL (a paravisor). |
| 5 | Documentation lives in `Guide/` and is published at https://openvmm.dev. |
| 6 | |
| 7 | ## Build & Setup |
| 8 | |
| 9 | Restore required dependencies before building for the first time: |
| 10 | ```bash |
| 11 | cargo xflowey restore-packages |
| 12 | ``` |
| 13 | |
| 14 | The project supports cross-compilation for `x86_64` and `aarch64`. |
| 15 | OpenHCL can only be built from Linux (WSL2 counts). |
| 16 | For cross-compilation from WSL2 to Windows, see |
| 17 | `Guide/src/dev_guide/getting_started/cross_compile.md` and source |
| 18 | `. ./build_support/setup_windows_cross.sh`. |
| 19 | |
| 20 | ## Git Commit Rules |
| 21 | |
| 22 | - **Never amend commits that have already been pushed.** Make new commits |
| 23 | instead. PRs are squash-merged, so a clean history is unnecessary. |
| 24 | - Rebasing onto `main` to resolve conflicts is fine, but do not use |
| 25 | `git commit --amend`, `git rebase -i`, or `git push --force` to clean |
| 26 | up history on already-pushed commits. |
| 27 | |
| 28 | ## Pre-Commit Checklist (MANDATORY) |
| 29 | |
| 30 | **You MUST run these commands before every `git commit` in this repo. |
| 31 | Do NOT commit without completing all three steps.** |
| 32 | |
| 33 | 1. `cargo clippy --all-targets -p <package-name>` — for each modified package. |
| 34 | 2. `cargo doc --no-deps -p <package-name>` — for each modified package. |
| 35 | 3. `cargo xtask fmt --fix` — fix formatting, headers, naming conventions. |
| 36 | Run this **last** because fixing clippy/doc issues may introduce |
| 37 | formatting changes that need to be cleaned up. |
| 38 | |
| 39 | If `cargo xtask fmt --fix` still fails after auto-fixes, fix the remaining |
| 40 | reported issues manually and re-run until it succeeds. Do not run individual |
| 41 | `--pass` commands afterward. |
| 42 | |
| 43 | ## Trust Boundaries & Safety |
| 44 | |
| 45 | Both OpenVMM and OpenHCL process data from untrusted sources. Code must |
| 46 | **never panic** on untrusted input. |
| 47 | |
| 48 | - **OpenVMM does not trust the guest** — code must not panic on any guest input |
| 49 | - **OpenHCL does not trust the root** — code must not panic on any root input |
| 50 | - **OpenHCL does not trust the VTL0 guest** — the attack surface is subtle and needs human review |
| 51 | |
| 52 | **Error handling across trust boundaries:** |
| 53 | - Use `thiserror` for typed error enums at library/API boundaries and |
| 54 | protocol-facing code |
| 55 | - Use `anyhow` with `.context("...")` for application-level plumbing and |
| 56 | context propagation |
| 57 | - Never `.unwrap()` or `.expect()` on data that crosses a trust boundary |
| 58 | - For protocol/hardware enums where unknown values must round-trip without |
| 59 | panicking, use the `open_enum!` macro instead of a normal Rust `enum` |
| 60 | - Rate-limit trace events that can be triggered repeatedly by guest |
| 61 | interactions — use `tracelimit::warn_ratelimited!` (or `error_ratelimited!`, |
| 62 | `info_ratelimited!`) instead of bare `tracing::warn!` etc. |
| 63 | |
| 64 | **Other safety rules:** |
| 65 | 1. Avoid `unsafe` code |
| 66 | 2. Avoid taking new external dependencies, especially those that significantly increase binary size |
| 67 | 3. Several OpenHCL crates (e.g., `minimal_rt`, `openhcl_boot`, `sidecar`, |
| 68 | `host_fdt_parser`) must support `no_std` builds. In particular, |
| 69 | `minimal_rt` and `host_fdt_parser` are unconditionally `no_std`, and |
| 70 | `openhcl_boot` and `sidecar` use `cfg_attr(minimal_rt, no_std, no_main)`. |
| 71 | Do not introduce `std`-only dependencies or APIs into code that is |
| 72 | compiled for the `minimal_rt` configuration in these crates |
| 73 | 4. Prefer `assert!` over `debug_assert!` for internal invariants — the |
| 74 | performance cost is negligible in nearly all code, and catching invariant |
| 75 | violations in release builds is more valuable. The project follows a |
| 76 | "fail fast" philosophy: crash immediately on broken invariants rather |
| 77 | than letting the process continue in an undefined state where bugs are |
| 78 | harder to diagnose. (This does not apply to untrusted input — use error |
| 79 | handling at trust boundaries, not assertions.) |
| 80 | |
| 81 | ## Testing |
| 82 | |
| 83 | Run tests with cargo-nextest using the `agent` profile, which suppresses |
| 84 | output for passing tests and only shows slow/failing tests: |
| 85 | ```bash |
| 86 | cargo nextest run --profile agent -p <package-name> |
| 87 | ``` |
| 88 | |
| 89 | **Do NOT pipe test output to `grep`, `tail`, or other filters.** The `agent` |
| 90 | profile already minimizes output. Piping hides failures and makes hangs |
| 91 | invisible. |
| 92 | |
| 93 | For VMM test validation during development, use `cargo xflowey vmm-tests-run`: |
| 94 | ```bash |
| 95 | # Run a specific test |
| 96 | cargo xflowey vmm-tests-run --filter "test(my_test_name)" --dir <output-dir> |
| 97 | ``` |
| 98 | This automatically discovers artifacts, builds dependencies, and runs tests. |
| 99 | See `Guide/src/dev_guide/tests/vmm.md` for details. |
| 100 | |
| 101 | - **Unit tests** — spread throughout crates in `#[cfg(test)]` blocks. |
| 102 | Should be fast, isolated, and not require root/administrator access. |
| 103 | Add `use test_with_tracing::test;` in test modules so that `tracing` |
| 104 | is initialized and traces appear in test output. |
| 105 | - **VMM tests** — integration tests in `vmm_tests/` using the petri |
| 106 | framework (requires additional setup). |
| 107 | - Mark tests requiring special setup with `#[ignore]`. |
| 108 | - Update `Guide/` docs when adding features or changing behavior |
| 109 | (see `.github/instructions/doc-code-sync.instructions.md` for the mapping) |
| 110 | - **CI failures** — to investigate failing CI checks on a PR, load the |
| 111 | `openvmm-ci-investigation` skill. |
| 112 | |
| 113 | ## Rust Edition |
| 114 | |
| 115 | This project uses the **Rust 2024 edition** (`edition = "2024"` in root |
| 116 | `Cargo.toml`). |
| 117 | |
| 118 | ## Common Pitfalls |
| 119 | |
| 120 | - **`guest_arch` not `target_arch`**: For guest-architecture-specific code, |
| 121 | use `cfg(guest_arch = "x86_64")` — **not** `cfg(target_arch = "x86_64")`. |
| 122 | The VMM can run guests of a different architecture than the host. Using |
| 123 | `target_arch` will fail CI. |
| 124 | - **Workspace dependencies**: All dependency versions are centralized in |
| 125 | the root `Cargo.toml`. In crate `Cargo.toml` files, use |
| 126 | `dep_name.workspace = true` — not inline version specifiers. Add new |
| 127 | dependencies to `[workspace.dependencies]` in the root first. |
| 128 | - **Pipeline YAMLs are auto-generated**: Files under `ci-flowey/` (e.g., |
| 129 | `openvmm-pr.yaml`) are generated by the flowey framework — do not |
| 130 | hand-edit them. Run `cargo xflowey regen` to regenerate. |
| 131 | - **flowey nodes**: Use `flowey::shell_cmd!` and `rt.sh` inside flowey |
| 132 | nodes — not `xshell::cmd!` or `xshell::Shell::new`. |
| 133 | |
| 134 | ## Autonomous Agent Inner Loop |
| 135 | |
| 136 | When running as a coding agent (GitHub Copilot coding agent or similar), |
| 137 | follow this validation loop **before pushing each commit**. This covers |
| 138 | the common early CI failures (including the fmt + clippy checks from job0) |
| 139 | locally, avoiding slow push-and-wait cycles. |
| 140 | |
| 141 | 1. **Identify modified packages.** For each file you changed, find the |
| 142 | crate's `Cargo.toml` and note the package name. |
| 143 | 2. **Check compilation:** `cargo check -p <package>` — fast type-check. |
| 144 | 3. **Clippy:** `cargo clippy --all-targets -p <package>` — lint. |
| 145 | 4. **Doc:** `cargo doc --no-deps -p <package>` — catch doc errors. |
| 146 | 5. **Unit tests:** `cargo nextest run --profile agent -p <package>` — run the crate's |
| 147 | tests. If nextest is not installed, use `cargo test -p <package>`. |
| 148 | 6. **Formatting:** `cargo xtask fmt --fix` — run last, since earlier |
| 149 | fixes may introduce formatting changes. |
| 150 | |
| 151 | If any step fails, fix the issue and re-run from that step. Do not push |
| 152 | until all six steps pass. |
| 153 | |
| 154 | **Cost notes:** Steps 2–5 are scoped to the modified package (`-p`), |
| 155 | so they are fast even in this large workspace. Step 6 runs workspace-wide |
| 156 | but is also fast. The full cycle typically takes under 2 minutes for |
| 157 | a single-crate change. |
| 158 | |