mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
Compare commits
66 Commits
v39.0
...
stable/v37
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4c0784f041 | ||
|
|
8632dda669 | ||
|
|
c2d3d015d8 | ||
|
|
115c455eaf | ||
|
|
259b8aa1c8 | ||
|
|
2a9978f3c0 | ||
|
|
3c4ff7de01 | ||
|
|
de6d6f2558 | ||
|
|
baf719c6ff | ||
|
|
c59c61a983 | ||
|
|
448fafd23a | ||
|
|
196a59f209 | ||
|
|
35d1998965 | ||
|
|
c5904a413e | ||
|
|
7729024451 | ||
|
|
5580dd6e6a | ||
|
|
21ea5afa0a | ||
|
|
a09d536dc1 | ||
|
|
f8a5c149eb | ||
|
|
8e6bdcbf11 | ||
|
|
93631b5e23 | ||
|
|
ade953e582 | ||
|
|
a3bd7eb9a0 | ||
|
|
b0dd4e72c5 | ||
|
|
ed1b415bad | ||
|
|
71708c9794 | ||
|
|
f58f9cf16a | ||
|
|
a7d967215f | ||
|
|
0e29fe1517 | ||
|
|
fbb648166a | ||
|
|
ea87988f93 | ||
|
|
f35d573431 | ||
|
|
a489a11ccf | ||
|
|
4f1fb3632b | ||
|
|
693e456793 | ||
|
|
8c1b112a60 | ||
|
|
26cab16830 | ||
|
|
c588138187 | ||
|
|
4b72e5a886 | ||
|
|
51febbb7fe | ||
|
|
551d36e502 | ||
|
|
6a5a2ac83d | ||
|
|
37666f842d | ||
|
|
a09d828713 | ||
|
|
67904a90fc | ||
|
|
196e653a50 | ||
|
|
355148c3d6 | ||
|
|
1dff2503a6 | ||
|
|
f4c85aef89 | ||
|
|
0131a408bf | ||
|
|
bd506500d7 | ||
|
|
80724b1662 | ||
|
|
1f6b43db49 | ||
|
|
878c2275a2 | ||
|
|
5fc018abdd | ||
|
|
690e10eef4 | ||
|
|
ea12024793 | ||
|
|
e082ed23ed | ||
|
|
d1953633e2 | ||
|
|
23f1490667 | ||
|
|
b312a970ef | ||
|
|
6e544d0a30 | ||
|
|
bc84ac4699 | ||
|
|
78f0f30751 | ||
|
|
8b0d43e2fe | ||
|
|
61430fb345 |
2
.github/workflows/audit.yaml
vendored
2
.github/workflows/audit.yaml
vendored
@@ -11,6 +11,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions-rust-lang/audit@v1
|
||||
- uses: actions-rs/audit-check@v1
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
5
.github/workflows/build.yaml
vendored
5
.github/workflows/build.yaml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
- stable
|
||||
- beta
|
||||
- nightly
|
||||
- "1.74.1"
|
||||
- "1.70"
|
||||
target:
|
||||
- x86_64-unknown-linux-gnu
|
||||
- x86_64-unknown-linux-musl
|
||||
@@ -29,10 +29,11 @@ jobs:
|
||||
run: sudo apt install -y musl-tools
|
||||
|
||||
- name: Install Rust toolchain (${{ matrix.rust }})
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
target: ${{ matrix.target }}
|
||||
override: true
|
||||
|
||||
- name: Build (default features)
|
||||
run: cargo rustc --locked --bin cloud-hypervisor -- -D warnings -D clippy::undocumented_unsafe_blocks
|
||||
|
||||
2
.github/workflows/docker-image.yaml
vendored
2
.github/workflows/docker-image.yaml
vendored
@@ -41,7 +41,7 @@ jobs:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
# generate Docker tags based on the following events/attributes
|
||||
tags: |
|
||||
type=raw,value=20240407-0
|
||||
type=raw,value={{date 'YYYYMMDD'}}-0
|
||||
type=sha
|
||||
|
||||
- name: Build and push
|
||||
|
||||
13
.github/workflows/fuzz-build.yaml
vendored
13
.github/workflows/fuzz-build.yaml
vendored
@@ -14,19 +14,18 @@ jobs:
|
||||
- nightly
|
||||
target:
|
||||
- x86_64-unknown-linux-gnu
|
||||
env:
|
||||
RUSTFLAGS: -D warnings
|
||||
steps:
|
||||
- name: Code checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Install Rust toolchain (${{ matrix.rust }})
|
||||
uses: dtolnay/rust-toolchain@stable
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: ${{ matrix.rust }}
|
||||
target: ${{ matrix.target }}
|
||||
override: true
|
||||
- name: Install Cargo fuzz
|
||||
run: cargo install cargo-fuzz
|
||||
- name: Fuzz Build
|
||||
# Temporary fix for cargo-fuzz on latest nightly: https://github.com/rust-fuzz/cargo-fuzz/issues/276
|
||||
#run: cargo install cargo-fuzz
|
||||
run: cargo install --git https://github.com/rust-fuzz/cargo-fuzz --rev b4df3e58f767b5cad8d1aa6753961003f56f3609
|
||||
- name: Cargo Fuzz Build
|
||||
run: cargo fuzz build
|
||||
- name: Fuzz Check
|
||||
run: cargo fuzz check
|
||||
|
||||
186
.github/workflows/release.yaml
vendored
186
.github/workflows/release.yaml
vendored
@@ -3,67 +3,135 @@ on: [create, merge_group]
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
|
||||
cancel-in-progress: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
jobs:
|
||||
release:
|
||||
if: (github.event_name == 'create' && github.event.ref_type == 'tag') || github.event_name == 'merge_group'
|
||||
name: Release ${{ matrix.platform.target }}
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
platform:
|
||||
- target: x86_64-unknown-linux-gnu
|
||||
args: --all --release --features mshv
|
||||
name_ch: cloud-hypervisor
|
||||
name_ch_remote: ch-remote
|
||||
- target: x86_64-unknown-linux-musl
|
||||
args: --all --release --features mshv
|
||||
name_ch: cloud-hypervisor-static
|
||||
name_ch_remote: ch-remote-static
|
||||
- target: aarch64-unknown-linux-musl
|
||||
args: --all --release
|
||||
name_ch: cloud-hypervisor-static-aarch64
|
||||
name_ch_remote: ch-remote-static-aarch64
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Code checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Install musl-gcc
|
||||
if: contains(matrix.platform.target, 'musl')
|
||||
run: sudo apt install -y musl-tools
|
||||
- name: Create release directory
|
||||
if: |
|
||||
github.event_name == 'create' && github.event.ref_type == 'tag' &&
|
||||
matrix.platform.target == 'x86_64-unknown-linux-gnu'
|
||||
run: rsync -rv --exclude=.git . ../cloud-hypervisor-${{ github.event.ref }}
|
||||
- name: Build ${{ matrix.platform.target }}
|
||||
uses: houseabsolute/actions-rust-cross@v0
|
||||
- name: Install Rust toolchain (x86_64-unknown-linux-gnu)
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: "1.70"
|
||||
target: x86_64-unknown-linux-gnu
|
||||
- name: Install Rust toolchain (x86_64-unknown-linux-musl)
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: "1.70"
|
||||
target: x86_64-unknown-linux-musl
|
||||
- name: Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
toolchain: "1.70"
|
||||
command: build
|
||||
target: ${{ matrix.platform.target }}
|
||||
args: ${{ matrix.platform.args }}
|
||||
strip: true
|
||||
toolchain: 1.74.1
|
||||
- name: Copy Release Binaries
|
||||
if: github.event_name == 'create' && github.event.ref_type == 'tag'
|
||||
shell: bash
|
||||
run: |
|
||||
cp target/${{ matrix.platform.target }}/release/cloud-hypervisor ./${{ matrix.platform.name_ch }}
|
||||
cp target/${{ matrix.platform.target }}/release/ch-remote ./${{ matrix.platform.name_ch_remote }}
|
||||
- name: Upload Release Artifacts
|
||||
if: github.event_name == 'create' && github.event.ref_type == 'tag'
|
||||
uses: actions/upload-artifact@v3
|
||||
args: --all --release --features mshv --target=x86_64-unknown-linux-gnu
|
||||
- name: Static Build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
name: Artifacts for ${{ matrix.platform.target }}
|
||||
path: |
|
||||
./${{ matrix.platform.name_ch }}
|
||||
./${{ matrix.platform.name_ch_remote }}
|
||||
toolchain: "1.70"
|
||||
command: build
|
||||
args: --all --release --features mshv --target=x86_64-unknown-linux-musl
|
||||
- name: Install Rust toolchain (aarch64-unknown-linux-musl)
|
||||
uses: actions-rs/toolchain@v1
|
||||
with:
|
||||
toolchain: "1.70"
|
||||
target: aarch64-unknown-linux-musl
|
||||
override: true
|
||||
- name: Create Release
|
||||
if: github.event_name == 'create' && github.event.ref_type == 'tag'
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.ref }}
|
||||
release_name: ${{ github.ref }}
|
||||
draft: true
|
||||
prerelease: true
|
||||
- name: Upload cloud-hypervisor
|
||||
if: github.event_name == 'create' && github.event.ref_type == 'tag'
|
||||
id: upload-release-cloud-hypervisor
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: target/x86_64-unknown-linux-gnu/release/cloud-hypervisor
|
||||
asset_name: cloud-hypervisor
|
||||
asset_content_type: application/octet-stream
|
||||
- name: Upload static cloud-hypervisor
|
||||
if: github.event_name == 'create' && github.event.ref_type == 'tag'
|
||||
id: upload-release-static-cloud-hypervisor
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: target/x86_64-unknown-linux-musl/release/cloud-hypervisor
|
||||
asset_name: cloud-hypervisor-static
|
||||
asset_content_type: application/octet-stream
|
||||
- name: Upload ch-remote
|
||||
if: github.event_name == 'create' && github.event.ref_type == 'tag'
|
||||
id: upload-release-ch-remote
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: target/x86_64-unknown-linux-gnu/release/ch-remote
|
||||
asset_name: ch-remote
|
||||
asset_content_type: application/octet-stream
|
||||
- name: Upload static-ch-remote
|
||||
if: github.event_name == 'create' && github.event.ref_type == 'tag'
|
||||
id: upload-release-static-ch-remote
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: target/x86_64-unknown-linux-musl/release/ch-remote
|
||||
asset_name: ch-remote-static
|
||||
asset_content_type: application/octet-stream
|
||||
- name: Clean build tree ahead of cross build
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
command: clean
|
||||
- name: Static Build (AArch64)
|
||||
uses: actions-rs/cargo@v1
|
||||
with:
|
||||
use-cross: true
|
||||
command: build
|
||||
args: --all --release --target=aarch64-unknown-linux-musl
|
||||
- name: Upload static AArch64 cloud-hypervisor
|
||||
if: github.event_name == 'create' && github.event.ref_type == 'tag'
|
||||
id: upload-release-static-aarch64-cloud-hypervisor
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: target/aarch64-unknown-linux-musl/release/cloud-hypervisor
|
||||
asset_name: cloud-hypervisor-static-aarch64
|
||||
asset_content_type: application/octet-stream
|
||||
- name: Upload static AArch64 ch-remote
|
||||
if: github.event_name == 'create' && github.event.ref_type == 'tag'
|
||||
id: upload-release-static-aarch64-ch-remote
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: target/aarch64-unknown-linux-musl/release/ch-remote
|
||||
asset_name: ch-remote-static-aarch64
|
||||
asset_content_type: application/octet-stream
|
||||
- name: Vendor
|
||||
if: |
|
||||
github.event_name == 'create' && github.event.ref_type == 'tag' &&
|
||||
matrix.platform.target == 'x86_64-unknown-linux-gnu'
|
||||
working-directory: ../cloud-hypervisor-${{ github.event.ref }}
|
||||
run: |
|
||||
mkdir ../vendor-cargo-home
|
||||
@@ -71,24 +139,16 @@ jobs:
|
||||
mkdir .cargo
|
||||
cargo vendor > .cargo/config.toml
|
||||
- name: Create vendored source archive
|
||||
if: |
|
||||
github.event_name == 'create' && github.event.ref_type == 'tag' &&
|
||||
matrix.platform.target == 'x86_64-unknown-linux-gnu'
|
||||
run: tar cJf cloud-hypervisor-${{ github.event.ref }}.tar.xz ../cloud-hypervisor-${{ github.event.ref }}
|
||||
working-directory: ../
|
||||
run: tar cJf cloud-hypervisor-${{ github.event.ref }}.tar.xz cloud-hypervisor-${{ github.event.ref }}
|
||||
- name: Upload cloud-hypervisor vendored source archive
|
||||
if: |
|
||||
github.event_name == 'create' && github.event.ref_type == 'tag' &&
|
||||
matrix.platform.target == 'x86_64-unknown-linux-gnu'
|
||||
id: upload-release-cloud-hypervisor-vendored-sources
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
path: cloud-hypervisor-${{ github.event.ref }}.tar.xz
|
||||
name: cloud-hypervisor-${{ github.event.ref }}.tar.xz
|
||||
- name: Create GitHub Release
|
||||
if: github.event_name == 'create' && github.event.ref_type == 'tag'
|
||||
uses: softprops/action-gh-release@v1
|
||||
id: upload-release-cloud-hypervisor-vendored-sources
|
||||
uses: actions/upload-release-asset@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
files: |
|
||||
./${{ matrix.platform.name_ch }}
|
||||
./${{ matrix.platform.name_ch_remote }}
|
||||
./cloud-hypervisor-${{ github.event.ref }}.tar.xz
|
||||
upload_url: ${{ steps.create_release.outputs.upload_url }}
|
||||
asset_path: ../cloud-hypervisor-${{ github.event.ref }}.tar.xz
|
||||
asset_name: cloud-hypervisor-${{ github.event.ref }}.tar.xz
|
||||
asset_content_type: application/x-xz
|
||||
|
||||
12
.github/workflows/reuse.yaml
vendored
12
.github/workflows/reuse.yaml
vendored
@@ -1,12 +0,0 @@
|
||||
name: REUSE Compliance Check
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
reuse:
|
||||
name: REUSE Compliance Check
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: REUSE Compliance Check
|
||||
uses: fsfe/reuse-action@v3
|
||||
20
.github/workflows/shlint.yaml
vendored
20
.github/workflows/shlint.yaml
vendored
@@ -1,20 +0,0 @@
|
||||
name: Shell scripts check
|
||||
on:
|
||||
pull_request:
|
||||
merge_group:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
|
||||
jobs:
|
||||
sh-checker:
|
||||
name: Check shell scripts
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
- name: Run the shell script checkers
|
||||
uses: luizm/action-sh-checker@master
|
||||
env:
|
||||
SHFMT_OPTS: -i 4 -d
|
||||
SHELLCHECK_OPTS: -x --source-path scripts
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -6,4 +6,3 @@
|
||||
**/rusty-tags.vi
|
||||
/rpm/SOURCES
|
||||
/.vscode
|
||||
/vendor
|
||||
|
||||
12
.reuse/dep5
12
.reuse/dep5
@@ -1,12 +0,0 @@
|
||||
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
|
||||
Upstream-Name: cloud-hypervisor
|
||||
Upstream-Contact: <>
|
||||
Source: https://www.cloudhypervisor.org
|
||||
|
||||
Files: docs/*.md *.md
|
||||
Copyright: 2024
|
||||
License: CC-BY-4.0
|
||||
|
||||
Files: scripts/* test_data/* *.toml .git* fuzz/Cargo.lock fuzz/.gitignore resources/linux-config-* vmm/src/api/openapi/cloud-hypervisor.yaml CODEOWNERS Cargo.lock
|
||||
Copyright: 2024
|
||||
License: Apache-2.0
|
||||
1063
Cargo.lock
generated
1063
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
33
Cargo.toml
33
Cargo.toml
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "cloud-hypervisor"
|
||||
version = "39.0.0"
|
||||
version = "37.1.0"
|
||||
authors = ["The Cloud Hypervisor Authors"]
|
||||
edition = "2021"
|
||||
default-run = "cloud-hypervisor"
|
||||
@@ -15,7 +15,7 @@ homepage = "https://github.com/cloud-hypervisor/cloud-hypervisor"
|
||||
# a.) A dependency requires it,
|
||||
# b.) If we want to use a new feature and that MSRV is at least 6 months old,
|
||||
# c.) There is a security issue that is addressed by the toolchain update.
|
||||
rust-version = "1.74.1"
|
||||
rust-version = "1.70"
|
||||
|
||||
[profile.release]
|
||||
lto = true
|
||||
@@ -29,32 +29,37 @@ strip = false
|
||||
debug = true
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.81"
|
||||
anyhow = "1.0.75"
|
||||
api_client = { path = "api_client" }
|
||||
clap = { version = "4.5.4", features = ["string"] }
|
||||
dhat = { version = "0.3.3", optional = true }
|
||||
clap = { version = "4.4.7", features = ["string"] }
|
||||
dhat = { version = "0.3.2", optional = true }
|
||||
epoll = "4.3.3"
|
||||
event_monitor = { path = "event_monitor" }
|
||||
hypervisor = { path = "hypervisor" }
|
||||
libc = "0.2.153"
|
||||
log = { version = "0.4.21", features = ["std"] }
|
||||
libc = "0.2.147"
|
||||
log = { version = "0.4.20", features = ["std"] }
|
||||
option_parser = { path = "option_parser" }
|
||||
seccompiler = "0.4.0"
|
||||
serde_json = "1.0.115"
|
||||
serde_json = "1.0.107"
|
||||
signal-hook = "0.3.17"
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.40"
|
||||
tpm = { path = "tpm"}
|
||||
tracer = { path = "tracer" }
|
||||
vmm = { path = "vmm" }
|
||||
vmm-sys-util = "0.12.1"
|
||||
vm-memory = "0.14.1"
|
||||
zbus = { version = "3.15.2", optional = true }
|
||||
vm-memory = "0.14.0"
|
||||
zbus = { version = "3.11.1", optional = true }
|
||||
|
||||
# List of patched crates
|
||||
[patch.crates-io]
|
||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-live-upgrade-stable-37.x" }
|
||||
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch-0.1.6" }
|
||||
|
||||
[dev-dependencies]
|
||||
dirs = "5.0.1"
|
||||
dirs = "5.0.0"
|
||||
net_util = { path = "net_util" }
|
||||
once_cell = "1.19.0"
|
||||
serde_json = "1.0.115"
|
||||
once_cell = "1.18.0"
|
||||
serde_json = "1.0.107"
|
||||
test_infra = { path = "test_infra" }
|
||||
wait-timeout = "0.2.0"
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ do not wish to use the pre-built binaries.
|
||||
## Booting Linux
|
||||
|
||||
Cloud Hypervisor supports direct kernel boot (the x86-64 kernel requires the kernel
|
||||
built with PVH support or a bzImage) or booting via a firmware (either [Rust Hypervisor
|
||||
built with PVH support) or booting via a firmware (either [Rust Hypervisor
|
||||
Firmware](https://github.com/cloud-hypervisor/rust-hypervisor-firmware) or an
|
||||
edk2 UEFI firmware called `CLOUDHV` / `CLOUDHV_EFI`.)
|
||||
|
||||
@@ -175,7 +175,7 @@ $ ./cloud-hypervisor \
|
||||
|
||||
#### Building your Kernel
|
||||
|
||||
Cloud Hypervisor also supports direct kernel boot. For x86-64, a `vmlinux` ELF kernel (compiled with PVH support) or a regular bzImage are supported. In order to support development there is a custom branch; however provided the required options are enabled any recent kernel will suffice.
|
||||
Cloud Hypervisor also supports direct kernel boot. For x86-64, a `vmlinux` ELF kernel (compiled with PVH support) is needed. In order to support development there is a custom branch; however provided the required options are enabled any recent kernel will suffice.
|
||||
|
||||
To build the kernel:
|
||||
|
||||
|
||||
@@ -10,19 +10,21 @@ sev_snp = []
|
||||
tdx = []
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.81"
|
||||
byteorder = "1.5.0"
|
||||
anyhow = "1.0.75"
|
||||
byteorder = "1.4.3"
|
||||
hypervisor = { path = "../hypervisor" }
|
||||
libc = "0.2.153"
|
||||
libc = "0.2.147"
|
||||
linux-loader = { version = "0.11.0", features = ["elf", "bzimage", "pe"] }
|
||||
log = "0.4.21"
|
||||
serde = { version = "1.0.197", features = ["rc", "derive"] }
|
||||
thiserror = "1.0.58"
|
||||
uuid = "1.8.0"
|
||||
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-bitmap"] }
|
||||
log = "0.4.20"
|
||||
serde = { version = "1.0.168", features = ["rc", "derive"] }
|
||||
thiserror = "1.0.40"
|
||||
uuid = "1.3.4"
|
||||
versionize = "0.2.0"
|
||||
versionize_derive = "0.1.6"
|
||||
vm-memory = { version = "0.14.0", features = ["backend-mmap", "backend-bitmap"] }
|
||||
vm-migration = { path = "../vm-migration" }
|
||||
vmm-sys-util = { version = "0.12.1", features = ["with-serde"] }
|
||||
|
||||
[target.'cfg(target_arch = "aarch64")'.dependencies]
|
||||
fdt_parser = { version = "0.1.5", package = "fdt" }
|
||||
fdt_parser = { version = "0.1.4", package = "fdt" }
|
||||
vm-fdt = { git = "https://github.com/rust-vmm/vm-fdt", branch = "main" }
|
||||
|
||||
@@ -111,9 +111,8 @@ pub const RAM_64BIT_START: GuestAddress = GuestAddress(0x1_0000_0000);
|
||||
pub const CMDLINE_MAX_SIZE: usize = 2048;
|
||||
|
||||
/// FDT is at the beginning of RAM.
|
||||
/// Maximum size of the device tree blob as specified in https://www.kernel.org/doc/Documentation/arm64/booting.txt.
|
||||
pub const FDT_START: GuestAddress = RAM_START;
|
||||
/// Maximum size of the device tree blob as specified in [the kernel
|
||||
/// documentation](https://www.kernel.org/doc/Documentation/arm64/booting.txt).
|
||||
pub const FDT_MAX_SIZE: u64 = 0x20_0000;
|
||||
|
||||
/// Put ACPI table above dtb
|
||||
|
||||
@@ -16,6 +16,7 @@ use crate::{DeviceType, GuestMemoryMmap, NumaNodes, PciSpaceInfo, RegionType};
|
||||
use hypervisor::arch::aarch64::gic::Vgic;
|
||||
use log::{log_enabled, Level};
|
||||
use std::collections::HashMap;
|
||||
use std::convert::TryInto;
|
||||
use std::fmt::Debug;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use vm_memory::{Address, GuestAddress, GuestMemory, GuestMemoryAtomic};
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// Copyright 2020 Arm Limited (or its affiliates). All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use std::io::{Read, Seek, SeekFrom};
|
||||
use std::os::fd::AsFd;
|
||||
|
||||
@@ -18,6 +18,9 @@ use std::fmt;
|
||||
use std::result;
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_migration::VersionMapped;
|
||||
|
||||
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<vm_memory::bitmap::AtomicBitmap>;
|
||||
type GuestRegionMmap = vm_memory::GuestRegionMmap<vm_memory::bitmap::AtomicBitmap>;
|
||||
@@ -45,17 +48,13 @@ pub enum Error {
|
||||
ModlistSetup(#[source] vm_memory::GuestMemoryError),
|
||||
#[error("RSDP extends past the end of guest memory")]
|
||||
RsdpPastRamEnd,
|
||||
#[error("Failed to setup Zero Page for bzImage")]
|
||||
ZeroPageSetup(#[source] vm_memory::GuestMemoryError),
|
||||
#[error("Zero Page for bzImage past RAM end")]
|
||||
ZeroPagePastRamEnd,
|
||||
}
|
||||
|
||||
/// Type for returning public functions outcome.
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
/// Type for memory region types.
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Serialize, Deserialize, Versionize)]
|
||||
pub enum RegionType {
|
||||
/// RAM type
|
||||
Ram,
|
||||
@@ -73,6 +72,8 @@ pub enum RegionType {
|
||||
Reserved,
|
||||
}
|
||||
|
||||
impl VersionMapped for RegionType {}
|
||||
|
||||
/// Module for aarch64 related functionality.
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub mod aarch64;
|
||||
|
||||
@@ -17,7 +17,6 @@ use crate::InitramfsConfig;
|
||||
use crate::RegionType;
|
||||
use hypervisor::arch::x86::{CpuIdEntry, CPUID_FLAG_VALID_INDEX};
|
||||
use hypervisor::{CpuVendor, HypervisorCpuError, HypervisorError};
|
||||
use linux_loader::loader::bootparam::{boot_params, setup_header};
|
||||
use linux_loader::loader::elf::start_info::{
|
||||
hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info,
|
||||
};
|
||||
@@ -64,8 +63,6 @@ pub const _NSIG: i32 = 65;
|
||||
pub struct EntryPoint {
|
||||
/// Address in guest memory where the guest must start execution
|
||||
pub entry_addr: GuestAddress,
|
||||
/// This field is used for bzImage to fill the zero page
|
||||
pub setup_header: Option<setup_header>,
|
||||
}
|
||||
|
||||
const E820_RAM: u32 = 1;
|
||||
@@ -183,9 +180,6 @@ pub enum Error {
|
||||
/// Error retrieving TDX capabilities through the hypervisor (kvm/mshv) API
|
||||
#[cfg(feature = "tdx")]
|
||||
TdxCapabilities(HypervisorError),
|
||||
|
||||
/// Failed to configure E820 map for bzImage
|
||||
E820Configuration,
|
||||
}
|
||||
|
||||
impl From<Error> for super::Error {
|
||||
@@ -848,7 +842,8 @@ pub fn configure_vcpu(
|
||||
|
||||
regs::setup_msrs(vcpu).map_err(Error::MsrsConfiguration)?;
|
||||
if let Some((kernel_entry_point, guest_memory)) = boot_setup {
|
||||
regs::setup_regs(vcpu, kernel_entry_point).map_err(Error::RegsConfiguration)?;
|
||||
regs::setup_regs(vcpu, kernel_entry_point.entry_addr.raw_value())
|
||||
.map_err(Error::RegsConfiguration)?;
|
||||
regs::setup_fpu(vcpu).map_err(Error::FpuConfiguration)?;
|
||||
regs::setup_sregs(&guest_memory.memory(), vcpu).map_err(Error::SregsConfiguration)?;
|
||||
}
|
||||
@@ -897,10 +892,8 @@ pub fn arch_memory_regions() -> Vec<(GuestAddress, usize, RegionType)> {
|
||||
pub fn configure_system(
|
||||
guest_mem: &GuestMemoryMmap,
|
||||
cmdline_addr: GuestAddress,
|
||||
cmdline_size: usize,
|
||||
initramfs: &Option<InitramfsConfig>,
|
||||
_num_cpus: u8,
|
||||
setup_header: Option<setup_header>,
|
||||
rsdp_addr: Option<GuestAddress>,
|
||||
sgx_epc_region: Option<SgxEpcRegion>,
|
||||
serial_number: Option<&str>,
|
||||
@@ -928,31 +921,25 @@ pub fn configure_system(
|
||||
}
|
||||
}
|
||||
|
||||
match setup_header {
|
||||
Some(hdr) => configure_32bit_entry(
|
||||
guest_mem,
|
||||
cmdline_addr,
|
||||
cmdline_size,
|
||||
initramfs,
|
||||
hdr,
|
||||
rsdp_addr,
|
||||
sgx_epc_region,
|
||||
),
|
||||
None => configure_pvh(
|
||||
guest_mem,
|
||||
cmdline_addr,
|
||||
initramfs,
|
||||
rsdp_addr,
|
||||
sgx_epc_region,
|
||||
),
|
||||
}
|
||||
configure_pvh(
|
||||
guest_mem,
|
||||
cmdline_addr,
|
||||
initramfs,
|
||||
rsdp_addr,
|
||||
sgx_epc_region,
|
||||
)
|
||||
}
|
||||
|
||||
type RamRange = (u64, u64);
|
||||
|
||||
/// Returns usable physical memory ranges for the guest
|
||||
/// These should be used to create e820_RAM memory maps
|
||||
pub fn generate_ram_ranges(guest_mem: &GuestMemoryMmap) -> super::Result<Vec<RamRange>> {
|
||||
///
|
||||
/// There are up to two usable physical memory ranges,
|
||||
/// divided by the gap at the end of 32bit address space.
|
||||
pub fn generate_ram_ranges(
|
||||
guest_mem: &GuestMemoryMmap,
|
||||
) -> super::Result<(RamRange, Option<RamRange>)> {
|
||||
// Merge continuous memory regions into one region.
|
||||
// Note: memory regions from "GuestMemory" are sorted and non-zero sized.
|
||||
let ram_regions = {
|
||||
@@ -985,11 +972,15 @@ pub fn generate_ram_ranges(guest_mem: &GuestMemoryMmap) -> super::Result<Vec<Ram
|
||||
ram_regions
|
||||
};
|
||||
|
||||
// Create the memory map entry for memory region before the gap
|
||||
let mut ram_ranges = vec![];
|
||||
if ram_regions.len() > 2 {
|
||||
error!(
|
||||
"There should be up to two usable physical memory ranges, devidided by the
|
||||
gap at the end of 32bit address space (e.g. between 3G and 4G)."
|
||||
);
|
||||
return Err(super::Error::MemmapTableSetup);
|
||||
}
|
||||
|
||||
// Generate the first usable physical memory range before the gap. The e820 map
|
||||
// should only report memory above 1MiB.
|
||||
// Generate the first usable physical memory range before the gap
|
||||
let first_ram_range = {
|
||||
let (first_region_start, first_region_end) =
|
||||
ram_regions.first().ok_or(super::Error::MemmapTableSetup)?;
|
||||
@@ -1016,19 +1007,33 @@ pub fn generate_ram_ranges(guest_mem: &GuestMemoryMmap) -> super::Result<Vec<Ram
|
||||
|
||||
(high_ram_start, *first_region_end)
|
||||
};
|
||||
ram_ranges.push(first_ram_range);
|
||||
|
||||
// Generate additional usable physical memory range after the gap if any.
|
||||
for ram_region in ram_regions.iter().skip(1) {
|
||||
// Generate the second usable physical memory range after the gap if any
|
||||
let second_ram_range = if let Some((second_region_start, second_region_end)) =
|
||||
ram_regions.get(1)
|
||||
{
|
||||
let ram_64bit_start = layout::RAM_64BIT_START.raw_value();
|
||||
|
||||
if second_region_start != &ram_64bit_start {
|
||||
error!(
|
||||
"Unexpected second memory region layout: start: 0x{:08x}, ram_64bit_start: 0x{:08x}",
|
||||
second_region_start, ram_64bit_start
|
||||
);
|
||||
|
||||
return Err(super::Error::MemmapTableSetup);
|
||||
}
|
||||
|
||||
info!(
|
||||
"found usable physical memory range, start: 0x{:08x}, end: 0x{:08x}",
|
||||
ram_region.0, ram_region.1
|
||||
"Second usable physical memory range, start: 0x{:08x}, end: 0x{:08x}",
|
||||
ram_64bit_start, second_region_end
|
||||
);
|
||||
|
||||
ram_ranges.push(*ram_region);
|
||||
}
|
||||
Some((ram_64bit_start, *second_region_end))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Ok(ram_ranges)
|
||||
Ok((first_ram_range, second_ram_range))
|
||||
}
|
||||
|
||||
fn configure_pvh(
|
||||
@@ -1079,18 +1084,30 @@ fn configure_pvh(
|
||||
add_memmap_entry(&mut memmap, 0, layout::EBDA_START.raw_value(), E820_RAM);
|
||||
|
||||
// Get usable physical memory ranges
|
||||
let ram_ranges = generate_ram_ranges(guest_mem)?;
|
||||
let (first_ram_range, second_ram_range) = generate_ram_ranges(guest_mem)?;
|
||||
|
||||
// Create e820 memory map entries
|
||||
for ram_range in ram_ranges {
|
||||
// Create e820 memory map entry before the gap
|
||||
info!(
|
||||
"create_memmap_entry, start: 0x{:08x}, end: 0x{:08x}",
|
||||
first_ram_range.0, first_ram_range.1
|
||||
);
|
||||
add_memmap_entry(
|
||||
&mut memmap,
|
||||
first_ram_range.0,
|
||||
first_ram_range.1 - first_ram_range.0,
|
||||
E820_RAM,
|
||||
);
|
||||
|
||||
// Create e820 memory map after the gap if any
|
||||
if let Some(second_ram_range) = second_ram_range {
|
||||
info!(
|
||||
"create_memmap_entry, start: 0x{:08x}, end: 0x{:08x}",
|
||||
ram_range.0, ram_range.1
|
||||
second_ram_range.0, second_ram_range.1
|
||||
);
|
||||
add_memmap_entry(
|
||||
&mut memmap,
|
||||
ram_range.0,
|
||||
ram_range.1 - ram_range.0,
|
||||
second_ram_range.0,
|
||||
second_ram_range.1 - second_ram_range.0,
|
||||
E820_RAM,
|
||||
);
|
||||
}
|
||||
@@ -1150,113 +1167,6 @@ fn configure_pvh(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn configure_32bit_entry(
|
||||
guest_mem: &GuestMemoryMmap,
|
||||
cmdline_addr: GuestAddress,
|
||||
cmdline_size: usize,
|
||||
initramfs: &Option<InitramfsConfig>,
|
||||
setup_hdr: setup_header,
|
||||
rsdp_addr: Option<GuestAddress>,
|
||||
sgx_epc_region: Option<SgxEpcRegion>,
|
||||
) -> super::Result<()> {
|
||||
const KERNEL_LOADER_OTHER: u8 = 0xff;
|
||||
|
||||
// Use the provided setup header
|
||||
let mut params = boot_params {
|
||||
hdr: setup_hdr,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// Common bootparams settings
|
||||
if params.hdr.type_of_loader == 0 {
|
||||
params.hdr.type_of_loader = KERNEL_LOADER_OTHER;
|
||||
}
|
||||
params.hdr.cmd_line_ptr = cmdline_addr.raw_value() as u32;
|
||||
params.hdr.cmdline_size = cmdline_size as u32;
|
||||
|
||||
if let Some(initramfs_config) = initramfs {
|
||||
params.hdr.ramdisk_image = initramfs_config.address.raw_value() as u32;
|
||||
params.hdr.ramdisk_size = initramfs_config.size as u32;
|
||||
}
|
||||
|
||||
add_e820_entry(&mut params, 0, layout::EBDA_START.raw_value(), E820_RAM)?;
|
||||
|
||||
let mem_end = guest_mem.last_addr();
|
||||
if mem_end < layout::MEM_32BIT_RESERVED_START {
|
||||
add_e820_entry(
|
||||
&mut params,
|
||||
layout::HIGH_RAM_START.raw_value(),
|
||||
mem_end.unchecked_offset_from(layout::HIGH_RAM_START) + 1,
|
||||
E820_RAM,
|
||||
)?;
|
||||
} else {
|
||||
add_e820_entry(
|
||||
&mut params,
|
||||
layout::HIGH_RAM_START.raw_value(),
|
||||
layout::MEM_32BIT_RESERVED_START.unchecked_offset_from(layout::HIGH_RAM_START),
|
||||
E820_RAM,
|
||||
)?;
|
||||
if mem_end > layout::RAM_64BIT_START {
|
||||
add_e820_entry(
|
||||
&mut params,
|
||||
layout::RAM_64BIT_START.raw_value(),
|
||||
mem_end.unchecked_offset_from(layout::RAM_64BIT_START) + 1,
|
||||
E820_RAM,
|
||||
)?;
|
||||
}
|
||||
}
|
||||
|
||||
add_e820_entry(
|
||||
&mut params,
|
||||
layout::PCI_MMCONFIG_START.0,
|
||||
layout::PCI_MMCONFIG_SIZE,
|
||||
E820_RESERVED,
|
||||
)?;
|
||||
|
||||
if let Some(sgx_epc_region) = sgx_epc_region {
|
||||
add_e820_entry(
|
||||
&mut params,
|
||||
sgx_epc_region.start().raw_value(),
|
||||
sgx_epc_region.size(),
|
||||
E820_RESERVED,
|
||||
)?;
|
||||
}
|
||||
|
||||
if let Some(rsdp_addr) = rsdp_addr {
|
||||
params.acpi_rsdp_addr = rsdp_addr.0;
|
||||
}
|
||||
|
||||
let zero_page_addr = layout::ZERO_PAGE_START;
|
||||
guest_mem
|
||||
.checked_offset(zero_page_addr, mem::size_of::<boot_params>())
|
||||
.ok_or(super::Error::ZeroPagePastRamEnd)?;
|
||||
guest_mem
|
||||
.write_obj(params, zero_page_addr)
|
||||
.map_err(super::Error::ZeroPageSetup)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Add an e820 region to the e820 map.
|
||||
/// Returns Ok(()) if successful, or an error if there is no space left in the map.
|
||||
fn add_e820_entry(
|
||||
params: &mut boot_params,
|
||||
addr: u64,
|
||||
size: u64,
|
||||
mem_type: u32,
|
||||
) -> Result<(), Error> {
|
||||
if params.e820_entries >= params.e820_table.len() as u8 {
|
||||
return Err(Error::E820Configuration);
|
||||
}
|
||||
|
||||
params.e820_table[params.e820_entries as usize].addr = addr;
|
||||
params.e820_table[params.e820_entries as usize].size = size;
|
||||
params.e820_table[params.e820_entries as usize].type_ = mem_type;
|
||||
params.e820_entries += 1;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_memmap_entry(memmap: &mut Vec<hvm_memmap_table_entry>, addr: u64, size: u64, mem_type: u32) {
|
||||
// Add the table entry to the vector
|
||||
memmap.push(hvm_memmap_table_entry {
|
||||
@@ -1503,7 +1413,6 @@ fn update_cpuid_sgx(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use linux_loader::loader::bootparam::boot_e820_entry;
|
||||
|
||||
#[test]
|
||||
fn regions_base_addr() {
|
||||
@@ -1520,10 +1429,8 @@ mod tests {
|
||||
let config_err = configure_system(
|
||||
&gm,
|
||||
GuestAddress(0),
|
||||
0,
|
||||
&None,
|
||||
1,
|
||||
None,
|
||||
Some(layout::RSDP_POINTER),
|
||||
None,
|
||||
None,
|
||||
@@ -1545,7 +1452,6 @@ mod tests {
|
||||
configure_system(
|
||||
&gm,
|
||||
GuestAddress(0),
|
||||
0,
|
||||
&None,
|
||||
no_vcpus,
|
||||
None,
|
||||
@@ -1554,7 +1460,6 @@ mod tests {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
@@ -1575,7 +1480,6 @@ mod tests {
|
||||
configure_system(
|
||||
&gm,
|
||||
GuestAddress(0),
|
||||
0,
|
||||
&None,
|
||||
no_vcpus,
|
||||
None,
|
||||
@@ -1584,14 +1488,12 @@ mod tests {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
configure_system(
|
||||
&gm,
|
||||
GuestAddress(0),
|
||||
0,
|
||||
&None,
|
||||
no_vcpus,
|
||||
None,
|
||||
@@ -1600,51 +1502,10 @@ mod tests {
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_e820_entry() {
|
||||
let e820_table = [(boot_e820_entry {
|
||||
addr: 0x1,
|
||||
size: 4,
|
||||
type_: 1,
|
||||
}); 128];
|
||||
|
||||
let expected_params = boot_params {
|
||||
e820_table,
|
||||
e820_entries: 1,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let mut params: boot_params = Default::default();
|
||||
add_e820_entry(
|
||||
&mut params,
|
||||
e820_table[0].addr,
|
||||
e820_table[0].size,
|
||||
e820_table[0].type_,
|
||||
)
|
||||
.unwrap();
|
||||
assert_eq!(
|
||||
format!("{:?}", params.e820_table[0]),
|
||||
format!("{:?}", expected_params.e820_table[0])
|
||||
);
|
||||
assert_eq!(params.e820_entries, expected_params.e820_entries);
|
||||
|
||||
// Exercise the scenario where the field storing the length of the e820 entry table is
|
||||
// is bigger than the allocated memory.
|
||||
params.e820_entries = params.e820_table.len() as u8 + 1;
|
||||
assert!(add_e820_entry(
|
||||
&mut params,
|
||||
e820_table[0].addr,
|
||||
e820_table[0].size,
|
||||
e820_table[0].type_
|
||||
)
|
||||
.is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_memmap_entry() {
|
||||
let mut memmap: Vec<hvm_memmap_table_entry> = Vec::new();
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
|
||||
|
||||
@@ -300,7 +300,8 @@ mod tests {
|
||||
use super::*;
|
||||
use crate::layout::MPTABLE_START;
|
||||
use vm_memory::{
|
||||
bitmap::BitmapSlice, GuestUsize, VolatileMemoryError, VolatileSlice, WriteVolatile,
|
||||
bitmap::BitmapSlice, GuestAddress, GuestUsize, VolatileMemoryError, VolatileSlice,
|
||||
WriteVolatile,
|
||||
};
|
||||
|
||||
fn table_entry_size(type_: u8) -> usize {
|
||||
|
||||
@@ -6,10 +6,8 @@
|
||||
// Portions Copyright 2017 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
use crate::layout::{
|
||||
BOOT_GDT_START, BOOT_IDT_START, BOOT_STACK_POINTER, PVH_INFO_START, ZERO_PAGE_START,
|
||||
};
|
||||
use crate::{EntryPoint, GuestMemoryMmap};
|
||||
use crate::layout::{BOOT_GDT_START, BOOT_IDT_START, PVH_INFO_START};
|
||||
use crate::GuestMemoryMmap;
|
||||
use hypervisor::arch::x86::gdt::{gdt_entry, segment_from_gdt};
|
||||
use hypervisor::arch::x86::regs::CR0_PE;
|
||||
use hypervisor::arch::x86::{FpuState, SpecialRegisters, StandardRegisters};
|
||||
@@ -79,22 +77,13 @@ pub fn setup_msrs(vcpu: &Arc<dyn hypervisor::Vcpu>) -> Result<()> {
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `vcpu` - Structure for the VCPU that holds the VCPU's fd.
|
||||
/// * `entry_point` - Description of the boot entry to set up.
|
||||
pub fn setup_regs(vcpu: &Arc<dyn hypervisor::Vcpu>, entry_point: EntryPoint) -> Result<()> {
|
||||
let regs = match entry_point.setup_header {
|
||||
None => StandardRegisters {
|
||||
rflags: 0x0000000000000002u64,
|
||||
rip: entry_point.entry_addr.raw_value(),
|
||||
rbx: PVH_INFO_START.raw_value(),
|
||||
..Default::default()
|
||||
},
|
||||
Some(_) => StandardRegisters {
|
||||
rflags: 0x0000000000000002u64,
|
||||
rip: entry_point.entry_addr.raw_value(),
|
||||
rsp: BOOT_STACK_POINTER.raw_value(),
|
||||
rsi: ZERO_PAGE_START.raw_value(),
|
||||
..Default::default()
|
||||
},
|
||||
/// * `boot_ip` - Starting instruction pointer.
|
||||
pub fn setup_regs(vcpu: &Arc<dyn hypervisor::Vcpu>, boot_ip: u64) -> Result<()> {
|
||||
let regs = StandardRegisters {
|
||||
rflags: 0x0000000000000002u64,
|
||||
rbx: PVH_INFO_START.raw_value(),
|
||||
rip: boot_ip,
|
||||
..Default::default()
|
||||
};
|
||||
vcpu.set_regs(®s).map_err(Error::SetBaseRegisters)
|
||||
}
|
||||
@@ -175,6 +164,7 @@ pub fn configure_segments_and_sregs(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::GuestMemoryMmap;
|
||||
use vm_memory::GuestAddress;
|
||||
|
||||
fn create_guest_mem() -> GuestMemoryMmap {
|
||||
|
||||
@@ -9,18 +9,19 @@ default = []
|
||||
io_uring = ["dep:io-uring"]
|
||||
|
||||
[dependencies]
|
||||
byteorder = "1.5.0"
|
||||
byteorder = "1.4.3"
|
||||
crc-any = "2.4.4"
|
||||
io-uring = { version = "0.6.3", optional = true }
|
||||
libc = "0.2.153"
|
||||
log = "0.4.21"
|
||||
remain = "0.2.13"
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
smallvec = "1.13.2"
|
||||
thiserror = "1.0.58"
|
||||
uuid = { version = "1.8.0", features = ["v4"] }
|
||||
virtio-bindings = { version = "0.2.2", features = ["virtio-v5_0_0"] }
|
||||
virtio-queue = "0.11.0"
|
||||
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
io-uring = { version = "0.6.2", optional = true }
|
||||
libc = "0.2.147"
|
||||
log = "0.4.20"
|
||||
remain = "0.2.11"
|
||||
smallvec = "1.11.0"
|
||||
thiserror = "1.0.40"
|
||||
uuid = { version = "1.3.4", features = ["v4"] }
|
||||
versionize = "0.2.0"
|
||||
versionize_derive = "0.1.6"
|
||||
virtio-bindings = { version = "0.2.0", features = ["virtio-v5_0_0"] }
|
||||
virtio-queue = "0.12.0"
|
||||
vm-memory = { version = "0.14.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
vm-virtio = { path = "../vm-virtio" }
|
||||
vmm-sys-util = "0.12.1"
|
||||
|
||||
@@ -37,11 +37,11 @@ use crate::vhdx::{Vhdx, VhdxError};
|
||||
#[cfg(feature = "io_uring")]
|
||||
use io_uring::{opcode, IoUring, Probe};
|
||||
use libc::{ioctl, S_IFBLK, S_IFMT};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use smallvec::SmallVec;
|
||||
use std::alloc::{alloc_zeroed, dealloc, Layout};
|
||||
use std::cmp;
|
||||
use std::collections::VecDeque;
|
||||
use std::convert::TryInto;
|
||||
use std::fmt::Debug;
|
||||
use std::fs::File;
|
||||
use std::io::{self, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
|
||||
@@ -53,19 +53,19 @@ use std::sync::Arc;
|
||||
use std::sync::MutexGuard;
|
||||
use std::time::Instant;
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_bindings::virtio_blk::*;
|
||||
use virtio_queue::DescriptorChain;
|
||||
use vm_memory::{
|
||||
bitmap::AtomicBitmap, bitmap::Bitmap, ByteValued, Bytes, GuestAddress, GuestMemory,
|
||||
GuestMemoryError, GuestMemoryLoadGuard,
|
||||
bitmap::Bitmap, ByteValued, Bytes, GuestAddress, GuestMemory, GuestMemoryError,
|
||||
GuestMemoryLoadGuard,
|
||||
};
|
||||
use vm_virtio::{AccessPlatform, Translatable};
|
||||
use vmm_sys_util::aio;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
use vmm_sys_util::{ioctl_io_nr, ioctl_ioc_nr};
|
||||
|
||||
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
|
||||
|
||||
const SECTOR_SHIFT: u8 = 9;
|
||||
pub const SECTOR_SIZE: u64 = 0x01 << SECTOR_SHIFT;
|
||||
|
||||
@@ -195,8 +195,8 @@ pub enum RequestType {
|
||||
Unsupported(u32),
|
||||
}
|
||||
|
||||
pub fn request_type(
|
||||
mem: &GuestMemoryMmap,
|
||||
pub fn request_type<B: Bitmap + 'static>(
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
desc_addr: GuestAddress,
|
||||
) -> result::Result<RequestType, Error> {
|
||||
let type_ = mem.read_obj(desc_addr).map_err(Error::GuestMemory)?;
|
||||
@@ -209,7 +209,10 @@ pub fn request_type(
|
||||
}
|
||||
}
|
||||
|
||||
fn sector(mem: &GuestMemoryMmap, desc_addr: GuestAddress) -> result::Result<u64, Error> {
|
||||
fn sector<B: Bitmap + 'static>(
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
desc_addr: GuestAddress,
|
||||
) -> result::Result<u64, Error> {
|
||||
const SECTOR_OFFSET: usize = 8;
|
||||
let addr = match mem.checked_offset(desc_addr, SECTOR_OFFSET) {
|
||||
Some(v) => v,
|
||||
@@ -239,8 +242,8 @@ pub struct Request {
|
||||
}
|
||||
|
||||
impl Request {
|
||||
pub fn parse(
|
||||
desc_chain: &mut DescriptorChain<GuestMemoryLoadGuard<GuestMemoryMmap>>,
|
||||
pub fn parse<B: Bitmap + 'static>(
|
||||
desc_chain: &mut DescriptorChain<GuestMemoryLoadGuard<vm_memory::GuestMemoryMmap<B>>>,
|
||||
access_platform: Option<&Arc<dyn AccessPlatform>>,
|
||||
) -> result::Result<Request, Error> {
|
||||
let hdr_desc = desc_chain
|
||||
@@ -331,11 +334,11 @@ impl Request {
|
||||
Ok(req)
|
||||
}
|
||||
|
||||
pub fn execute<T: Seek + Read + Write>(
|
||||
pub fn execute<T: Seek + Read + Write, B: Bitmap + 'static>(
|
||||
&self,
|
||||
disk: &mut T,
|
||||
disk_nsectors: u64,
|
||||
mem: &GuestMemoryMmap,
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
serial: &[u8],
|
||||
) -> result::Result<u32, ExecuteError> {
|
||||
disk.seek(SeekFrom::Start(self.sector << SECTOR_SHIFT))
|
||||
@@ -388,9 +391,9 @@ impl Request {
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
pub fn execute_async(
|
||||
pub fn execute_async<B: Bitmap + 'static>(
|
||||
&mut self,
|
||||
mem: &GuestMemoryMmap,
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
disk_nsectors: u64,
|
||||
disk_image: &mut dyn AsyncIo,
|
||||
serial: &[u8],
|
||||
@@ -543,7 +546,7 @@ impl Request {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
||||
#[repr(C, packed)]
|
||||
pub struct VirtioBlockConfig {
|
||||
pub capacity: u64,
|
||||
@@ -566,7 +569,7 @@ pub struct VirtioBlockConfig {
|
||||
pub write_zeroes_may_unmap: u8,
|
||||
pub unused1: [u8; 3],
|
||||
}
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
||||
#[repr(C, packed)]
|
||||
pub struct VirtioBlockGeometry {
|
||||
pub cylinders: u16,
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
mod qcow_raw_file;
|
||||
mod raw_file;
|
||||
@@ -1824,6 +1822,7 @@ pub fn detect_image_type(file: &mut RawFile) -> Result<ImageType> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::io::{Read, Seek, SeekFrom, Write};
|
||||
use vmm_sys_util::tempfile::TempFile;
|
||||
use vmm_sys_util::write_zeroes::WriteZeroes;
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
use super::RawFile;
|
||||
use byteorder::{BigEndian, ReadBytesExt, WriteBytesExt};
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
use crate::BlockBackend;
|
||||
use libc::c_void;
|
||||
use std::alloc::{alloc_zeroed, dealloc, Layout};
|
||||
use std::convert::TryInto;
|
||||
use std::fs::{File, Metadata};
|
||||
use std::io::{self, Read, Seek, SeekFrom, Write};
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
use std::fmt::{self, Display};
|
||||
use std::io;
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
use std::collections::hash_map::IterMut;
|
||||
use std::collections::HashMap;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{read_aligned_block_size, DiskTopology};
|
||||
use std::convert::TryInto;
|
||||
use std::fs::File;
|
||||
use std::io::{Seek, SeekFrom};
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ extern crate log;
|
||||
use byteorder::{ByteOrder, LittleEndian, ReadBytesExt};
|
||||
use remain::sorted;
|
||||
use std::collections::btree_map::BTreeMap;
|
||||
use std::convert::TryInto;
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read, Seek, SeekFrom, Write};
|
||||
use std::mem::size_of;
|
||||
@@ -90,7 +91,7 @@ pub type Result<T> = std::result::Result<T, VhdxHeaderError>;
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct FileTypeIdentifier {
|
||||
pub _signature: u64,
|
||||
pub signature: u64,
|
||||
}
|
||||
|
||||
impl FileTypeIdentifier {
|
||||
@@ -98,14 +99,14 @@ impl FileTypeIdentifier {
|
||||
pub fn new(f: &mut File) -> Result<FileTypeIdentifier> {
|
||||
f.seek(SeekFrom::Start(FILE_START))
|
||||
.map_err(VhdxHeaderError::SeekFileTypeIdentifier)?;
|
||||
let _signature = f
|
||||
let signature = f
|
||||
.read_u64::<LittleEndian>()
|
||||
.map_err(VhdxHeaderError::ReadFileTypeIdentifier)?;
|
||||
if _signature != VHDX_SIGN {
|
||||
if signature != VHDX_SIGN {
|
||||
return Err(VhdxHeaderError::InvalidVHDXSign);
|
||||
}
|
||||
|
||||
Ok(FileTypeIdentifier { _signature })
|
||||
Ok(FileTypeIdentifier { signature })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -352,6 +353,12 @@ impl RegionTableEntry {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct RegionEntry {
|
||||
_start: u64,
|
||||
_end: u64,
|
||||
}
|
||||
|
||||
enum HeaderNo {
|
||||
First,
|
||||
Second,
|
||||
|
||||
@@ -6,21 +6,22 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
acpi_tables = { git = "https://github.com/rust-vmm/acpi_tables", branch = "main" }
|
||||
anyhow = "1.0.81"
|
||||
anyhow = "1.0.75"
|
||||
arch = { path = "../arch" }
|
||||
bitflags = "2.5.0"
|
||||
byteorder = "1.5.0"
|
||||
bitflags = "2.4.1"
|
||||
byteorder = "1.4.3"
|
||||
event_monitor = { path = "../event_monitor" }
|
||||
hypervisor = { path = "../hypervisor" }
|
||||
libc = "0.2.153"
|
||||
log = "0.4.21"
|
||||
libc = "0.2.147"
|
||||
log = "0.4.20"
|
||||
pci = { path = "../pci" }
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.40"
|
||||
tpm = { path = "../tpm" }
|
||||
versionize = "0.2.0"
|
||||
versionize_derive = "0.1.6"
|
||||
vm-allocator = { path = "../vm-allocator" }
|
||||
vm-device = { path = "../vm-device" }
|
||||
vm-memory = "0.14.1"
|
||||
vm-memory = "0.14.0"
|
||||
vm-migration = { path = "../vm-migration" }
|
||||
vmm-sys-util = "0.12.1"
|
||||
|
||||
|
||||
@@ -1,64 +0,0 @@
|
||||
// Copyright © 2023 Cyberus Technology
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
|
||||
//! Module for [`DebugconState`].
|
||||
|
||||
use std::io;
|
||||
use std::io::Write;
|
||||
use std::sync::{Arc, Barrier};
|
||||
use vm_device::BusDevice;
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
|
||||
/// I/O-port.
|
||||
pub const DEFAULT_PORT: u64 = 0xe9;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct DebugconState {}
|
||||
|
||||
/// Emulates a debug console similar to the QEMU debugcon device. This device
|
||||
/// is stateless and only prints the bytes (usually text) that are written to
|
||||
/// it.
|
||||
///
|
||||
/// This device is only available on x86.
|
||||
///
|
||||
/// Reference:
|
||||
/// - https://github.com/qemu/qemu/blob/master/hw/char/debugcon.c
|
||||
/// - https://phip1611.de/blog/how-to-use-qemus-debugcon-feature-and-write-to-a-file/
|
||||
pub struct DebugConsole {
|
||||
id: String,
|
||||
out: Box<dyn io::Write + Send>,
|
||||
}
|
||||
|
||||
impl DebugConsole {
|
||||
pub fn new(id: String, out: Box<dyn io::Write + Send>) -> Self {
|
||||
Self { id, out }
|
||||
}
|
||||
}
|
||||
|
||||
impl BusDevice for DebugConsole {
|
||||
fn read(&mut self, _base: u64, _offset: u64, _data: &mut [u8]) {}
|
||||
|
||||
fn write(&mut self, _base: u64, _offset: u64, data: &[u8]) -> Option<Arc<Barrier>> {
|
||||
if let Err(e) = self.out.write_all(data) {
|
||||
// unlikely
|
||||
error!("debug-console: failed writing data: {e:?}");
|
||||
}
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
impl Snapshottable for DebugConsole {
|
||||
fn id(&self) -> String {
|
||||
self.id.clone()
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&())
|
||||
}
|
||||
}
|
||||
|
||||
impl Pausable for DebugConsole {}
|
||||
impl Transportable for DebugConsole {}
|
||||
impl Migratable for DebugConsole {}
|
||||
@@ -11,16 +11,19 @@
|
||||
|
||||
use super::interrupt_controller::{Error, InterruptController};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::result;
|
||||
use std::sync::{Arc, Barrier};
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_device::interrupt::{
|
||||
InterruptIndex, InterruptManager, InterruptSourceConfig, InterruptSourceGroup,
|
||||
MsiIrqGroupConfig, MsiIrqSourceConfig,
|
||||
};
|
||||
use vm_device::BusDevice;
|
||||
use vm_memory::GuestAddress;
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
type Result<T> = result::Result<T, Error>;
|
||||
@@ -133,7 +136,7 @@ pub struct Ioapic {
|
||||
interrupt_source_group: Arc<dyn InterruptSourceGroup>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Versionize)]
|
||||
pub struct IoapicState {
|
||||
id_reg: u32,
|
||||
reg_sel: u32,
|
||||
@@ -141,6 +144,7 @@ pub struct IoapicState {
|
||||
used_entries: [bool; NUM_IOAPIC_PINS],
|
||||
apic_address: u64,
|
||||
}
|
||||
impl VersionMapped for IoapicState {}
|
||||
|
||||
impl BusDevice for Ioapic {
|
||||
fn read(&mut self, _base: u64, offset: u64, data: &mut [u8]) {
|
||||
@@ -440,7 +444,7 @@ impl Snapshottable for Ioapic {
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
use libc::{clock_gettime, gmtime_r, timespec, tm, CLOCK_REALTIME};
|
||||
use std::cmp::min;
|
||||
|
||||
@@ -8,13 +8,16 @@
|
||||
//!
|
||||
|
||||
use crate::{read_le_u32, write_le_u32};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::result;
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::{fmt, io};
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_device::interrupt::InterruptSourceGroup;
|
||||
use vm_device::BusDevice;
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
|
||||
const OFS_DATA: u64 = 0x400; // Data Register
|
||||
const GPIODIR: u64 = 0x400; // Direction Register
|
||||
@@ -86,7 +89,7 @@ pub struct Gpio {
|
||||
interrupt: Arc<dyn InterruptSourceGroup>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Versionize)]
|
||||
pub struct GpioState {
|
||||
data: u32,
|
||||
old_in_data: u32,
|
||||
@@ -99,6 +102,8 @@ pub struct GpioState {
|
||||
afsel: u32,
|
||||
}
|
||||
|
||||
impl VersionMapped for GpioState {}
|
||||
|
||||
impl Gpio {
|
||||
/// Constructs an PL061 GPIO device.
|
||||
pub fn new(
|
||||
@@ -323,7 +328,7 @@ impl Snapshottable for Gpio {
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -334,6 +339,8 @@ impl Migratable for Gpio {}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{read_le_u32, write_le_u32};
|
||||
use std::sync::Arc;
|
||||
use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
|
||||
@@ -329,9 +329,10 @@ impl BusDevice for Rtc {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::{
|
||||
read_be_u16, read_be_u32, read_le_i32, read_le_u16, read_le_u64, write_be_u16,
|
||||
write_be_u32, write_le_i32, write_le_u16, write_le_u64,
|
||||
read_be_u16, read_be_u32, read_le_i32, read_le_u16, read_le_u32, read_le_u64, write_be_u16,
|
||||
write_be_u32, write_le_i32, write_le_u16, write_le_u32, write_le_u64,
|
||||
};
|
||||
use std::sync::Arc;
|
||||
use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
|
||||
@@ -5,13 +5,16 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::VecDeque;
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::{io, result};
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_device::interrupt::InterruptSourceGroup;
|
||||
use vm_device::BusDevice;
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
use vmm_sys_util::errno::Result;
|
||||
|
||||
const LOOP_SIZE: usize = 0x40;
|
||||
@@ -71,7 +74,7 @@ pub struct Serial {
|
||||
out: Option<Box<dyn io::Write + Send>>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Versionize)]
|
||||
pub struct SerialState {
|
||||
interrupt_enable: u8,
|
||||
interrupt_identification: u8,
|
||||
@@ -83,6 +86,7 @@ pub struct SerialState {
|
||||
baud_divisor: u16,
|
||||
in_buffer: Vec<u8>,
|
||||
}
|
||||
impl VersionMapped for SerialState {}
|
||||
|
||||
impl Serial {
|
||||
pub fn new(
|
||||
@@ -330,7 +334,7 @@ impl Snapshottable for Serial {
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,7 +345,8 @@ impl Migratable for Serial {}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::sync::Mutex;
|
||||
use std::io;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
|
||||
@@ -7,15 +7,18 @@
|
||||
//!
|
||||
|
||||
use crate::{read_le_u32, write_le_u32};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::VecDeque;
|
||||
use std::fmt;
|
||||
use std::sync::{Arc, Barrier};
|
||||
use std::time::Instant;
|
||||
use std::{io, result};
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_device::interrupt::InterruptSourceGroup;
|
||||
use vm_device::BusDevice;
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
|
||||
/* Registers */
|
||||
const UARTDR: u64 = 0;
|
||||
@@ -91,7 +94,7 @@ pub struct Pl011 {
|
||||
timestamp: std::time::Instant,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Versionize)]
|
||||
pub struct Pl011State {
|
||||
flags: u32,
|
||||
lcr: u32,
|
||||
@@ -110,6 +113,8 @@ pub struct Pl011State {
|
||||
read_trigger: u32,
|
||||
}
|
||||
|
||||
impl VersionMapped for Pl011State {}
|
||||
|
||||
impl Pl011 {
|
||||
/// Constructs an AMBA PL011 UART device.
|
||||
pub fn new(
|
||||
@@ -449,7 +454,7 @@ impl Snapshottable for Pl011 {
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -460,7 +465,8 @@ impl Migratable for Pl011 {}
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::sync::Mutex;
|
||||
use std::io;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use vm_device::interrupt::{InterruptIndex, InterruptSourceConfig};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
|
||||
@@ -15,8 +15,6 @@ extern crate event_monitor;
|
||||
extern crate log;
|
||||
|
||||
pub mod acpi;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub mod debug_console;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
pub mod gic;
|
||||
pub mod interrupt_controller;
|
||||
|
||||
@@ -9,15 +9,18 @@ use pci::{
|
||||
PciClassCode, PciConfiguration, PciDevice, PciDeviceError, PciHeaderType, PciSubclass,
|
||||
PCI_CONFIGURATION_ID,
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::any::Any;
|
||||
use std::result;
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_allocator::{AddressAllocator, SystemAllocator};
|
||||
use vm_device::{BusDevice, Resource};
|
||||
use vm_memory::{Address, GuestAddress};
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
|
||||
const PVPANIC_VENDOR_ID: u16 = 0x1b36;
|
||||
const PVPANIC_DEVICE_ID: u16 = 0x0011;
|
||||
@@ -57,20 +60,23 @@ pub struct PvPanicDevice {
|
||||
bar_regions: Vec<PciBarConfiguration>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Versionize)]
|
||||
pub struct PvPanicDeviceState {
|
||||
events: u8,
|
||||
}
|
||||
|
||||
impl VersionMapped for PvPanicDeviceState {}
|
||||
|
||||
impl PvPanicDevice {
|
||||
pub fn new(id: String, snapshot: Option<Snapshot>) -> Result<Self, PvPanicError> {
|
||||
let pci_configuration_state =
|
||||
vm_migration::state_from_id(snapshot.as_ref(), PCI_CONFIGURATION_ID).map_err(|e| {
|
||||
PvPanicError::RetrievePciConfigurationState(anyhow!(
|
||||
"Failed to get PciConfigurationState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
vm_migration::versioned_state_from_id(snapshot.as_ref(), PCI_CONFIGURATION_ID)
|
||||
.map_err(|e| {
|
||||
PvPanicError::RetrievePciConfigurationState(anyhow!(
|
||||
"Failed to get PciConfigurationState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
|
||||
let mut configuration = PciConfiguration::new(
|
||||
PVPANIC_VENDOR_ID,
|
||||
@@ -91,7 +97,7 @@ impl PvPanicDevice {
|
||||
|
||||
let state: Option<PvPanicDeviceState> = snapshot
|
||||
.as_ref()
|
||||
.map(|s| s.to_state())
|
||||
.map(|s| s.to_versioned_state())
|
||||
.transpose()
|
||||
.map_err(|e| {
|
||||
PvPanicError::CreatePvPanicDevice(anyhow!(
|
||||
@@ -204,7 +210,7 @@ impl PciDevice for PvPanicDevice {
|
||||
}
|
||||
|
||||
bars.push(bar);
|
||||
self.bar_regions.clone_from(&bars);
|
||||
self.bar_regions = bars.clone();
|
||||
|
||||
Ok(bars)
|
||||
}
|
||||
@@ -253,7 +259,7 @@ impl Snapshottable for PvPanicDevice {
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
let mut snapshot = Snapshot::new_from_state(&self.state())?;
|
||||
let mut snapshot = Snapshot::new_from_versioned_state(&self.state())?;
|
||||
|
||||
// Snapshot PciConfiguration
|
||||
snapshot.add_snapshot(self.configuration.id(), self.configuration.snapshot()?);
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
All documentations (e.g. files with extension `.md`) in this repository is
|
||||
covered by the following license:
|
||||
The documentation in this directory is covered by the following license:
|
||||
|
||||
Attribution 4.0 International
|
||||
|
||||
13
docs/api.md
13
docs/api.md
@@ -110,7 +110,6 @@ The Cloud Hypervisor API exposes the following actions through its endpoints:
|
||||
| Add vsock device to the VM | `/vm.add-vsock` | `/schemas/VsockConfig` | `/schemas/PciDeviceInfo` | The VM is booted |
|
||||
| Remove device from the VM | `/vm.remove-device` | `/schemas/VmRemoveDevice` | N/A | The VM is booted |
|
||||
| Dump the VM counters | `/vm.counters` | N/A | `/schemas/VmCounters` | The VM is booted |
|
||||
| Inject an NMI | `/vm.nmi` | N/A | N/A | The VM is booted |
|
||||
| Prepare to receive a migration | `/vm.receive-migration` | `/schemas/ReceiveMigrationData` | N/A | N/A |
|
||||
| Start to send migration to target | `/vm.send-migration` | `/schemas/SendMigrationData` | N/A | The VM is booted and (shared mem or hugepages enabled) |
|
||||
|
||||
@@ -148,7 +147,7 @@ We want to create a virtual machine with the following characteristics:
|
||||
`/opt/clh/images/focal-server-cloudimg-amd64.raw`
|
||||
|
||||
```shell
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
|
||||
curl --unix-socket /tmp/cloud-hypervisor.sock -i \
|
||||
-X PUT 'http://localhost/api/v1/vm.create' \
|
||||
@@ -168,7 +167,7 @@ curl --unix-socket /tmp/cloud-hypervisor.sock -i \
|
||||
Once the VM is created, we can boot it:
|
||||
|
||||
```shell
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
|
||||
curl --unix-socket /tmp/cloud-hypervisor.sock -i -X PUT 'http://localhost/api/v1/vm.boot'
|
||||
```
|
||||
@@ -178,7 +177,7 @@ curl --unix-socket /tmp/cloud-hypervisor.sock -i -X PUT 'http://localhost/api/v1
|
||||
We can fetch information about any VM, as soon as it's created:
|
||||
|
||||
```shell
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
|
||||
curl --unix-socket /tmp/cloud-hypervisor.sock -i \
|
||||
-X GET 'http://localhost/api/v1/vm.info' \
|
||||
@@ -190,7 +189,7 @@ curl --unix-socket /tmp/cloud-hypervisor.sock -i \
|
||||
We can reboot a VM that's already booted:
|
||||
|
||||
```shell
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
|
||||
curl --unix-socket /tmp/cloud-hypervisor.sock -i -X PUT 'http://localhost/api/v1/vm.reboot'
|
||||
```
|
||||
@@ -200,7 +199,7 @@ curl --unix-socket /tmp/cloud-hypervisor.sock -i -X PUT 'http://localhost/api/v1
|
||||
Once booted, we can shut a VM down from the REST API:
|
||||
|
||||
```shell
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
|
||||
curl --unix-socket /tmp/cloud-hypervisor.sock -i -X PUT 'http://localhost/api/v1/vm.shutdown'
|
||||
```
|
||||
@@ -386,7 +385,7 @@ APIs work together, let's look at a complete VM creation flow, from the
|
||||
[REST API](#rest-api) in order to creates a virtual machine:
|
||||
```
|
||||
shell
|
||||
#!/usr/bin/env bash
|
||||
#!/bin/bash
|
||||
|
||||
curl --unix-socket /tmp/cloud-hypervisor.sock -i \
|
||||
-X PUT 'http://localhost/api/v1/vm.create' \
|
||||
|
||||
@@ -1,16 +1,7 @@
|
||||
# `cloud-hypervisor` debug IO ports
|
||||
# `cloud-hypervisor` debug IO port
|
||||
|
||||
When running x86 guests, `cloud-hypervisor` provides different kinds of debug ports:
|
||||
- [`0x80` debug port](https://www.intel.com/content/www/us/en/support/articles/000005500/boards-and-kits.html)
|
||||
- Debug console (by default at `0xe9`).
|
||||
- Firmware debug port at `0x402`.
|
||||
|
||||
All of them can be used to trace user-defined guest events and all of them can
|
||||
be used simultaneously.
|
||||
|
||||
## Debug Ports Overview
|
||||
|
||||
### `0x80` I/O port
|
||||
`cloud-hypervisor` uses the [`0x80`](https://www.intel.com/content/www/us/en/support/articles/000005500/boards-and-kits.html)
|
||||
I/O port to trace user defined guest events.
|
||||
|
||||
Whenever the guest write one byte between `0x0` and `0xF` on this particular
|
||||
I/O port, `cloud-hypervisor` will log and timestamp that event at the `debug`
|
||||
@@ -39,7 +30,7 @@ guest will have `cloud-hypervisor` generate timestamped logs of all those steps.
|
||||
That provides a basic but convenient way of measuring not only the overall guest
|
||||
boot time but all intermediate steps as well.
|
||||
|
||||
#### Logging
|
||||
## Logging
|
||||
|
||||
Assuming parts of the guest software stack have been instrumented to use the
|
||||
`cloud-hypervisor` debug I/O port, we may want to gather the related logs.
|
||||
@@ -68,29 +59,3 @@ $ grep "Debug I/O port" /tmp/ch-fw.log
|
||||
cloud-hypervisor: 19.762449ms: DEBUG:vmm/src/vm.rs:510 -- [Debug I/O port: Firmware code 0x0] 0.019004 seconds
|
||||
cloud-hypervisor: 403.499628ms: DEBUG:vmm/src/vm.rs:510 -- [Debug I/O port: Firmware code 0x1] 0.402744 seconds
|
||||
```
|
||||
|
||||
### Debug console port
|
||||
|
||||
The debug console is inspired by QEMU and Bochs, which have a similar feature.
|
||||
By default, the I/O port `0xe9` is used. This port can be configured like a
|
||||
console. Thus, it can print to a tty, a file, or a pty, for example.
|
||||
|
||||
### Firmware debug port
|
||||
|
||||
The firmware debug port is also a simple port that prints all bytes written to
|
||||
it. The firmware debug port only prints to stdout.
|
||||
|
||||
## When do I need these ports?
|
||||
|
||||
The ports are on the one hand interesting for firmware or kernel developers, as
|
||||
they provide an easy way to print debug information from within a guest.
|
||||
Furthermore, you can patch "normal" software to measure certain events, such as
|
||||
the boot time of a guest.
|
||||
|
||||
## Which port should I choose?
|
||||
|
||||
The `0x80` debug port and the port of the firmware debug device are always
|
||||
available. The debug console must be activated via the command line, but
|
||||
provides more configuration options.
|
||||
|
||||
You can use different ports for different aspect of your logging messages.
|
||||
@@ -103,7 +103,7 @@ firmware:
|
||||
### TDShim
|
||||
|
||||
> **Note**
|
||||
> The latest version of TDShim being tested is [_v0.8.0_](https://github.com/confidential-containers/td-shim/releases/tag/v0.8.0).
|
||||
> The latest version of TDShim being tested is [_66bb334_](https://github.com/confidential-containers/td-shim/tree/66bb33451befbf1291abe3cfea7ee9e99d922b0d).
|
||||
|
||||
This is a lightweight version of the TDVF, written in Rust and designed for
|
||||
direct kernel boot, which is useful for containers use cases.
|
||||
@@ -113,7 +113,7 @@ and `LLVM` first. The TDshim can be build as follows:
|
||||
```bash
|
||||
git clone https://github.com/confidential-containers/td-shim
|
||||
cd td-shim
|
||||
git checkout v0.8.0
|
||||
git checkout 66bb33451befbf1291abe3cfea7ee9e99d922b0d
|
||||
cargo install cargo-xbuild
|
||||
export CC=clang
|
||||
export AR=llvm-ar
|
||||
@@ -121,13 +121,15 @@ export CC_x86_64_unknown_none=clang
|
||||
export AR_x86_64_unknown_none=llvm-ar
|
||||
git submodule update --init --recursive
|
||||
./sh_script/preparation.sh
|
||||
cargo image --release
|
||||
cargo xbuild -p td-shim --target x86_64-unknown-none --release --features=main,tdx
|
||||
cargo run -p td-shim-tools --bin td-shim-ld --features=linker -- target/x86_64-unknown-none/release/ResetVector.bin target/x86_64-unknown-none/release/td-shim -o target/release/final.bin
|
||||
```
|
||||
|
||||
If debug logs from the TDShim is needed, here are the alternative
|
||||
commands:
|
||||
```bash
|
||||
cargo image
|
||||
cargo xbuild -p td-shim --target x86_64-unknown-none --features=main,tdx
|
||||
cargo run -p td-shim-tools --bin td-shim-ld --features=linker -- target/x86_64-unknown-none/debug/ResetVector.bin target/x86_64-unknown-none/debug/td-shim -o target/debug/final.bin
|
||||
```
|
||||
|
||||
And run a TDX VM by providing the firmware previously built, along with a guest
|
||||
|
||||
@@ -42,14 +42,3 @@ actual rate limit users get can be as low as
|
||||
generally advisable to keep `bw/ops_refill_time` larger than `100 ms`
|
||||
(`cool_down_time`) to make sure the actual rate limit is close to users'
|
||||
expectation ("refill-rate").
|
||||
|
||||
## Rate Limit Groups
|
||||
It is possible to throttle the aggregate bandwidth or operations
|
||||
of multiple virtio-blk devices using a `rate_limit_group`. virtio-blk devices may be
|
||||
dynamically added and removed from a `rate_limit_group`. The following example
|
||||
demonstrates how to throttle the aggregate bandwidth of two disks to 10 MiB/s.
|
||||
```
|
||||
--disk path=disk0.raw,rate_limit_group=group0 \
|
||||
path=disk1.raw,rate_limit_group=group0 \
|
||||
--rate-limit-group bw_size=1048576,bw_refill_time,bw_refill_time=100
|
||||
```
|
||||
|
||||
@@ -60,7 +60,10 @@ implement a full emulation of a physical IOMMU.
|
||||
|
||||
### Kernel
|
||||
|
||||
As of Kernel 5.14, virtio-iommu is available for both X86-64 and Aarch64.
|
||||
Since virtio-iommu has landed partially into the version 5.3 of the Linux
|
||||
kernel, a special branch is needed to get things working with Cloud Hypervisor.
|
||||
By partially, we are talking about x86 specifically, as it is already fully
|
||||
functional for ARM architectures.
|
||||
|
||||
## Usage
|
||||
|
||||
|
||||
62
docs/vfio.md
62
docs/vfio.md
@@ -122,64 +122,4 @@ $ ls /sys/kernel/iommu_groups/22/devices/
|
||||
|
||||
This means these two devices are under the same IOMMU group 22. In such case,
|
||||
it is important to bind both devices to VFIO and pass them both through the
|
||||
VM, otherwise this could cause some functional and security issues.
|
||||
|
||||
### Advanced Configuration Options
|
||||
|
||||
When using NVIDIA GPUs in a VFIO passthrough configuration, advanced
|
||||
configuration options are supported to enable GPUDirect P2P DMA over
|
||||
PCIe. When enabled, loads and stores between GPUs use native PCIe
|
||||
peer-to-peer transactions instead of a shared memory buffer. This drastically
|
||||
decreases P2P latency between GPUs. This functionality is supported by
|
||||
cloud-hypervisor on NVIDIA Turing, Ampere, Hopper, and Lovelace GPUs.
|
||||
|
||||
The NVIDIA driver does not enable GPUDirect P2P over PCIe within guests
|
||||
by default because hardware support for routing P2P TLP between PCIe root
|
||||
ports is optional. PCIe P2P should always be supported between devices
|
||||
on the same PCIe switch. The `x_nv_gpudirect_clique` config argument may
|
||||
be used to signal support for PCIe P2P traffic between NVIDIA VFIO endpoints.
|
||||
The guest driver assumes that P2P traffic is supported between all endpoints
|
||||
that are part of the same clique.
|
||||
```
|
||||
--device path=/sys/bus/pci/devices/0000:01:00.0/,x_nv_gpudirect_clique=0
|
||||
```
|
||||
|
||||
The following command can be run on the guest to verify that GPUDirect P2P is
|
||||
correctly enabled.
|
||||
```
|
||||
nvidia-smi topo -p2p r
|
||||
GPU0 GPU1 GPU2 GPU3 GPU4 GPU5 GPU6 GPU7
|
||||
GPU0 X OK OK OK OK OK OK OK
|
||||
GPU1 OK X OK OK OK OK OK OK
|
||||
GPU2 OK OK X OK OK OK OK OK
|
||||
GPU3 OK OK OK X OK OK OK OK
|
||||
GPU4 OK OK OK OK X OK OK OK
|
||||
GPU5 OK OK OK OK OK X OK OK
|
||||
GPU6 OK OK OK OK OK OK X OK
|
||||
GPU7 OK OK OK OK OK OK OK X
|
||||
```
|
||||
|
||||
Some VFIO devices have a 32-bit mmio BAR. When using many such devices, it is
|
||||
possible to exhaust the 32-bit mmio space available on a PCI segment. The
|
||||
following example demonstrates an example device with a 16 MiB 32-bit mmio BAR.
|
||||
```
|
||||
lspci -s 0000:01:00.0 -v
|
||||
0000:01:00.0 3D controller: NVIDIA Corporation Device 26b9 (rev a1)
|
||||
[...]
|
||||
Memory at f9000000 (32-bit, non-prefetchable) [size=16M]
|
||||
Memory at 46000000000 (64-bit, prefetchable) [size=64G]
|
||||
Memory at 48040000000 (64-bit, prefetchable) [size=32M]
|
||||
[...]
|
||||
```
|
||||
|
||||
When using multiple PCI segments, the 32-bit mmio address space available to
|
||||
be allocated to VFIO devices is equally split between all PCI segments by
|
||||
default. This can be tuned with the `--pci-segment` flag. The following example
|
||||
demonstrates a guest with two PCI segments. 2/3 of the 32-bit mmio address
|
||||
space is available for use by devices on PCI segment 0 and 1/3 of the 32-bit
|
||||
mmio address space is available for use by devices on PCI segment 1.
|
||||
```
|
||||
--platform num_pci_segments=2
|
||||
--pci-segment pci_segment=0,mmio32_aperture_weight=2
|
||||
--pci-segment pci_segment=1,mmio32_aperture_weight=1
|
||||
```
|
||||
VM, otherwise this could cause some functional and security issues.
|
||||
@@ -2,8 +2,8 @@
|
||||
|
||||
The purpose of this document is to illustrate how to test vhost-user-net
|
||||
in cloud-hypervisor with OVS/DPDK as the backend. This document was
|
||||
tested with Open vSwitch v2.17.8, DPDK v21.11.4, and Cloud Hypervisor
|
||||
v37.0 on Ubuntu 22.04.3 (host kernel v5.15.0).
|
||||
tested with Open vSwitch v2.13.1, DPDK v19.11.3, and Cloud Hypervisor
|
||||
v15.0 on Ubuntu 20.04.1 (host kernel v5.4.0).
|
||||
|
||||
## Framework
|
||||
|
||||
@@ -74,8 +74,8 @@ Here is an example how to create a bridge and add two DPDK ports to it
|
||||
# create a bridge
|
||||
ovs-vsctl add-br ovsbr0 -- set bridge ovsbr0 datapath_type=netdev
|
||||
# create two DPDK ports and add them to the bridge
|
||||
ovs-vsctl add-port ovsbr0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuserclient options:vhost-server-path=/tmp/vhost-user1
|
||||
ovs-vsctl add-port ovsbr0 vhost-user2 -- set Interface vhost-user2 type=dpdkvhostuserclient options:vhost-server-path=/tmp/vhost-user2
|
||||
ovs-vsctl add-port ovsbr0 vhost-user1 -- set Interface vhost-user1 type=dpdkvhostuser
|
||||
ovs-vsctl add-port ovsbr0 vhost-user2 -- set Interface vhost-user2 type=dpdkvhostuser
|
||||
# set the number of rx queues
|
||||
ovs-vsctl set Interface vhost-user1 options:n_rxq=2
|
||||
ovs-vsctl set Interface vhost-user2 options:n_rxq=2
|
||||
@@ -92,7 +92,7 @@ VMs run in client mode. They connect to the socket created by the `dpdkvhostuser
|
||||
--kernel vmlinux \
|
||||
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
|
||||
--disk path=focal-server-cloudimg-amd64.raw \
|
||||
--net mac=52:54:00:02:d9:01,vhost_user=true,socket=/tmp/vhost-user1,num_queues=4,vhost_mode=server
|
||||
--net mac=52:54:00:02:d9:01,vhost_user=true,socket=/var/run/openvswitch/vhost-user1,num_queues=4
|
||||
|
||||
# From another terminal. We need to give the cloud-hypervisor binary the NET_ADMIN capabilities for it to set TAP interfaces up on the host.
|
||||
./cloud-hypervisor \
|
||||
@@ -101,21 +101,21 @@ VMs run in client mode. They connect to the socket created by the `dpdkvhostuser
|
||||
--kernel vmlinux \
|
||||
--cmdline "console=ttyS0 console=hvc0 root=/dev/vda1 rw" \
|
||||
--disk path=focal-server-cloudimg-amd64.raw \
|
||||
--net mac=52:54:20:11:C5:02,vhost_user=true,socket=/tmp/vhost-user2,num_queues=4,vhost_mode=server
|
||||
--net mac=52:54:20:11:C5:02,vhost_user=true,socket=/var/run/openvswitch/vhost-user2,num_queues=4
|
||||
```
|
||||
|
||||
_Setup VM1_
|
||||
```bash
|
||||
# From inside the guest
|
||||
sudo ip addr add 172.100.0.1/24 dev ens3
|
||||
sudo ip link set up dev ens3
|
||||
sudo ip addr add 172.100.0.1/24 dev ens2
|
||||
sudo ip link set up dev ens2
|
||||
```
|
||||
|
||||
_Setup VM2_
|
||||
```bash
|
||||
# From inside the guest
|
||||
sudo ip addr add 172.100.0.2/24 dev ens3
|
||||
sudo ip link set up dev ens3
|
||||
sudo ip addr add 172.100.0.2/24 dev ens2
|
||||
sudo ip link set up dev ens2
|
||||
```
|
||||
|
||||
_Ping VM1 from VM2_
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# VSOCK support
|
||||
|
||||
VSOCK provides a way for guest and host to communicate through a socket. `cloud-hypervisor` only supports stream VSOCK sockets.
|
||||
VSOCK provides a way for guest and host to communicate through a socket. VSOCK sockets support both stream and datagram types.
|
||||
|
||||
The `virtio-vsock` is based on the [Firecracker](https://github.com/firecracker-microvm/firecracker/blob/main/docs/vsock.md) implementation, where additional details can be found.
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ authors = ["The Cloud Hypervisor Authors"]
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
flume = "0.11.0"
|
||||
libc = "0.2.153"
|
||||
once_cell = "1.19.0"
|
||||
serde = { version = "1.0.197", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.115"
|
||||
flume = "0.10.14"
|
||||
libc = "0.2.147"
|
||||
once_cell = "1.18.0"
|
||||
serde = { version = "1.0.168", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.107"
|
||||
|
||||
361
fuzz/Cargo.lock
generated
361
fuzz/Cargo.lock
generated
@@ -5,16 +5,16 @@ version = 3
|
||||
[[package]]
|
||||
name = "acpi_tables"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/rust-vmm/acpi_tables?branch=main#ca1a473fe73cdd8eb49c1449faad7aaac06f32c2"
|
||||
source = "git+https://github.com/rust-vmm/acpi_tables?branch=main#1a733bf690ccc10bdfeacad33e3c9f6cce0008fd"
|
||||
dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "anstream"
|
||||
version = "0.6.13"
|
||||
version = "0.6.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d96bd03f33fe50a863e394ee9718a706f988b9079b20c3784fb726e7678b62fb"
|
||||
checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"anstyle-parse",
|
||||
@@ -26,9 +26,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anstyle"
|
||||
version = "1.0.6"
|
||||
version = "1.0.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8901269c6307e8d93993578286ac0edf7f195079ffff5ebdeea6a59ffb7e36bc"
|
||||
checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
|
||||
|
||||
[[package]]
|
||||
name = "anstyle-parse"
|
||||
@@ -60,9 +60,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "anyhow"
|
||||
version = "1.0.82"
|
||||
version = "1.0.79"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f538837af36e6f6a9be0faa67f9a314f8119e4e4b5867c6ab40ed60360142519"
|
||||
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca"
|
||||
|
||||
[[package]]
|
||||
name = "api_client"
|
||||
@@ -79,9 +79,9 @@ checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110"
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "1.7.1"
|
||||
version = "1.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457"
|
||||
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
|
||||
|
||||
[[package]]
|
||||
name = "arch"
|
||||
@@ -97,6 +97,8 @@ dependencies = [
|
||||
"serde",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vm-fdt",
|
||||
"vm-memory",
|
||||
"vm-migration",
|
||||
@@ -105,9 +107,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.2.0"
|
||||
version = "1.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80"
|
||||
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
@@ -117,9 +128,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
|
||||
|
||||
[[package]]
|
||||
name = "bitflags"
|
||||
version = "2.5.0"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cf4b9d6a944f767f8e5e0db018570623c85f3d925ac718db4e06d0187adb21c1"
|
||||
checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
|
||||
|
||||
[[package]]
|
||||
name = "block"
|
||||
@@ -131,10 +142,11 @@ dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"remain",
|
||||
"serde",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
"uuid",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"virtio-bindings",
|
||||
"virtio-queue",
|
||||
"vm-memory",
|
||||
@@ -144,9 +156,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.16.0"
|
||||
version = "3.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "79296716171880943b8470b5f8d03aa55eb2e645a4874bdbb28adb49162e012c"
|
||||
checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
@@ -156,9 +168,9 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b"
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.0.92"
|
||||
version = "1.0.83"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2678b2e3449475e95b0aa6f9b506a28e61b3dc8996592b983695e8ebb58a8b41"
|
||||
checksum = "f1174fb0b6ec23863f8b971027804a42614e347eafb0a95bf0b12cdae21fc4d0"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
@@ -172,34 +184,34 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.4"
|
||||
version = "4.4.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90bc066a67923782aa8515dbaea16946c5bcc5addbd668bb80af688e53e548a0"
|
||||
checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c"
|
||||
dependencies = [
|
||||
"clap_builder",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_builder"
|
||||
version = "4.5.2"
|
||||
version = "4.4.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae129e2e766ae0ec03484e609954119f123cc1fe650337e155d03b022f24f7b4"
|
||||
checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7"
|
||||
dependencies = [
|
||||
"anstream",
|
||||
"anstyle",
|
||||
"clap_lex",
|
||||
"strsim 0.11.1",
|
||||
"strsim",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "clap_lex"
|
||||
version = "0.7.0"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "98cc8fbded0c607b7ba9dd60cd98df59af97e84d24e49c8557331cfc26d301ce"
|
||||
checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
|
||||
|
||||
[[package]]
|
||||
name = "cloud-hypervisor"
|
||||
version = "38.0.0"
|
||||
version = "37.0.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"api_client",
|
||||
@@ -262,10 +274,16 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.8"
|
||||
name = "crc64"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54e36fcd13ed84ffdfda6f5be89b31287cbb80c439841fe69e04841435464391"
|
||||
checksum = "2707e3afba5e19b75d582d88bc79237418f2a2a2d673d01cf9b03633b46e98f3"
|
||||
|
||||
[[package]]
|
||||
name = "darling"
|
||||
version = "0.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0209d94da627ab5605dcccf08bb18afa5009cfbef48d8a8b7d7bdbc79be25c5e"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"darling_macro",
|
||||
@@ -273,27 +291,27 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "darling_core"
|
||||
version = "0.20.8"
|
||||
version = "0.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c2cf1c23a687a1feeb728783b993c4e1ad83d99f351801977dd809b48d0a70f"
|
||||
checksum = "177e3443818124b357d8e76f53be906d60937f0d3a90773a664fa63fa253e621"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim 0.10.0",
|
||||
"syn",
|
||||
"strsim",
|
||||
"syn 2.0.47",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "darling_macro"
|
||||
version = "0.20.8"
|
||||
version = "0.20.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a668eda54683121533a393014d8692171709ff57a7d61f187b6e782719f8933f"
|
||||
checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.47",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -309,16 +327,17 @@ dependencies = [
|
||||
"acpi_tables",
|
||||
"anyhow",
|
||||
"arch",
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.4.1",
|
||||
"byteorder",
|
||||
"event_monitor",
|
||||
"hypervisor",
|
||||
"libc",
|
||||
"log",
|
||||
"pci",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"tpm",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vm-allocator",
|
||||
"vm-device",
|
||||
"vm-memory",
|
||||
@@ -332,7 +351,7 @@ version = "4.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "74351c3392ea1ff6cd2628e0042d268ac2371cb613252ff383b6dfa50d22fa79"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.4.1",
|
||||
"libc",
|
||||
]
|
||||
|
||||
@@ -355,13 +374,14 @@ checksum = "784a4df722dc6267a04af36895398f59d21d07dce47232adf31ec0ff2fa45e67"
|
||||
|
||||
[[package]]
|
||||
name = "flume"
|
||||
version = "0.11.0"
|
||||
version = "0.10.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181"
|
||||
checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577"
|
||||
dependencies = [
|
||||
"futures-core",
|
||||
"futures-sink",
|
||||
"nanorand",
|
||||
"pin-project",
|
||||
"spin",
|
||||
]
|
||||
|
||||
@@ -385,9 +405,9 @@ checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5"
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.14"
|
||||
version = "0.2.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94b22e06ecb0110981051723910cbf0b5f5e09a2062dd7663334ee79a9d1286c"
|
||||
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"js-sys",
|
||||
@@ -422,9 +442,9 @@ checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.6.3"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9febecd4aebbe9c7c23c8e536e966805fdf09944c8a915e7991ee51acb67087"
|
||||
checksum = "460648e47a07a43110fbfa2e0b14afb2be920093c31e5dccc50e49568e099762"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"libc",
|
||||
@@ -432,46 +452,45 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "itoa"
|
||||
version = "1.0.11"
|
||||
version = "1.0.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "49f1f14873335454500d59611f1cf4a4b0f786f9ac11f4312a78e4cf2566695b"
|
||||
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c"
|
||||
|
||||
[[package]]
|
||||
name = "jobserver"
|
||||
version = "0.1.30"
|
||||
version = "0.1.27"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "685a7d121ee3f65ae4fddd72b25a04bb36b6af81bc0828f7d5434c0fe60fa3a2"
|
||||
checksum = "8c37f63953c4c63420ed5fd3d6d398c719489b9f872b9fa683262f8edd363c7d"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.69"
|
||||
version = "0.3.66"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "29c15563dc2726973df627357ce0c9ddddbea194836909d655df6a75d2cf296d"
|
||||
checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kvm-bindings"
|
||||
version = "0.8.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a82e7e8725a39a0015e511a46cc1f7d90cecc180db1610c4d0d4339a9e48bd21"
|
||||
version = "0.7.0"
|
||||
source = "git+https://github.com/cloud-hypervisor/kvm-bindings?branch=ch-live-upgrade-stable-37.x#f03fc575cdf20c3af9ca3d4d203f171943d95be4"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"vmm-sys-util",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "kvm-ioctls"
|
||||
version = "0.17.0"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bedae2ca4a531bebe311abaf9691f5cc14eaa21475243caa2e39c43bb872947d"
|
||||
checksum = "9002dff009755414f22b962ec6ae6980b07d6d8b06e5297b1062019d72bd6a8c"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.4.1",
|
||||
"kvm-bindings",
|
||||
"libc",
|
||||
"vmm-sys-util",
|
||||
@@ -479,9 +498,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.153"
|
||||
version = "0.2.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c198f91728a82281a64e1f4f9eeb25d82cb32a5de251c6bd1b5154d63a8e7bd"
|
||||
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
|
||||
|
||||
[[package]]
|
||||
name = "libfuzzer-sys"
|
||||
@@ -515,14 +534,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.21"
|
||||
version = "0.4.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||
|
||||
[[package]]
|
||||
name = "micro_http"
|
||||
version = "0.1.0"
|
||||
source = "git+https://github.com/firecracker-microvm/micro-http?branch=main#ef43cef7162a55a6790d528a5e76b4fe2da22de0"
|
||||
source = "git+https://github.com/firecracker-microvm/micro-http?branch=main#e75dfa1eeea23b69caa7407bc2c3a76d7b7262fb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"vmm-sys-util",
|
||||
@@ -556,6 +575,8 @@ dependencies = [
|
||||
"rate_limiter",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"virtio-bindings",
|
||||
"virtio-queue",
|
||||
"vm-memory",
|
||||
@@ -584,6 +605,8 @@ dependencies = [
|
||||
"log",
|
||||
"serde",
|
||||
"thiserror",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vfio-bindings",
|
||||
"vfio-ioctls",
|
||||
"vfio_user",
|
||||
@@ -595,19 +618,39 @@ dependencies = [
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.81"
|
||||
name = "pin-project"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba"
|
||||
checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422"
|
||||
dependencies = [
|
||||
"pin-project-internal",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project-internal"
|
||||
version = "1.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.47",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.76"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
|
||||
dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.36"
|
||||
version = "1.0.35"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7"
|
||||
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
]
|
||||
@@ -616,7 +659,6 @@ dependencies = [
|
||||
name = "rate_limiter"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"epoll",
|
||||
"libc",
|
||||
"log",
|
||||
"thiserror",
|
||||
@@ -625,20 +667,20 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "remain"
|
||||
version = "0.2.13"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ad9f2390298a947ee0aa6073d440e221c0726188cfbcdf9604addb6ee393eb4a"
|
||||
checksum = "1ad5e011230cad274d0532460c5ab69828ea47ae75681b42a841663efffaf794"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.47",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ryu"
|
||||
version = "1.0.17"
|
||||
version = "1.0.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e86697c916019a8588c99b5fac3cead74ec0b4b819707a682fd4d23fa0ce1ba1"
|
||||
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c"
|
||||
|
||||
[[package]]
|
||||
name = "scopeguard"
|
||||
@@ -657,29 +699,29 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde"
|
||||
version = "1.0.198"
|
||||
version = "1.0.195"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9846a40c979031340571da2545a4e5b7c4163bdae79b301d5f86d03979451fcc"
|
||||
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
|
||||
dependencies = [
|
||||
"serde_derive",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_derive"
|
||||
version = "1.0.198"
|
||||
version = "1.0.195"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e88edab869b01783ba905e7d0153f9fc1a6505a96e4ad3018011eedb838566d9"
|
||||
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.47",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.115"
|
||||
version = "1.0.111"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12dc5c46daa8e9fdf4f5e71b6cf9a53f2487da0e86e55808e2d35539666497dd"
|
||||
checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
@@ -688,25 +730,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_with"
|
||||
version = "3.8.0"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2c85f8e96d1d6857f13768fcbd895fcb06225510022a2774ed8b5150581847b0"
|
||||
checksum = "64cd236ccc1b7a29e7e2739f27c0b2dd199804abc4290e32f59f3b68d6405c23"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_with_macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_with_macros"
|
||||
version = "3.8.0"
|
||||
version = "3.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8b3a576c4eb2924262d5951a3b737ccaf16c931e39a2810c36f9a7e25575557"
|
||||
checksum = "93634eb5f75a2323b16de4748022ac4297f9e76b6dced2be287a099f41b5e788"
|
||||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.47",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -725,18 +766,18 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "signal-hook-registry"
|
||||
version = "1.4.2"
|
||||
version = "1.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1"
|
||||
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "smallvec"
|
||||
version = "1.13.2"
|
||||
version = "1.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67"
|
||||
checksum = "2593d31f82ead8df961d8bd23a64c2ccf2eb5dd34b0a34bfb4dd54011c72009e"
|
||||
|
||||
[[package]]
|
||||
name = "spin"
|
||||
@@ -754,16 +795,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
|
||||
|
||||
[[package]]
|
||||
name = "strsim"
|
||||
version = "0.11.1"
|
||||
name = "syn"
|
||||
version = "1.0.109"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
|
||||
checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "2.0.58"
|
||||
version = "2.0.47"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "44cfb93f38070beee36b3fef7d4f5a16f27751d94b187b666a5cc5e9b0d30687"
|
||||
checksum = "1726efe18f42ae774cc644f330953a5e7b3c3003d3edcecf18850fe9d4dd9afb"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@@ -772,22 +818,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.58"
|
||||
version = "1.0.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "03468839009160513471e86a034bb2c5c0e4baae3b43f79ffc55c4a5427b3297"
|
||||
checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.58"
|
||||
version = "1.0.56"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c61f3ba182994efc43764a46c018c347bc492c79f024e705f46567b418f6d4f7"
|
||||
checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.47",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -828,17 +874,44 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
|
||||
|
||||
[[package]]
|
||||
name = "uuid"
|
||||
version = "1.8.0"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a183cf7feeba97b4dd1c0d46788634f6221d87fa961b305bed08c851829efcc0"
|
||||
checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "versionize"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "62929d59c7f6730b7298fcb363760550f4db6e353fbac4076d447d0e82799d6d"
|
||||
dependencies = [
|
||||
"bincode",
|
||||
"crc64",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"syn 1.0.109",
|
||||
"versionize_derive",
|
||||
"vmm-sys-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "versionize_derive"
|
||||
version = "0.1.6"
|
||||
source = "git+https://github.com/cloud-hypervisor/versionize_derive?branch=ch-0.1.6#7906da996152e2d0ab08f5526440683bf3ca7834"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vfio-bindings"
|
||||
version = "0.4.0"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#da8c5b67095fb70f5ef237ca63d316219888f015"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#0daff4d4c159e842cf18b8b90457a45032b2df5a"
|
||||
dependencies = [
|
||||
"vmm-sys-util",
|
||||
]
|
||||
@@ -846,7 +919,7 @@ dependencies = [
|
||||
[[package]]
|
||||
name = "vfio-ioctls"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#da8c5b67095fb70f5ef237ca63d316219888f015"
|
||||
source = "git+https://github.com/rust-vmm/vfio?branch=main#0daff4d4c159e842cf18b8b90457a45032b2df5a"
|
||||
dependencies = [
|
||||
"byteorder",
|
||||
"kvm-bindings",
|
||||
@@ -882,7 +955,7 @@ version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2b64e816d0d49769fbfaa1494eb77cc2a3ddc526ead05c7f922cb7d64106286f"
|
||||
dependencies = [
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.4.1",
|
||||
"libc",
|
||||
"vm-memory",
|
||||
"vmm-sys-util",
|
||||
@@ -913,9 +986,10 @@ dependencies = [
|
||||
"seccompiler",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_with",
|
||||
"serial_buffer",
|
||||
"thiserror",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vhost",
|
||||
"virtio-bindings",
|
||||
"virtio-queue",
|
||||
@@ -963,14 +1037,14 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "vm-fdt"
|
||||
version = "0.3.0"
|
||||
source = "git+https://github.com/rust-vmm/vm-fdt?branch=main#982fb8d9c8cd7f53520d7e304b39ff307fa3a641"
|
||||
version = "0.2.0"
|
||||
source = "git+https://github.com/rust-vmm/vm-fdt?branch=main#c5a99ab71b130435927d19b50c85fcd5ce904a8c"
|
||||
|
||||
[[package]]
|
||||
name = "vm-memory"
|
||||
version = "0.14.1"
|
||||
version = "0.14.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3c3aba5064cc5f6f7740cddc8dae34d2d9a311cac69b60d942af7f3ab8fc49f4"
|
||||
checksum = "74ffc42216c32c35f858fa4bfdcd9b61017dfd691e0240268fdc85dbf59e5459"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"libc",
|
||||
@@ -986,6 +1060,8 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vm-memory",
|
||||
]
|
||||
|
||||
@@ -1006,7 +1082,7 @@ dependencies = [
|
||||
"anyhow",
|
||||
"arc-swap",
|
||||
"arch",
|
||||
"bitflags 2.5.0",
|
||||
"bitflags 2.4.1",
|
||||
"block",
|
||||
"cfg-if",
|
||||
"clap",
|
||||
@@ -1023,7 +1099,6 @@ dependencies = [
|
||||
"once_cell",
|
||||
"option_parser",
|
||||
"pci",
|
||||
"rate_limiter",
|
||||
"seccompiler",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -1032,6 +1107,8 @@ dependencies = [
|
||||
"thiserror",
|
||||
"tracer",
|
||||
"uuid",
|
||||
"versionize",
|
||||
"versionize_derive",
|
||||
"vfio-ioctls",
|
||||
"vfio_user",
|
||||
"virtio-devices",
|
||||
@@ -1065,9 +1142,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.92"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4be2531df63900aeb2bca0daaaddec08491ee64ceecbee5076636a3b026795a8"
|
||||
checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
@@ -1075,24 +1152,24 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.92"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "614d787b966d3989fa7bb98a654e369c762374fd3213d212cfc0251257e747da"
|
||||
checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"log",
|
||||
"once_cell",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.47",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.92"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1f8823de937b71b9460c0c34e25f3da88250760bec0ebac694b49997550d726"
|
||||
checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2"
|
||||
dependencies = [
|
||||
"quote",
|
||||
"wasm-bindgen-macro-support",
|
||||
@@ -1100,22 +1177,22 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.92"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e94f17b526d0a461a191c78ea52bbce64071ed5c04c9ffe424dcb38f74171bb7"
|
||||
checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.47",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.92"
|
||||
version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "af190c94f2773fdb3729c55b007a722abb5384da03bc0986df4c289bf5567e96"
|
||||
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
@@ -1150,9 +1227,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.4"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7dd37b7e5ab9018759f893a1952c9420d060016fc19a472b4bb20d1bdd694d1b"
|
||||
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
@@ -1165,45 +1242,45 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.4"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcf46cf4c365c6f2d1cc93ce535f2c8b244591df96ceee75d8e83deb70a9cac9"
|
||||
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.4"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da9f259dd3bcf6990b55bffd094c4f7235817ba4ceebde8e6d11cd0c5633b675"
|
||||
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.5"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.5"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.5"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.5"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.5"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
||||
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04"
|
||||
|
||||
[[package]]
|
||||
name = "zerocopy"
|
||||
@@ -1223,5 +1300,5 @@ checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
"syn 2.0.47",
|
||||
]
|
||||
|
||||
@@ -14,8 +14,8 @@ igvm = []
|
||||
[dependencies]
|
||||
block = { path = "../block" }
|
||||
devices = { path = "../devices" }
|
||||
epoll = "4.3.3"
|
||||
libc = "0.2.153"
|
||||
epoll = "4.3.1"
|
||||
libc = "0.2.152"
|
||||
libfuzzer-sys = "0.4.7"
|
||||
linux-loader = { version = "0.11.0", features = ["elf", "bzimage", "pe"] }
|
||||
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" }
|
||||
@@ -23,10 +23,10 @@ net_util = { path = "../net_util" }
|
||||
once_cell = "1.19.0"
|
||||
seccompiler = "0.4.0"
|
||||
virtio-devices = { path = "../virtio-devices" }
|
||||
virtio-queue = "0.11.0"
|
||||
virtio-queue = "0.12.0"
|
||||
vmm = { path = "../vmm" }
|
||||
vmm-sys-util = "0.12.1"
|
||||
vm-memory = "0.14.1"
|
||||
vm-memory = "0.14.0"
|
||||
vm-migration = { path = "../vm-migration" }
|
||||
vm-device = { path = "../vm-device" }
|
||||
vm-virtio = { path = "../vm-virtio" }
|
||||
@@ -34,6 +34,10 @@ vm-virtio = { path = "../vm-virtio" }
|
||||
[dependencies.cloud-hypervisor]
|
||||
path = ".."
|
||||
|
||||
[patch.crates-io]
|
||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-live-upgrade-stable-37.x" }
|
||||
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch-0.1.6" }
|
||||
|
||||
# Prevent this from interfering with workspaces
|
||||
[workspace]
|
||||
members = ["."]
|
||||
|
||||
@@ -21,7 +21,6 @@ use virtio_devices::{Block, VirtioDevice, VirtioInterrupt, VirtioInterruptType};
|
||||
use virtio_queue::{Queue, QueueT};
|
||||
use vm_memory::{bitmap::AtomicBitmap, Bytes, GuestAddress, GuestMemoryAtomic};
|
||||
use vmm_sys_util::eventfd::{EventFd, EFD_NONBLOCK};
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
type GuestMemoryMmap = vm_memory::GuestMemoryMmap<AtomicBitmap>;
|
||||
|
||||
@@ -50,7 +49,6 @@ fuzz_target!(|bytes| {
|
||||
let shm = memfd_create(&ffi::CString::new("fuzz").unwrap(), 0).unwrap();
|
||||
let disk_file: File = unsafe { File::from_raw_fd(shm) };
|
||||
let qcow_disk = Box::new(RawFileDiskSync::new(disk_file)) as Box<dyn DiskFile>;
|
||||
let queue_affinity = BTreeMap::new();
|
||||
let mut block = Block::new(
|
||||
"tmp".to_owned(),
|
||||
qcow_disk,
|
||||
@@ -64,7 +62,6 @@ fuzz_target!(|bytes| {
|
||||
None,
|
||||
EventFd::new(EFD_NONBLOCK).unwrap(),
|
||||
None,
|
||||
queue_affinity,
|
||||
)
|
||||
.unwrap();
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
use devices::legacy::Cmos;
|
||||
use libc::EFD_NONBLOCK;
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::Arc;
|
||||
use vm_device::BusDevice;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
|
||||
@@ -7,18 +7,9 @@ use libfuzzer_sys::fuzz_target;
|
||||
use micro_http::Request;
|
||||
use once_cell::sync::Lazy;
|
||||
use std::os::unix::io::AsRawFd;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::mpsc::{channel, Receiver};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
use vm_migration::MigratableError;
|
||||
use vmm::api::{
|
||||
http::*, ApiRequest, RequestHandler, VmInfoResponse, VmReceiveMigrationData,
|
||||
VmSendMigrationData, VmmPingResponse,
|
||||
};
|
||||
use vmm::config::RestoreConfig;
|
||||
use vmm::vm::{Error as VmError, VmState};
|
||||
use vmm::vm_config::*;
|
||||
use vmm::api::{http::*, ApiRequest, ApiResponsePayload};
|
||||
use vmm::{EpollContext, EpollDispatch};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
@@ -78,208 +69,6 @@ fn generate_request(bytes: &[u8]) -> Option<Request> {
|
||||
Request::try_from(&request, None).ok()
|
||||
}
|
||||
|
||||
struct StubApiRequestHandler;
|
||||
|
||||
impl RequestHandler for StubApiRequestHandler {
|
||||
fn vm_create(&mut self, _: Arc<Mutex<VmConfig>>) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_boot(&mut self) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_pause(&mut self) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_resume(&mut self) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_snapshot(&mut self, _: &str) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_restore(&mut self, _: RestoreConfig) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(all(target_arch = "x86_64", feature = "guest_debug"))]
|
||||
fn vm_coredump(&mut self, _: &str) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_shutdown(&mut self) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_reboot(&mut self) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_info(&self) -> Result<VmInfoResponse, VmError> {
|
||||
Ok(VmInfoResponse {
|
||||
config: Arc::new(Mutex::new(VmConfig {
|
||||
cpus: CpusConfig {
|
||||
boot_vcpus: 1,
|
||||
max_vcpus: 1,
|
||||
topology: None,
|
||||
kvm_hyperv: false,
|
||||
max_phys_bits: 46,
|
||||
affinity: None,
|
||||
features: CpuFeatures::default(),
|
||||
},
|
||||
memory: MemoryConfig {
|
||||
size: 536_870_912,
|
||||
mergeable: false,
|
||||
hotplug_method: HotplugMethod::Acpi,
|
||||
hotplug_size: None,
|
||||
hotplugged_size: None,
|
||||
shared: false,
|
||||
hugepages: false,
|
||||
hugepage_size: None,
|
||||
prefault: false,
|
||||
zones: None,
|
||||
thp: true,
|
||||
},
|
||||
payload: Some(PayloadConfig {
|
||||
kernel: Some(PathBuf::from("/path/to/kernel")),
|
||||
firmware: None,
|
||||
cmdline: None,
|
||||
initramfs: None,
|
||||
#[cfg(feature = "igvm")]
|
||||
igvm: None,
|
||||
}),
|
||||
rate_limit_groups: None,
|
||||
disks: None,
|
||||
net: None,
|
||||
rng: RngConfig {
|
||||
src: PathBuf::from("/dev/urandom"),
|
||||
iommu: false,
|
||||
},
|
||||
balloon: None,
|
||||
fs: None,
|
||||
pmem: None,
|
||||
serial: ConsoleConfig {
|
||||
file: None,
|
||||
mode: ConsoleOutputMode::Null,
|
||||
iommu: false,
|
||||
socket: None,
|
||||
},
|
||||
console: ConsoleConfig {
|
||||
file: None,
|
||||
mode: ConsoleOutputMode::Tty,
|
||||
iommu: false,
|
||||
socket: None,
|
||||
},
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
debug_console: DebugConsoleConfig::default(),
|
||||
devices: None,
|
||||
user_devices: None,
|
||||
vdpa: None,
|
||||
vsock: None,
|
||||
pvpanic: false,
|
||||
iommu: false,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
sgx_epc: None,
|
||||
numa: None,
|
||||
watchdog: false,
|
||||
#[cfg(feature = "guest_debug")]
|
||||
gdb: false,
|
||||
pci_segments: None,
|
||||
platform: None,
|
||||
tpm: None,
|
||||
preserved_fds: None,
|
||||
})),
|
||||
state: VmState::Running,
|
||||
memory_actual_size: 0,
|
||||
device_tree: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn vmm_ping(&self) -> VmmPingResponse {
|
||||
VmmPingResponse {
|
||||
build_version: String::new(),
|
||||
version: String::new(),
|
||||
pid: 0,
|
||||
features: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn vm_delete(&mut self) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vmm_shutdown(&mut self) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_resize(&mut self, _: Option<u8>, _: Option<u64>, _: Option<u64>) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_resize_zone(&mut self, _: String, _: u64) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_add_device(&mut self, _: DeviceConfig) -> Result<Option<Vec<u8>>, VmError> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn vm_add_user_device(&mut self, _: UserDeviceConfig) -> Result<Option<Vec<u8>>, VmError> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn vm_remove_device(&mut self, _: String) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_add_disk(&mut self, _: DiskConfig) -> Result<Option<Vec<u8>>, VmError> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn vm_add_fs(&mut self, _: FsConfig) -> Result<Option<Vec<u8>>, VmError> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn vm_add_pmem(&mut self, _: PmemConfig) -> Result<Option<Vec<u8>>, VmError> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn vm_add_net(&mut self, _: NetConfig) -> Result<Option<Vec<u8>>, VmError> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn vm_add_vdpa(&mut self, _: VdpaConfig) -> Result<Option<Vec<u8>>, VmError> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn vm_add_vsock(&mut self, _: VsockConfig) -> Result<Option<Vec<u8>>, VmError> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn vm_counters(&mut self) -> Result<Option<Vec<u8>>, VmError> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn vm_power_button(&mut self) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_receive_migration(&mut self, _: VmReceiveMigrationData) -> Result<(), MigratableError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_send_migration(&mut self, _: VmSendMigrationData) -> Result<(), MigratableError> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn vm_nmi(&mut self) -> Result<(), VmError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn http_receiver_stub(exit_evt: EventFd, api_evt: EventFd, api_receiver: Receiver<ApiRequest>) {
|
||||
let mut epoll = EpollContext::new().unwrap();
|
||||
epoll.add_event(&exit_evt, EpollDispatch::Exit).unwrap();
|
||||
@@ -309,7 +98,89 @@ fn http_receiver_stub(exit_evt: EventFd, api_evt: EventFd, api_receiver: Receive
|
||||
EpollDispatch::Api => {
|
||||
for _ in 0..api_evt.read().unwrap() {
|
||||
let api_request = api_receiver.recv().unwrap();
|
||||
api_request(&mut StubApiRequestHandler).unwrap();
|
||||
match api_request {
|
||||
ApiRequest::VmCreate(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmDelete(sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmBoot(sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmShutdown(sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmReboot(sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmInfo(sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmmPing(sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmPause(sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmResume(sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmSnapshot(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmRestore(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmmShutdown(sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmResize(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmResizeZone(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmAddDevice(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmAddUserDevice(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmRemoveDevice(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmAddDisk(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmAddFs(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmAddPmem(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmAddNet(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmAddVdpa(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmAddVsock(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmCounters(sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmReceiveMigration(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmSendMigration(_, sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
ApiRequest::VmPowerButton(sender) => {
|
||||
sender.send(Ok(ApiResponsePayload::Empty)).unwrap();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
#![no_main]
|
||||
use libfuzzer_sys::fuzz_target;
|
||||
|
||||
@@ -12,28 +12,28 @@ sev_snp = ["igvm_parser", "igvm_defs"]
|
||||
tdx = []
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.81"
|
||||
byteorder = "1.5.0"
|
||||
anyhow = "1.0.75"
|
||||
byteorder = "1.4.3"
|
||||
igvm_defs = { git = "https://github.com/microsoft/igvm", branch = "main", package = "igvm_defs", optional = true }
|
||||
igvm_parser = { git = "https://github.com/microsoft/igvm", branch = "main", package = "igvm", optional = true }
|
||||
libc = "0.2.153"
|
||||
log = "0.4.21"
|
||||
kvm-bindings = { version = "0.8.1", optional = true, features = ["serde"] }
|
||||
kvm-ioctls = { version = "0.17.0", optional = true }
|
||||
libc = "0.2.147"
|
||||
log = "0.4.20"
|
||||
kvm-ioctls = { version = "0.16.0", optional = true }
|
||||
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-live-upgrade-stable-37.x", features = ["with-serde", "fam-wrappers"], optional = true }
|
||||
mshv-bindings = { git = "https://github.com/rust-vmm/mshv", branch = "main", features = ["with-serde", "fam-wrappers"], optional = true }
|
||||
mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", branch = "main", optional = true}
|
||||
serde = { version = "1.0.197", features = ["rc", "derive"] }
|
||||
serde_with = { version = "3.7.0", default-features = false, features = ["macros"] }
|
||||
serde = { version = "1.0.168", features = ["rc", "derive"] }
|
||||
serde_with = { version = "3.4.0", default-features = false, features = ["macros"] }
|
||||
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
|
||||
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic"] }
|
||||
vm-memory = { version = "0.14.0", features = ["backend-mmap", "backend-atomic"] }
|
||||
vmm-sys-util = { version = "0.12.1", features = ["with-serde"] }
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.52"
|
||||
|
||||
[target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86]
|
||||
optional = true
|
||||
version = "1.21.0"
|
||||
version = "1.20.0"
|
||||
default-features = false
|
||||
features = ["std", "decoder", "op_code_info", "instr_info", "fast_fmt"]
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "0.11.3"
|
||||
env_logger = "0.10.0"
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// Copyright 2022 Arm Limited (or its affiliates). All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{CpuState, GicState, HypervisorDeviceError, HypervisorVmError};
|
||||
use std::any::Any;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
// Copyright 2022 Arm Limited (or its affiliates). All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
pub mod gic;
|
||||
|
||||
@@ -10,8 +10,10 @@
|
||||
// CMP-Compare Two Operands
|
||||
//
|
||||
|
||||
use crate::arch::emulator::{EmulationError, PlatformEmulator};
|
||||
use crate::arch::x86::emulator::instructions::*;
|
||||
use crate::arch::x86::regs::*;
|
||||
use crate::arch::x86::Exception;
|
||||
|
||||
// CMP affects OF, SF, ZF, AF, PF and CF
|
||||
const FLAGS_MASK: u64 = CF | PF | AF | ZF | SF | OF;
|
||||
@@ -209,6 +211,8 @@ impl<T: CpuStateManager> InstructionHandler<T> for Cmp_rm64_imm8 {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#![allow(unused_mut)]
|
||||
|
||||
use super::*;
|
||||
use crate::arch::x86::emulator::mock_vmm::*;
|
||||
|
||||
|
||||
@@ -12,7 +12,9 @@
|
||||
// Copies the second operand (source operand) to the first operand (destination operand).
|
||||
//
|
||||
|
||||
use crate::arch::emulator::{EmulationError, PlatformEmulator};
|
||||
use crate::arch::x86::emulator::instructions::*;
|
||||
use crate::arch::x86::Exception;
|
||||
|
||||
macro_rules! mov_rm_r {
|
||||
($bound:ty) => {
|
||||
@@ -269,6 +271,7 @@ impl<T: CpuStateManager> InstructionHandler<T> for Mov_RAX_moffs64 {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#![allow(unused_mut)]
|
||||
use super::*;
|
||||
use crate::arch::x86::emulator::mock_vmm::*;
|
||||
|
||||
|
||||
@@ -10,8 +10,10 @@
|
||||
// MOVS - Move Data from String to String
|
||||
//
|
||||
|
||||
use crate::arch::emulator::{EmulationError, PlatformEmulator};
|
||||
use crate::arch::x86::emulator::instructions::*;
|
||||
use crate::arch::x86::regs::DF;
|
||||
use crate::arch::x86::Exception;
|
||||
|
||||
macro_rules! movs {
|
||||
($bound:ty) => {
|
||||
@@ -100,6 +102,7 @@ impl<T: CpuStateManager> InstructionHandler<T> for Movsb_m8_m8 {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#![allow(unused_mut)]
|
||||
use super::*;
|
||||
use crate::arch::x86::emulator::mock_vmm::*;
|
||||
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
// OR - Logical inclusive OR
|
||||
//
|
||||
|
||||
use crate::arch::emulator::{EmulationError, PlatformEmulator};
|
||||
use crate::arch::x86::emulator::instructions::*;
|
||||
use crate::arch::x86::Exception;
|
||||
|
||||
macro_rules! or_rm_r {
|
||||
($bound:ty) => {
|
||||
@@ -50,6 +52,7 @@ impl<T: CpuStateManager> InstructionHandler<T> for Or_rm8_r8 {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#![allow(unused_mut)]
|
||||
use super::*;
|
||||
|
||||
use crate::arch::x86::emulator::mock_vmm::*;
|
||||
|
||||
@@ -648,9 +648,13 @@ impl<'a, T: CpuStateManager> Emulator<'a, T> {
|
||||
|
||||
#[cfg(test)]
|
||||
mod mock_vmm {
|
||||
#![allow(unused_mut)]
|
||||
|
||||
use super::*;
|
||||
use crate::arch::x86::emulator::EmulatorCpuState as CpuState;
|
||||
use crate::arch::emulator::{EmulationError, PlatformEmulator};
|
||||
use crate::arch::x86::emulator::{Emulator, EmulatorCpuState as CpuState};
|
||||
use crate::arch::x86::gdt::{gdt_entry, segment_from_gdt};
|
||||
use crate::arch::x86::Exception;
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
@@ -768,6 +772,7 @@ mod mock_vmm {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
#![allow(unused_mut)]
|
||||
use super::*;
|
||||
use crate::arch::x86::emulator::mock_vmm::*;
|
||||
|
||||
|
||||
@@ -312,10 +312,10 @@ pub struct MsrEntry {
|
||||
pub data: u64,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[serde_with::serde_as]
|
||||
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct XsaveState {
|
||||
#[serde_as(as = "[_; 1024usize]")]
|
||||
pub region: [u32; 1024usize],
|
||||
}
|
||||
|
||||
@@ -325,3 +325,26 @@ impl Default for XsaveState {
|
||||
unsafe { ::std::mem::zeroed() }
|
||||
}
|
||||
}
|
||||
|
||||
impl<'de> serde::Deserialize<'de> for XsaveState {
|
||||
fn deserialize<D>(deserializer: D) -> std::result::Result<Self, D::Error>
|
||||
where
|
||||
D: serde::Deserializer<'de>,
|
||||
{
|
||||
let region: Vec<u32> = Vec::deserialize(deserializer)?;
|
||||
let mut val: XsaveState = XsaveState::default();
|
||||
// This panics if the source and destination have different lengths.
|
||||
val.region.copy_from_slice(®ion[..]);
|
||||
Ok(val)
|
||||
}
|
||||
}
|
||||
|
||||
impl serde::Serialize for XsaveState {
|
||||
fn serialize<S>(&self, serializer: S) -> std::result::Result<S::Ok, S::Error>
|
||||
where
|
||||
S: serde::Serializer,
|
||||
{
|
||||
let region = &self.region[..];
|
||||
region.serialize(serializer)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// Copyright 2017 The Chromium OS Authors. All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
|
||||
|
||||
@@ -107,28 +107,14 @@ pub enum HypervisorCpuError {
|
||||
///
|
||||
/// Setting Saved Processor Extended States error
|
||||
///
|
||||
#[cfg(feature = "kvm")]
|
||||
#[error("Failed to set Saved Processor Extended States: {0}")]
|
||||
SetXsaveState(#[source] anyhow::Error),
|
||||
///
|
||||
/// Getting Saved Processor Extended States error
|
||||
///
|
||||
#[cfg(feature = "kvm")]
|
||||
#[error("Failed to get Saved Processor Extended States: {0}")]
|
||||
GetXsaveState(#[source] anyhow::Error),
|
||||
///
|
||||
/// Getting the VP state components error
|
||||
///
|
||||
#[cfg(feature = "mshv")]
|
||||
#[error("Failed to get VP State Components: {0}")]
|
||||
GetAllVpStateComponents(#[source] anyhow::Error),
|
||||
///
|
||||
/// Setting the VP state components error
|
||||
///
|
||||
#[cfg(feature = "mshv")]
|
||||
#[error("Failed to set VP State Components: {0}")]
|
||||
SetAllVpStateComponents(#[source] anyhow::Error),
|
||||
///
|
||||
/// Setting Extended Control Registers error
|
||||
///
|
||||
#[error("Failed to set Extended Control Registers: {0}")]
|
||||
@@ -286,23 +272,18 @@ pub enum HypervisorCpuError {
|
||||
///
|
||||
#[error("Failed to get CPUID entries: {0}")]
|
||||
GetCpuidVales(#[source] anyhow::Error),
|
||||
///
|
||||
/// Setting SEV control register error
|
||||
///
|
||||
#[cfg(feature = "sev_snp")]
|
||||
#[error("Failed to set sev control register: {0}")]
|
||||
SetSevControlRegister(#[source] anyhow::Error),
|
||||
|
||||
/// Error injecting NMI
|
||||
///
|
||||
#[error("Failed to inject NMI")]
|
||||
Nmi(#[source] anyhow::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum VmExit {
|
||||
pub enum VmExit<'a> {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
IoOut(u16 /* port */, &'a [u8] /* data */),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
IoIn(u16 /* port */, &'a mut [u8] /* data */),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
IoapicEoi(u8 /* vector */),
|
||||
MmioRead(u64 /* address */, &'a mut [u8]),
|
||||
MmioWrite(u64 /* address */, &'a [u8]),
|
||||
Ignore,
|
||||
Reset,
|
||||
Shutdown,
|
||||
@@ -514,14 +495,4 @@ pub trait Vcpu: Send + Sync {
|
||||
) -> Result<[u32; 4]> {
|
||||
unimplemented!()
|
||||
}
|
||||
#[cfg(feature = "mshv")]
|
||||
fn set_sev_control_register(&self, _reg: u64) -> Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
/// Trigger NMI interrupt
|
||||
///
|
||||
fn nmi(&self) -> Result<()>;
|
||||
}
|
||||
|
||||
@@ -21,6 +21,8 @@ use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
///
|
||||
///
|
||||
pub enum HypervisorError {
|
||||
///
|
||||
/// Hypervisor availability check error
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
// Copyright 2022 Arm Limited (or its affiliates). All rights reserved.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
mod dist_regs;
|
||||
mod icc_regs;
|
||||
@@ -8,7 +6,7 @@ mod redist_regs;
|
||||
|
||||
use crate::arch::aarch64::gic::{Error, Result, Vgic, VgicConfig};
|
||||
use crate::device::HypervisorDeviceError;
|
||||
use crate::kvm::KvmVm;
|
||||
use crate::kvm::{kvm_bindings, KvmVm};
|
||||
use crate::{CpuState, Vm};
|
||||
use dist_regs::{get_dist_regs, read_ctlr, set_dist_regs, write_ctlr};
|
||||
use icc_regs::{get_icc_regs, set_icc_regs};
|
||||
@@ -16,6 +14,7 @@ use kvm_ioctls::DeviceFd;
|
||||
use redist_regs::{construct_gicr_typers, get_redist_regs, set_redist_regs};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::any::Any;
|
||||
use std::convert::TryInto;
|
||||
|
||||
const GITS_CTLR: u32 = 0x0000;
|
||||
const GITS_IIDR: u32 = 0x0004;
|
||||
|
||||
@@ -27,6 +27,8 @@ use crate::{arm64_core_reg_id, offset_of};
|
||||
use kvm_ioctls::{NoDatamatch, VcpuFd, VmFd};
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use std::convert::TryInto;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::fs::File;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
@@ -36,6 +38,7 @@ use std::os::unix::io::RawFd;
|
||||
use std::result;
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
use std::sync::Mutex;
|
||||
use std::sync::{Arc, RwLock};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
@@ -102,15 +105,6 @@ pub use {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
const KVM_CAP_SGX_ATTRIBUTE: u32 = 196;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use vmm_sys_util::ioctl_io_nr;
|
||||
|
||||
#[cfg(all(not(feature = "tdx"), target_arch = "x86_64"))]
|
||||
use vmm_sys_util::ioctl_ioc_nr;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
ioctl_io_nr!(KVM_NMI, kvm_bindings::KVMIO, 0x9a);
|
||||
|
||||
#[cfg(feature = "tdx")]
|
||||
const KVM_EXIT_TDX: u32 = 50;
|
||||
#[cfg(feature = "tdx")]
|
||||
@@ -321,7 +315,7 @@ impl From<CpuState> for VcpuKvmState {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
impl From<kvm_clock_data> for ClockData {
|
||||
fn from(d: kvm_clock_data) -> Self {
|
||||
ClockData::Kvm(d)
|
||||
ClockData::Kvm(d.into())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,7 +323,7 @@ impl From<kvm_clock_data> for ClockData {
|
||||
impl From<ClockData> for kvm_clock_data {
|
||||
fn from(ms: ClockData) -> Self {
|
||||
match ms {
|
||||
ClockData::Kvm(s) => s,
|
||||
ClockData::Kvm(s) => s.into(),
|
||||
/* Needed in case other hypervisors are enabled */
|
||||
#[allow(unreachable_patterns)]
|
||||
_ => panic!("CpuState is not valid"),
|
||||
@@ -454,12 +448,12 @@ impl vm::Vm for KvmVm {
|
||||
id: u8,
|
||||
vm_ops: Option<Arc<dyn VmOps>>,
|
||||
) -> vm::Result<Arc<dyn cpu::Vcpu>> {
|
||||
let fd = self
|
||||
let vc = self
|
||||
.fd
|
||||
.create_vcpu(id as u64)
|
||||
.map_err(|e| vm::HypervisorVmError::CreateVcpu(e.into()))?;
|
||||
let vcpu = KvmVcpu {
|
||||
fd: Arc::new(Mutex::new(fd)),
|
||||
fd: vc,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
msrs: self.msrs.clone(),
|
||||
vm_ops,
|
||||
@@ -1169,7 +1163,7 @@ impl hypervisor::Hypervisor for KvmHypervisor {
|
||||
|
||||
/// Vcpu struct for KVM
|
||||
pub struct KvmVcpu {
|
||||
fd: Arc<Mutex<VcpuFd>>,
|
||||
fd: VcpuFd,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
msrs: Vec<MsrEntry>,
|
||||
vm_ops: Option<Arc<dyn vm::VmOps>>,
|
||||
@@ -1197,8 +1191,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
fn get_regs(&self) -> cpu::Result<StandardRegisters> {
|
||||
Ok(self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_regs()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetStandardRegs(e.into()))?
|
||||
.into())
|
||||
@@ -1220,8 +1212,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
for i in 0..31 {
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.regs.regs[i] = u64::from_le_bytes(bytes);
|
||||
@@ -1233,8 +1223,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
let off = offset_of!(user_pt_regs, sp);
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.regs.sp = u64::from_le_bytes(bytes);
|
||||
@@ -1243,8 +1231,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
let off = offset_of!(user_pt_regs, pc);
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.regs.pc = u64::from_le_bytes(bytes);
|
||||
@@ -1253,8 +1239,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
let off = offset_of!(user_pt_regs, pstate);
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.regs.pstate = u64::from_le_bytes(bytes);
|
||||
@@ -1263,8 +1247,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
let off = offset_of!(kvm_regs, sp_el1);
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.sp_el1 = u64::from_le_bytes(bytes);
|
||||
@@ -1274,8 +1256,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
let off = offset_of!(kvm_regs, elr_el1);
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.elr_el1 = u64::from_le_bytes(bytes);
|
||||
@@ -1285,8 +1265,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
for i in 0..KVM_NR_SPSR as usize {
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.spsr[i] = u64::from_le_bytes(bytes);
|
||||
@@ -1299,8 +1277,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
for i in 0..32 {
|
||||
let mut bytes = [0_u8; 16];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U128, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.fp_regs.vregs[i] = u128::from_le_bytes(bytes);
|
||||
@@ -1311,8 +1287,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpsr);
|
||||
let mut bytes = [0_u8; 4];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.fp_regs.fpsr = u32::from_le_bytes(bytes);
|
||||
@@ -1321,8 +1295,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpcr);
|
||||
let mut bytes = [0_u8; 4];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off), &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
|
||||
state.fp_regs.fpcr = u32::from_le_bytes(bytes);
|
||||
@@ -1336,8 +1308,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
fn set_regs(&self, regs: &StandardRegisters) -> cpu::Result<()> {
|
||||
let regs = (*regs).into();
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_regs(®s)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetStandardRegs(e.into()))
|
||||
}
|
||||
@@ -1354,8 +1324,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
let mut off = offset_of!(user_pt_regs, regs);
|
||||
for i in 0..31 {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
|
||||
&state.regs.regs[i].to_le_bytes(),
|
||||
@@ -1366,8 +1334,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
|
||||
let off = offset_of!(user_pt_regs, sp);
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
|
||||
&state.regs.sp.to_le_bytes(),
|
||||
@@ -1376,8 +1342,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
|
||||
let off = offset_of!(user_pt_regs, pc);
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
|
||||
&state.regs.pc.to_le_bytes(),
|
||||
@@ -1386,8 +1350,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
|
||||
let off = offset_of!(user_pt_regs, pstate);
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
|
||||
&state.regs.pstate.to_le_bytes(),
|
||||
@@ -1396,8 +1358,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
|
||||
let off = offset_of!(kvm_regs, sp_el1);
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
|
||||
&state.sp_el1.to_le_bytes(),
|
||||
@@ -1406,8 +1366,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
|
||||
let off = offset_of!(kvm_regs, elr_el1);
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
|
||||
&state.elr_el1.to_le_bytes(),
|
||||
@@ -1417,8 +1375,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
let mut off = offset_of!(kvm_regs, spsr);
|
||||
for i in 0..KVM_NR_SPSR as usize {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
|
||||
&state.spsr[i].to_le_bytes(),
|
||||
@@ -1430,8 +1386,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
let mut off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, vregs);
|
||||
for i in 0..32 {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U128, off),
|
||||
&state.fp_regs.vregs[i].to_le_bytes(),
|
||||
@@ -1442,8 +1396,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
|
||||
let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpsr);
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U32, off),
|
||||
&state.fp_regs.fpsr.to_le_bytes(),
|
||||
@@ -1452,8 +1404,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
|
||||
let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpcr);
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U32, off),
|
||||
&state.fp_regs.fpcr.to_le_bytes(),
|
||||
@@ -1469,8 +1419,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
fn get_sregs(&self) -> cpu::Result<SpecialRegisters> {
|
||||
Ok(self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_sregs()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetSpecialRegs(e.into()))?
|
||||
.into())
|
||||
@@ -1483,8 +1431,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
fn set_sregs(&self, sregs: &SpecialRegisters) -> cpu::Result<()> {
|
||||
let sregs = (*sregs).into();
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_sregs(&sregs)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetSpecialRegs(e.into()))
|
||||
}
|
||||
@@ -1496,8 +1442,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
fn get_fpu(&self) -> cpu::Result<FpuState> {
|
||||
Ok(self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_fpu()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetFloatingPointRegs(e.into()))?
|
||||
.into())
|
||||
@@ -1510,8 +1454,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
fn set_fpu(&self, fpu: &FpuState) -> cpu::Result<()> {
|
||||
let fpu: kvm_bindings::kvm_fpu = (*fpu).clone().into();
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_fpu(&fpu)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetFloatingPointRegs(e.into()))
|
||||
}
|
||||
@@ -1527,8 +1469,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
.map_err(|_| cpu::HypervisorCpuError::SetCpuid(anyhow!("failed to create CpuId")))?;
|
||||
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_cpuid2(&kvm_cpuid)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetCpuid(e.into()))
|
||||
}
|
||||
@@ -1547,8 +1487,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
..Default::default()
|
||||
};
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.enable_cap(&cap)
|
||||
.map_err(|e| cpu::HypervisorCpuError::EnableHyperVSyncIc(e.into()))
|
||||
}
|
||||
@@ -1560,8 +1498,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
fn get_cpuid2(&self, num_entries: usize) -> cpu::Result<Vec<CpuIdEntry>> {
|
||||
let kvm_cpuid = self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_cpuid2(num_entries)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetCpuid(e.into()))?;
|
||||
|
||||
@@ -1577,8 +1513,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
fn get_lapic(&self) -> cpu::Result<LapicState> {
|
||||
Ok(self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_lapic()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetlapicState(e.into()))?
|
||||
.into())
|
||||
@@ -1591,8 +1525,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
fn set_lapic(&self, klapic: &LapicState) -> cpu::Result<()> {
|
||||
let klapic: kvm_bindings::kvm_lapic_state = (*klapic).clone().into();
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_lapic(&klapic)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetLapicState(e.into()))
|
||||
}
|
||||
@@ -1606,8 +1538,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
let mut kvm_msrs = MsrEntries::from_entries(&kvm_msrs).unwrap();
|
||||
let succ = self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_msrs(&mut kvm_msrs)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetMsrEntries(e.into()))?;
|
||||
|
||||
@@ -1630,8 +1560,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
let kvm_msrs: Vec<kvm_msr_entry> = msrs.iter().map(|e| (*e).into()).collect();
|
||||
let kvm_msrs = MsrEntries::from_entries(&kvm_msrs).unwrap();
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_msrs(&kvm_msrs)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetMsrEntries(e.into()))
|
||||
}
|
||||
@@ -1642,8 +1570,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
fn get_mp_state(&self) -> cpu::Result<MpState> {
|
||||
Ok(self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_mp_state()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetMpState(e.into()))?
|
||||
.into())
|
||||
@@ -1654,8 +1580,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
///
|
||||
fn set_mp_state(&self, mp_state: MpState) -> cpu::Result<()> {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_mp_state(mp_state.into())
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetMpState(e.into()))
|
||||
}
|
||||
@@ -1667,8 +1591,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
fn translate_gva(&self, gva: u64, _flags: u64) -> cpu::Result<(u64, u32)> {
|
||||
let tr = self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.translate_gva(gva)
|
||||
.map_err(|e| cpu::HypervisorCpuError::TranslateVirtualAddress(e.into()))?;
|
||||
// tr.valid is set if the GVA is mapped to valid GPA.
|
||||
@@ -1685,7 +1607,7 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
/// Triggers the running of the current virtual CPU returning an exit reason.
|
||||
///
|
||||
fn run(&self) -> std::result::Result<cpu::VmExit, cpu::HypervisorCpuError> {
|
||||
match self.fd.lock().unwrap().run() {
|
||||
match self.fd.run() {
|
||||
Ok(run) => match run {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
VcpuExit::IoIn(addr, data) => {
|
||||
@@ -1696,7 +1618,7 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||
}
|
||||
|
||||
Ok(cpu::VmExit::Ignore)
|
||||
Ok(cpu::VmExit::IoIn(addr, data))
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
VcpuExit::IoOut(addr, data) => {
|
||||
@@ -1707,7 +1629,7 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||
}
|
||||
|
||||
Ok(cpu::VmExit::Ignore)
|
||||
Ok(cpu::VmExit::IoOut(addr, data))
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
VcpuExit::IoapicEoi(vector) => Ok(cpu::VmExit::IoapicEoi(vector)),
|
||||
@@ -1740,7 +1662,7 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||
}
|
||||
|
||||
Ok(cpu::VmExit::Ignore)
|
||||
Ok(cpu::VmExit::MmioRead(addr, data))
|
||||
}
|
||||
VcpuExit::MmioWrite(addr, data) => {
|
||||
if let Some(vm_ops) = &self.vm_ops {
|
||||
@@ -1750,7 +1672,7 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()));
|
||||
}
|
||||
|
||||
Ok(cpu::VmExit::Ignore)
|
||||
Ok(cpu::VmExit::MmioWrite(addr, data))
|
||||
}
|
||||
VcpuExit::Hyperv => Ok(cpu::VmExit::Hyperv),
|
||||
#[cfg(feature = "tdx")]
|
||||
@@ -1779,7 +1701,7 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
/// potential soft lockups when being resumed.
|
||||
///
|
||||
fn notify_guest_clock_paused(&self) -> cpu::Result<()> {
|
||||
if let Err(e) = self.fd.lock().unwrap().kvmclock_ctrl() {
|
||||
if let Err(e) = self.fd.kvmclock_ctrl() {
|
||||
// Linux kernel returns -EINVAL if the PV clock isn't yet initialised
|
||||
// which could be because we're still in firmware or the guest doesn't
|
||||
// use KVM clock.
|
||||
@@ -1841,8 +1763,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
}
|
||||
}
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_guest_debug(&dbg)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetDebugRegs(e.into()))
|
||||
}
|
||||
@@ -1850,8 +1770,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn vcpu_init(&self, kvi: &VcpuInit) -> cpu::Result<()> {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.vcpu_init(kvi)
|
||||
.map_err(|e| cpu::HypervisorCpuError::VcpuInit(e.into()))
|
||||
}
|
||||
@@ -1863,8 +1781,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn get_reg_list(&self, reg_list: &mut RegList) -> cpu::Result<()> {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_reg_list(reg_list)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))
|
||||
}
|
||||
@@ -1897,8 +1813,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
| KVM_REG_ARM64_SYSREG_OP2_MASK)) as u64);
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(id, &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))?;
|
||||
Ok(u64::from_le_bytes(bytes))
|
||||
@@ -1926,8 +1840,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
// Get the register index of the PSTATE (Processor State) register.
|
||||
let pstate = offset_of!(user_pt_regs, pstate) + kreg_off;
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, pstate),
|
||||
&PSTATE_FAULT_BITS_64.to_le_bytes(),
|
||||
@@ -1939,8 +1851,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
// Setting the PC (Processor Counter) to the current program address (kernel address).
|
||||
let pc = offset_of!(user_pt_regs, pc) + kreg_off;
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, pc),
|
||||
&boot_ip.to_le_bytes(),
|
||||
@@ -1953,8 +1863,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
// We are choosing to place it the end of DRAM. See `get_fdt_addr`.
|
||||
let regs0 = offset_of!(user_pt_regs, regs) + kreg_off;
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(
|
||||
arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0),
|
||||
&fdt_start.to_le_bytes(),
|
||||
@@ -2069,7 +1977,7 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
msr_entries
|
||||
};
|
||||
|
||||
let vcpu_events = self.get_vcpu_events()?;
|
||||
let vcpu_events = self.get_vcpu_events()?.into();
|
||||
let tsc_khz = self.tsc_khz()?;
|
||||
|
||||
Ok(VcpuKvmState {
|
||||
@@ -2106,8 +2014,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
let mut sys_regs: Vec<Register> = Vec::new();
|
||||
let mut reg_list = RegList::new(500).unwrap();
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_reg_list(&mut reg_list)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))?;
|
||||
|
||||
@@ -2126,8 +2032,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
for index in indices.iter() {
|
||||
let mut bytes = [0_u8; 8];
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_one_reg(*index, &mut bytes)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))?;
|
||||
sys_regs.push(kvm_bindings::kvm_one_reg {
|
||||
@@ -2226,7 +2130,7 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
}
|
||||
}
|
||||
|
||||
self.set_vcpu_events(&state.vcpu_events)?;
|
||||
self.set_vcpu_events(&state.vcpu_events.into())?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
@@ -2242,8 +2146,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
// Set system registers
|
||||
for reg in &state.sys_regs {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_one_reg(reg.id, ®.addr.to_le_bytes())
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetSysRegister(e.into()))?;
|
||||
}
|
||||
@@ -2258,20 +2160,15 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
///
|
||||
#[cfg(feature = "tdx")]
|
||||
fn tdx_init(&self, hob_address: u64) -> cpu::Result<()> {
|
||||
tdx_command(
|
||||
&self.fd.lock().unwrap().as_raw_fd(),
|
||||
TdxCommand::InitVcpu,
|
||||
0,
|
||||
hob_address,
|
||||
)
|
||||
.map_err(cpu::HypervisorCpuError::InitializeTdx)
|
||||
tdx_command(&self.fd.as_raw_fd(), TdxCommand::InitVcpu, 0, hob_address)
|
||||
.map_err(cpu::HypervisorCpuError::InitializeTdx)
|
||||
}
|
||||
|
||||
///
|
||||
/// Set the "immediate_exit" state
|
||||
///
|
||||
fn set_immediate_exit(&self, exit: bool) {
|
||||
self.fd.lock().unwrap().set_kvm_immediate_exit(exit.into());
|
||||
self.fd.set_kvm_immediate_exit(exit.into());
|
||||
}
|
||||
|
||||
///
|
||||
@@ -2279,8 +2176,7 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
///
|
||||
#[cfg(feature = "tdx")]
|
||||
fn get_tdx_exit_details(&mut self) -> cpu::Result<TdxExitDetails> {
|
||||
let mut fd = self.fd.as_ref().lock().unwrap();
|
||||
let kvm_run = fd.get_kvm_run();
|
||||
let kvm_run = self.fd.get_kvm_run();
|
||||
// SAFETY: accessing a union field in a valid structure
|
||||
let tdx_vmcall = unsafe {
|
||||
&mut (*((&mut kvm_run.__bindgen_anon_1) as *mut kvm_run__bindgen_ty_1
|
||||
@@ -2309,8 +2205,7 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
///
|
||||
#[cfg(feature = "tdx")]
|
||||
fn set_tdx_status(&mut self, status: TdxExitStatus) {
|
||||
let mut fd = self.fd.as_ref().lock().unwrap();
|
||||
let kvm_run = fd.get_kvm_run();
|
||||
let kvm_run = self.fd.get_kvm_run();
|
||||
// SAFETY: accessing a union field in a valid structure
|
||||
let tdx_vmcall = unsafe {
|
||||
&mut (*((&mut kvm_run.__bindgen_anon_1) as *mut kvm_run__bindgen_ty_1
|
||||
@@ -2359,7 +2254,7 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
addr: 0x0,
|
||||
flags: 0,
|
||||
};
|
||||
self.fd.lock().unwrap().has_device_attr(&cpu_attr).is_ok()
|
||||
self.fd.has_device_attr(&cpu_attr).is_ok()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
@@ -2377,13 +2272,9 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
flags: 0,
|
||||
};
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_device_attr(&cpu_attr_irq)
|
||||
.map_err(|_| cpu::HypervisorCpuError::InitializePmu)?;
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_device_attr(&cpu_attr)
|
||||
.map_err(|_| cpu::HypervisorCpuError::InitializePmu)
|
||||
}
|
||||
@@ -2393,7 +2284,7 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
/// Get the frequency of the TSC if available
|
||||
///
|
||||
fn tsc_khz(&self) -> cpu::Result<Option<u32>> {
|
||||
match self.fd.lock().unwrap().get_tsc_khz() {
|
||||
match self.fd.get_tsc_khz() {
|
||||
Err(e) => {
|
||||
if e.errno() == libc::EIO {
|
||||
Ok(None)
|
||||
@@ -2410,7 +2301,7 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
/// Set the frequency of the TSC if available
|
||||
///
|
||||
fn set_tsc_khz(&self, freq: u32) -> cpu::Result<()> {
|
||||
match self.fd.lock().unwrap().set_tsc_khz(freq) {
|
||||
match self.fd.set_tsc_khz(freq) {
|
||||
Err(e) => {
|
||||
if e.errno() == libc::EIO {
|
||||
Ok(())
|
||||
@@ -2421,23 +2312,6 @@ impl cpu::Vcpu for KvmVcpu {
|
||||
Ok(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
/// Trigger NMI interrupt
|
||||
///
|
||||
fn nmi(&self) -> cpu::Result<()> {
|
||||
match self.fd.lock().unwrap().nmi() {
|
||||
Err(e) => {
|
||||
if e.errno() == libc::EIO {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(cpu::HypervisorCpuError::Nmi(e.into()))
|
||||
}
|
||||
}
|
||||
Ok(_) => Ok(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl KvmVcpu {
|
||||
@@ -2448,8 +2322,6 @@ impl KvmVcpu {
|
||||
fn get_xsave(&self) -> cpu::Result<XsaveState> {
|
||||
Ok(self
|
||||
.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_xsave()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetXsaveState(e.into()))?
|
||||
.into())
|
||||
@@ -2462,8 +2334,6 @@ impl KvmVcpu {
|
||||
fn set_xsave(&self, xsave: &XsaveState) -> cpu::Result<()> {
|
||||
let xsave: kvm_bindings::kvm_xsave = (*xsave).clone().into();
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_xsave(&xsave)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetXsaveState(e.into()))
|
||||
}
|
||||
@@ -2474,8 +2344,6 @@ impl KvmVcpu {
|
||||
///
|
||||
fn get_xcrs(&self) -> cpu::Result<ExtendedControlRegisters> {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_xcrs()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetXcsr(e.into()))
|
||||
}
|
||||
@@ -2486,8 +2354,6 @@ impl KvmVcpu {
|
||||
///
|
||||
fn set_xcrs(&self, xcrs: &ExtendedControlRegisters) -> cpu::Result<()> {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_xcrs(xcrs)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetXcsr(e.into()))
|
||||
}
|
||||
@@ -2499,8 +2365,6 @@ impl KvmVcpu {
|
||||
///
|
||||
fn get_vcpu_events(&self) -> cpu::Result<VcpuEvents> {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_vcpu_events()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetVcpuEvents(e.into()))
|
||||
}
|
||||
@@ -2512,8 +2376,6 @@ impl KvmVcpu {
|
||||
///
|
||||
fn set_vcpu_events(&self, events: &VcpuEvents) -> cpu::Result<()> {
|
||||
self.fd
|
||||
.lock()
|
||||
.unwrap()
|
||||
.set_vcpu_events(events)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetVcpuEvents(e.into()))
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ pub use {
|
||||
kvm_bindings::kvm_cpuid_entry2, kvm_bindings::kvm_dtable, kvm_bindings::kvm_fpu,
|
||||
kvm_bindings::kvm_lapic_state, kvm_bindings::kvm_mp_state as MpState,
|
||||
kvm_bindings::kvm_msr_entry, kvm_bindings::kvm_regs, kvm_bindings::kvm_segment,
|
||||
kvm_bindings::kvm_sregs, kvm_bindings::kvm_vcpu_events as VcpuEvents,
|
||||
kvm_bindings::kvm_sregs, kvm_bindings::kvm_vcpu_events_old as VcpuEvents,
|
||||
kvm_bindings::kvm_xcrs as ExtendedControlRegisters, kvm_bindings::kvm_xsave,
|
||||
kvm_bindings::CpuId, kvm_bindings::MsrList, kvm_bindings::Msrs as MsrEntries,
|
||||
kvm_bindings::KVM_CPUID_FLAG_SIGNIFCANT_INDEX,
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
#[macro_use]
|
||||
extern crate anyhow;
|
||||
#[allow(unused_imports)]
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
|
||||
@@ -134,7 +134,6 @@ pub const USER_MEMORY_REGION_READ: u32 = 1;
|
||||
pub const USER_MEMORY_REGION_WRITE: u32 = 1 << 1;
|
||||
pub const USER_MEMORY_REGION_EXECUTE: u32 = 1 << 2;
|
||||
pub const USER_MEMORY_REGION_LOG_DIRTY: u32 = 1 << 3;
|
||||
pub const USER_MEMORY_REGION_ADJUSTABLE: u32 = 1 << 4;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum MpState {
|
||||
@@ -163,7 +162,7 @@ pub enum CpuState {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
pub enum ClockData {
|
||||
#[cfg(feature = "kvm")]
|
||||
Kvm(kvm_bindings::kvm_clock_data),
|
||||
Kvm(kvm_bindings::kvm_clock_data_old),
|
||||
#[cfg(feature = "mshv")]
|
||||
Mshv, /* MSHV does not support ClockData yet */
|
||||
}
|
||||
|
||||
@@ -13,8 +13,8 @@ use crate::hypervisor;
|
||||
use crate::vec_with_array_field;
|
||||
use crate::vm::{self, InterruptSourceConfig, VmOps};
|
||||
use crate::HypervisorType;
|
||||
use mshv_bindings::*;
|
||||
use mshv_ioctls::{set_registers_64, InterruptRequest, Mshv, NoDatamatch, VcpuFd, VmFd, VmType};
|
||||
pub use mshv_bindings::*;
|
||||
use mshv_ioctls::{set_registers_64, Mshv, NoDatamatch, VcpuFd, VmFd, VmType};
|
||||
use std::any::Any;
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, RwLock};
|
||||
@@ -29,13 +29,9 @@ pub mod x86_64;
|
||||
#[cfg(feature = "sev_snp")]
|
||||
use snp_constants::*;
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
use crate::ClockData;
|
||||
|
||||
use crate::{
|
||||
CpuState, IoEventAddress, IrqRoutingEntry, MpState, UserMemoryRegion,
|
||||
USER_MEMORY_REGION_ADJUSTABLE, USER_MEMORY_REGION_EXECUTE, USER_MEMORY_REGION_READ,
|
||||
USER_MEMORY_REGION_WRITE,
|
||||
ClockData, CpuState, IoEventAddress, IrqRoutingEntry, MpState, UserMemoryRegion,
|
||||
USER_MEMORY_REGION_EXECUTE, USER_MEMORY_REGION_READ, USER_MEMORY_REGION_WRITE,
|
||||
};
|
||||
#[cfg(feature = "sev_snp")]
|
||||
use igvm_defs::IGVM_VHS_SNP_ID_BLOCK;
|
||||
@@ -77,9 +73,6 @@ impl From<mshv_user_mem_region> for UserMemoryRegion {
|
||||
if region.flags & HV_MAP_GPA_EXECUTABLE != 0 {
|
||||
flags |= USER_MEMORY_REGION_EXECUTE;
|
||||
}
|
||||
if region.flags & HV_MAP_GPA_ADJUSTABLE != 0 {
|
||||
flags |= USER_MEMORY_REGION_ADJUSTABLE;
|
||||
}
|
||||
|
||||
UserMemoryRegion {
|
||||
guest_phys_addr: (region.guest_pfn << PAGE_SHIFT as u64)
|
||||
@@ -104,9 +97,6 @@ impl From<UserMemoryRegion> for mshv_user_mem_region {
|
||||
if region.flags & USER_MEMORY_REGION_EXECUTE != 0 {
|
||||
flags |= HV_MAP_GPA_EXECUTABLE;
|
||||
}
|
||||
if region.flags & USER_MEMORY_REGION_ADJUSTABLE != 0 {
|
||||
flags |= HV_MAP_GPA_ADJUSTABLE;
|
||||
}
|
||||
|
||||
mshv_user_mem_region {
|
||||
guest_pfn: region.guest_phys_addr >> PAGE_SHIFT,
|
||||
@@ -291,39 +281,25 @@ impl hypervisor::Hypervisor for MshvHypervisor {
|
||||
)
|
||||
.map_err(|e| hypervisor::HypervisorError::SetPartitionProperty(e.into()))?;
|
||||
|
||||
let msr_list = self.get_msr_list()?;
|
||||
let num_msrs = msr_list.as_fam_struct_ref().nmsrs as usize;
|
||||
let mut msrs: Vec<MsrEntry> = vec![
|
||||
MsrEntry {
|
||||
..Default::default()
|
||||
};
|
||||
num_msrs
|
||||
];
|
||||
let indices = msr_list.as_slice();
|
||||
for (pos, index) in indices.iter().enumerate() {
|
||||
msrs[pos].index = *index;
|
||||
}
|
||||
let vm_fd = Arc::new(fd);
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
{
|
||||
let msr_list = self.get_msr_list()?;
|
||||
let num_msrs = msr_list.as_fam_struct_ref().nmsrs as usize;
|
||||
let mut msrs: Vec<MsrEntry> = vec![
|
||||
MsrEntry {
|
||||
..Default::default()
|
||||
};
|
||||
num_msrs
|
||||
];
|
||||
let indices = msr_list.as_slice();
|
||||
for (pos, index) in indices.iter().enumerate() {
|
||||
msrs[pos].index = *index;
|
||||
}
|
||||
|
||||
Ok(Arc::new(MshvVm {
|
||||
fd: vm_fd,
|
||||
msrs,
|
||||
dirty_log_slots: Arc::new(RwLock::new(HashMap::new())),
|
||||
#[cfg(feature = "sev_snp")]
|
||||
sev_snp_enabled: mshv_vm_type == VmType::Snp,
|
||||
}))
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
{
|
||||
Ok(Arc::new(MshvVm {
|
||||
fd: vm_fd,
|
||||
dirty_log_slots: Arc::new(RwLock::new(HashMap::new())),
|
||||
}))
|
||||
}
|
||||
Ok(Arc::new(MshvVm {
|
||||
fd: vm_fd,
|
||||
msrs,
|
||||
dirty_log_slots: Arc::new(RwLock::new(HashMap::new())),
|
||||
}))
|
||||
}
|
||||
|
||||
/// Create a mshv vm object and return the object as Vm trait object
|
||||
@@ -341,7 +317,6 @@ impl hypervisor::Hypervisor for MshvHypervisor {
|
||||
let vm_type = 0;
|
||||
self.create_vm_with_type(vm_type)
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
/// Get the supported CpuID
|
||||
///
|
||||
@@ -361,11 +336,10 @@ impl hypervisor::Hypervisor for MshvHypervisor {
|
||||
pub struct MshvVcpu {
|
||||
fd: VcpuFd,
|
||||
vp_index: u8,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
cpuid: Vec<CpuIdEntry>,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
msrs: Vec<MsrEntry>,
|
||||
vm_ops: Option<Arc<dyn vm::VmOps>>,
|
||||
#[cfg(feature = "sev_snp")]
|
||||
vm_fd: Arc<VmFd>,
|
||||
}
|
||||
|
||||
@@ -508,7 +482,6 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
warn!("TRIPLE FAULT");
|
||||
Ok(cpu::VmExit::Shutdown)
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
hv_message_type_HVMSG_X64_IO_PORT_INTERCEPT => {
|
||||
let info = x.to_ioport_info().unwrap();
|
||||
let access_info = info.access_info;
|
||||
@@ -599,7 +572,6 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetRegister(e.into()))?;
|
||||
Ok(cpu::VmExit::Ignore)
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
hv_message_type_HVMSG_UNMAPPED_GPA => {
|
||||
let info = x.to_memory_info().unwrap();
|
||||
let insn_len = info.instruction_byte_count as usize;
|
||||
@@ -625,70 +597,6 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
|
||||
Ok(cpu::VmExit::Ignore)
|
||||
}
|
||||
#[cfg(feature = "sev_snp")]
|
||||
hv_message_type_HVMSG_GPA_ATTRIBUTE_INTERCEPT => {
|
||||
let info = x.to_gpa_attribute_info().unwrap();
|
||||
let host_vis = info.__bindgen_anon_1.host_visibility();
|
||||
if host_vis >= HV_MAP_GPA_READABLE | HV_MAP_GPA_WRITABLE {
|
||||
warn!("Ignored attribute intercept with full host visibility");
|
||||
return Ok(cpu::VmExit::Ignore);
|
||||
}
|
||||
|
||||
let num_ranges = info.__bindgen_anon_1.range_count();
|
||||
assert!(num_ranges >= 1);
|
||||
if num_ranges > 1 {
|
||||
return Err(cpu::HypervisorCpuError::RunVcpu(anyhow!(
|
||||
"Unhandled VCPU exit(GPA_ATTRIBUTE_INTERCEPT): Expected num_ranges to be 1 but found num_ranges {:?}",
|
||||
num_ranges
|
||||
)));
|
||||
}
|
||||
|
||||
// TODO: we could also deny the request with HvCallCompleteIntercept
|
||||
let mut gpas = Vec::new();
|
||||
let ranges = info.ranges;
|
||||
let (gfn_start, gfn_count) = snp::parse_gpa_range(ranges[0]).unwrap();
|
||||
debug!(
|
||||
"Releasing pages: gfn_start: {:x?}, gfn_count: {:?}",
|
||||
gfn_start, gfn_count
|
||||
);
|
||||
let gpa_start = gfn_start * HV_PAGE_SIZE as u64;
|
||||
for i in 0..gfn_count {
|
||||
gpas.push(gpa_start + i * HV_PAGE_SIZE as u64);
|
||||
}
|
||||
|
||||
let mut gpa_list =
|
||||
vec_with_array_field::<mshv_modify_gpa_host_access, u64>(gpas.len());
|
||||
gpa_list[0].gpa_list_size = gpas.len() as u64;
|
||||
gpa_list[0].host_access = host_vis;
|
||||
gpa_list[0].acquire = 0;
|
||||
gpa_list[0].flags = 0;
|
||||
|
||||
// SAFETY: gpa_list initialized with gpas.len() and now it is being turned into
|
||||
// gpas_slice with gpas.len() again. It is guaranteed to be large enough to hold
|
||||
// everything from gpas.
|
||||
unsafe {
|
||||
let gpas_slice: &mut [u64] = gpa_list[0].gpa_list.as_mut_slice(gpas.len());
|
||||
gpas_slice.copy_from_slice(gpas.as_slice());
|
||||
}
|
||||
|
||||
self.vm_fd
|
||||
.modify_gpa_host_access(&gpa_list[0])
|
||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(anyhow!(
|
||||
"Unhandled VCPU exit: attribute intercept - couldn't modify host access {}", e
|
||||
)))?;
|
||||
Ok(cpu::VmExit::Ignore)
|
||||
}
|
||||
hv_message_type_HVMSG_UNACCEPTED_GPA => {
|
||||
let info = x.to_memory_info().unwrap();
|
||||
let gva = info.guest_virtual_address;
|
||||
let gpa = info.guest_physical_address;
|
||||
|
||||
Err(cpu::HypervisorCpuError::RunVcpu(anyhow!(
|
||||
"Unhandled VCPU exit: Unaccepted GPA({:x}) found at GVA({:x})",
|
||||
gpa,
|
||||
gva,
|
||||
)))
|
||||
}
|
||||
hv_message_type_HVMSG_X64_CPUID_INTERCEPT => {
|
||||
let info = x.to_cpuid_info().unwrap();
|
||||
debug!("cpuid eax: {:x}", { info.rax });
|
||||
@@ -709,7 +617,6 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
debug!("Exception Info {:?}", { info.exception_vector });
|
||||
Ok(cpu::VmExit::Ignore)
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
hv_message_type_HVMSG_X64_APIC_EOI => {
|
||||
let info = x.to_apic_eoi_info().unwrap();
|
||||
// The kernel should dispatch the EOI to the correct thread.
|
||||
@@ -1123,14 +1030,13 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
.sev_snp_ap_create(&mshv_ap_create_req)
|
||||
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
|
||||
|
||||
let mut swei1_rw_gpa_arg = mshv_bindings::mshv_read_write_gpa {
|
||||
base_gpa: ghcb_gpa + GHCB_SW_EXITINFO1_OFFSET,
|
||||
let mut swei2_rw_gpa_arg = mshv_bindings::mshv_read_write_gpa {
|
||||
base_gpa: ghcb_gpa + GHCB_SW_EXITINFO2_OFFSET,
|
||||
byte_count: std::mem::size_of::<u64>() as u32,
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
self.fd
|
||||
.gpa_write(&mut swei1_rw_gpa_arg)
|
||||
.gpa_write(&mut swei2_rw_gpa_arg)
|
||||
.map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?;
|
||||
}
|
||||
_ => panic!(
|
||||
@@ -1160,46 +1066,6 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn init_pmu(&self, irq: u32) -> cpu::Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn has_pmu_support(&self) -> bool {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn setup_regs(&self, cpu_id: u8, boot_ip: u64, fdt_start: u64) -> cpu::Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn get_sys_reg(&self, sys_reg: u32) -> cpu::Result<u64> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn get_reg_list(&self, reg_list: &mut RegList) -> cpu::Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn vcpu_init(&self, kvi: &VcpuInit) -> cpu::Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn set_regs(&self, regs: &StandardRegisters) -> cpu::Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn get_regs(&self) -> cpu::Result<StandardRegisters> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
/// X86 specific call to setup the CPUID registers.
|
||||
@@ -1275,18 +1141,19 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
/// Set CPU state for x86_64 guest.
|
||||
/// Set CPU state
|
||||
///
|
||||
fn set_state(&self, state: &CpuState) -> cpu::Result<()> {
|
||||
let mut state: VcpuMshvState = state.clone().into();
|
||||
let state: VcpuMshvState = state.clone().into();
|
||||
self.set_msrs(&state.msrs)?;
|
||||
self.set_vcpu_events(&state.vcpu_events)?;
|
||||
self.set_regs(&state.regs.into())?;
|
||||
self.set_sregs(&state.sregs.into())?;
|
||||
self.set_fpu(&state.fpu)?;
|
||||
self.set_xcrs(&state.xcrs)?;
|
||||
self.set_lapic(&state.lapic)?;
|
||||
self.set_xsave(&state.xsave)?;
|
||||
// These registers are global and needed to be set only for first VCPU
|
||||
// as Microsoft Hypervisor allows setting this regsier for only one VCPU
|
||||
if self.vp_index == 0 {
|
||||
@@ -1297,23 +1164,11 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
self.fd
|
||||
.set_debug_regs(&state.dbg)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetDebugRegs(e.into()))?;
|
||||
self.fd
|
||||
.set_all_vp_state_components(&mut state.vp_states)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetAllVpStateComponents(e.into()))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
///
|
||||
/// Set CPU state for aarch64 guest.
|
||||
///
|
||||
fn set_state(&self, state: &CpuState) -> cpu::Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
/// Get CPU State for x86_64 guest
|
||||
/// Get CPU State
|
||||
///
|
||||
fn state(&self) -> cpu::Result<CpuState> {
|
||||
let regs = self.get_regs()?;
|
||||
@@ -1323,6 +1178,8 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
let vcpu_events = self.get_vcpu_events()?;
|
||||
let mut msrs = self.msrs.clone();
|
||||
self.get_msrs(&mut msrs)?;
|
||||
let lapic = self.get_lapic()?;
|
||||
let xsave = self.get_xsave()?;
|
||||
let misc = self
|
||||
.fd
|
||||
.get_misc_regs()
|
||||
@@ -1331,10 +1188,6 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
.fd
|
||||
.get_debug_regs()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetDebugRegs(e.into()))?;
|
||||
let vp_states = self
|
||||
.fd
|
||||
.get_all_vp_state_components()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetAllVpStateComponents(e.into()))?;
|
||||
|
||||
Ok(VcpuMshvState {
|
||||
msrs,
|
||||
@@ -1343,21 +1196,14 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
sregs: sregs.into(),
|
||||
fpu,
|
||||
xcrs,
|
||||
lapic,
|
||||
dbg,
|
||||
xsave,
|
||||
misc,
|
||||
vp_states,
|
||||
}
|
||||
.into())
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
///
|
||||
/// Get CPU state for aarch64 guest.
|
||||
///
|
||||
fn state(&self) -> cpu::Result<CpuState> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
/// Translate guest virtual address to guest physical address
|
||||
@@ -1395,38 +1241,29 @@ impl cpu::Vcpu for MshvVcpu {
|
||||
]
|
||||
.to_vec()
|
||||
}
|
||||
|
||||
///
|
||||
/// Sets the AMD specific vcpu's sev control register.
|
||||
///
|
||||
#[cfg(feature = "sev_snp")]
|
||||
fn set_sev_control_register(&self, vmsa_pfn: u64) -> cpu::Result<()> {
|
||||
let sev_control_reg = snp::get_sev_control_register(vmsa_pfn);
|
||||
|
||||
self.fd
|
||||
.set_sev_control_register(sev_control_reg)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetSevControlRegister(e.into()))
|
||||
}
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
/// Trigger NMI interrupt
|
||||
///
|
||||
fn nmi(&self) -> cpu::Result<()> {
|
||||
let cfg = InterruptRequest {
|
||||
interrupt_type: hv_interrupt_type_HV_X64_INTERRUPT_TYPE_NMI,
|
||||
apic_id: self.vp_index as u64,
|
||||
level_triggered: false,
|
||||
vector: 0,
|
||||
logical_destination_mode: false,
|
||||
long_mode: false,
|
||||
};
|
||||
self.vm_fd
|
||||
.request_virtual_interrupt(&cfg)
|
||||
.map_err(|e| cpu::HypervisorCpuError::Nmi(e.into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl MshvVcpu {
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
/// X86 specific call that returns the vcpu's current "xsave struct".
|
||||
///
|
||||
fn get_xsave(&self) -> cpu::Result<Xsave> {
|
||||
self.fd
|
||||
.get_xsave()
|
||||
.map_err(|e| cpu::HypervisorCpuError::GetXsaveState(e.into()))
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
/// X86 specific call that sets the vcpu's current "xsave struct".
|
||||
///
|
||||
fn set_xsave(&self, xsave: &Xsave) -> cpu::Result<()> {
|
||||
self.fd
|
||||
.set_xsave(xsave)
|
||||
.map_err(|e| cpu::HypervisorCpuError::SetXsaveState(e.into()))
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
///
|
||||
/// X86 specific call that returns the vcpu's current "xcrs".
|
||||
@@ -1470,13 +1307,11 @@ impl MshvVcpu {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
struct MshvEmulatorContext<'a> {
|
||||
vcpu: &'a MshvVcpu,
|
||||
map: (u64, u64), // Initial GVA to GPA mapping provided by the hypervisor
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
impl<'a> MshvEmulatorContext<'a> {
|
||||
// Do the actual gva -> gpa translation
|
||||
#[allow(non_upper_case_globals)]
|
||||
@@ -1500,7 +1335,6 @@ impl<'a> MshvEmulatorContext<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
/// Platform emulation for Hyper-V
|
||||
impl<'a> PlatformEmulator for MshvEmulatorContext<'a> {
|
||||
type CpuState = EmulatorCpuState;
|
||||
@@ -1601,11 +1435,8 @@ impl<'a> PlatformEmulator for MshvEmulatorContext<'a> {
|
||||
/// Wrapper over Mshv VM ioctls.
|
||||
pub struct MshvVm {
|
||||
fd: Arc<VmFd>,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
msrs: Vec<MsrEntry>,
|
||||
dirty_log_slots: Arc<RwLock<HashMap<u64, MshvDirtyLogSlot>>>,
|
||||
#[cfg(feature = "sev_snp")]
|
||||
sev_snp_enabled: bool,
|
||||
}
|
||||
|
||||
impl MshvVm {
|
||||
@@ -1700,11 +1531,10 @@ impl vm::Vm for MshvVm {
|
||||
let vcpu = MshvVcpu {
|
||||
fd: vcpu_fd,
|
||||
vp_index: id,
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
cpuid: Vec::new(),
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
msrs: self.msrs.clone(),
|
||||
vm_ops,
|
||||
#[cfg(feature = "sev_snp")]
|
||||
vm_fd: self.fd.clone(),
|
||||
};
|
||||
Ok(Arc::new(vcpu))
|
||||
@@ -1726,11 +1556,6 @@ impl vm::Vm for MshvVm {
|
||||
addr: &IoEventAddress,
|
||||
datamatch: Option<DataMatch>,
|
||||
) -> vm::Result<()> {
|
||||
#[cfg(feature = "sev_snp")]
|
||||
if self.sev_snp_enabled {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let addr = &mshv_ioctls::IoEventAddress::from(*addr);
|
||||
debug!(
|
||||
"register_ioevent fd {} addr {:x?} datamatch {:?}",
|
||||
@@ -1758,11 +1583,6 @@ impl vm::Vm for MshvVm {
|
||||
|
||||
/// Unregister an event from a certain address it has been previously registered to.
|
||||
fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> vm::Result<()> {
|
||||
#[cfg(feature = "sev_snp")]
|
||||
if self.sev_snp_enabled {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let addr = &mshv_ioctls::IoEventAddress::from(*addr);
|
||||
debug!("unregister_ioevent fd {} addr {:x?}", fd.as_raw_fd(), addr);
|
||||
|
||||
@@ -1815,7 +1635,7 @@ impl vm::Vm for MshvVm {
|
||||
readonly: bool,
|
||||
_log_dirty_pages: bool,
|
||||
) -> UserMemoryRegion {
|
||||
let mut flags = HV_MAP_GPA_READABLE | HV_MAP_GPA_EXECUTABLE | HV_MAP_GPA_ADJUSTABLE;
|
||||
let mut flags = HV_MAP_GPA_READABLE | HV_MAP_GPA_EXECUTABLE;
|
||||
if !readonly {
|
||||
flags |= HV_MAP_GPA_WRITABLE;
|
||||
}
|
||||
@@ -1994,7 +1814,7 @@ impl vm::Vm for MshvVm {
|
||||
fn complete_isolated_import(
|
||||
&self,
|
||||
snp_id_block: IGVM_VHS_SNP_ID_BLOCK,
|
||||
host_data: [u8; 32],
|
||||
host_data: &[u8],
|
||||
id_block_enabled: u8,
|
||||
) -> vm::Result<()> {
|
||||
let mut auth_info = hv_snp_id_auth_info {
|
||||
@@ -2027,7 +1847,7 @@ impl vm::Vm for MshvVm {
|
||||
policy: get_default_snp_guest_policy(),
|
||||
},
|
||||
id_auth_info: auth_info,
|
||||
host_data,
|
||||
host_data: host_data[0..32].try_into().unwrap(),
|
||||
id_block_enabled,
|
||||
author_key_enabled: 0,
|
||||
},
|
||||
@@ -2037,14 +1857,4 @@ impl vm::Vm for MshvVm {
|
||||
.complete_isolated_import(&data)
|
||||
.map_err(|e| vm::HypervisorVmError::CompleteIsolatedImport(e.into()))
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn create_vgic(&self, config: VgicConfig) -> vm::Result<Arc<Mutex<dyn Vgic>>> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "aarch64")]
|
||||
fn get_preferred_target(&self, kvi: &mut VcpuInit) -> vm::Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,10 +19,10 @@ use std::fmt;
|
||||
///
|
||||
pub use {
|
||||
mshv_bindings::hv_cpuid_entry, mshv_bindings::mshv_user_mem_region as MemoryRegion,
|
||||
mshv_bindings::msr_entry, mshv_bindings::AllVpStateComponents, mshv_bindings::CpuId,
|
||||
mshv_bindings::DebugRegisters, mshv_bindings::FloatingPointUnit,
|
||||
mshv_bindings::LapicState as MshvLapicState, mshv_bindings::MiscRegs as MiscRegisters,
|
||||
mshv_bindings::MsrList, mshv_bindings::Msrs as MsrEntries, mshv_bindings::Msrs,
|
||||
mshv_bindings::msr_entry, mshv_bindings::CpuId, mshv_bindings::DebugRegisters,
|
||||
mshv_bindings::FloatingPointUnit, mshv_bindings::LapicState as MshvLapicState,
|
||||
mshv_bindings::MiscRegs as MiscRegisters, mshv_bindings::MsrList,
|
||||
mshv_bindings::Msrs as MsrEntries, mshv_bindings::Msrs,
|
||||
mshv_bindings::SegmentRegister as MshvSegmentRegister,
|
||||
mshv_bindings::SpecialRegisters as MshvSpecialRegisters,
|
||||
mshv_bindings::StandardRegisters as MshvStandardRegisters, mshv_bindings::SuspendRegisters,
|
||||
@@ -38,9 +38,10 @@ pub struct VcpuMshvState {
|
||||
pub sregs: MshvSpecialRegisters,
|
||||
pub fpu: FpuState,
|
||||
pub xcrs: ExtendedControlRegisters,
|
||||
pub lapic: LapicState,
|
||||
pub dbg: DebugRegisters,
|
||||
pub xsave: Xsave,
|
||||
pub misc: MiscRegisters,
|
||||
pub vp_states: AllVpStateComponents,
|
||||
}
|
||||
|
||||
impl fmt::Display for VcpuMshvState {
|
||||
@@ -52,7 +53,7 @@ impl fmt::Display for VcpuMshvState {
|
||||
msr_entries[i][1] = entry.data;
|
||||
msr_entries[i][0] = entry.index as u64;
|
||||
}
|
||||
write!(f, "Number of MSRs: {}: MSRs: {:#010X?}, -- VCPU Events: {:?} -- Standard registers: {:?} Special Registers: {:?} ---- Floating Point Unit: {:?} --- Extended Control Register: {:?} --- DBG: {:?} --- VP States: {:?}",
|
||||
write!(f, "Number of MSRs: {}: MSRs: {:#010X?}, -- VCPU Events: {:?} -- Standard registers: {:?} Special Registers: {:?} ---- Floating Point Unit: {:?} --- Extended Control Register: {:?} --- Local APIC: {:?} --- DBG: {:?} --- Xsave: {:?}",
|
||||
msr_entries.len(),
|
||||
msr_entries,
|
||||
self.vcpu_events,
|
||||
@@ -60,8 +61,9 @@ impl fmt::Display for VcpuMshvState {
|
||||
self.sregs,
|
||||
self.fpu,
|
||||
self.xcrs,
|
||||
self.lapic,
|
||||
self.dbg,
|
||||
self.vp_states,
|
||||
self.xsave,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -385,7 +385,7 @@ pub trait Vm: Send + Sync + Any {
|
||||
fn complete_isolated_import(
|
||||
&self,
|
||||
_snp_id_block: IGVM_VHS_SNP_ID_BLOCK,
|
||||
_host_data: [u8; 32],
|
||||
_host_data: &[u8],
|
||||
_id_block_enabled: u8,
|
||||
) -> Result<()> {
|
||||
unimplemented!()
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright TUNTAP, 2017 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the THIRD-PARTY file.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(non_camel_case_types)]
|
||||
|
||||
@@ -6,21 +6,23 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
epoll = "4.3.3"
|
||||
getrandom = "0.2.13"
|
||||
libc = "0.2.153"
|
||||
log = "0.4.21"
|
||||
getrandom = "0.2.10"
|
||||
libc = "0.2.147"
|
||||
log = "0.4.20"
|
||||
net_gen = { path = "../net_gen" }
|
||||
rate_limiter = { path = "../rate_limiter" }
|
||||
serde = "1.0.197"
|
||||
thiserror = "1.0.58"
|
||||
virtio-bindings = "0.2.2"
|
||||
virtio-queue = "0.11.0"
|
||||
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
serde = "1.0.168"
|
||||
thiserror = "1.0.52"
|
||||
versionize = "0.2.0"
|
||||
versionize_derive = "0.1.6"
|
||||
virtio-bindings = "0.2.0"
|
||||
virtio-queue = "0.12.0"
|
||||
vm-memory = { version = "0.14.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
vm-virtio = { path = "../vm-virtio" }
|
||||
vmm-sys-util = "0.12.1"
|
||||
|
||||
[dev-dependencies]
|
||||
once_cell = "1.19.0"
|
||||
once_cell = "1.18.0"
|
||||
pnet = "0.34.0"
|
||||
pnet_datalink = "0.34.0"
|
||||
serde_json = "1.0.115"
|
||||
serde_json = "1.0.107"
|
||||
|
||||
@@ -14,13 +14,13 @@ mod open_tap;
|
||||
mod queue_pair;
|
||||
mod tap;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io::Error as IoError;
|
||||
use std::os::raw::c_uint;
|
||||
use std::os::unix::io::{FromRawFd, RawFd};
|
||||
use std::{io, mem, net};
|
||||
use thiserror::Error;
|
||||
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use virtio_bindings::virtio_net::{
|
||||
virtio_net_hdr_v1, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MAX, VIRTIO_NET_CTRL_MQ_VQ_PAIRS_MIN,
|
||||
VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_GUEST_TSO4,
|
||||
@@ -45,7 +45,7 @@ pub enum Error {
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[repr(C, packed)]
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
||||
#[derive(Copy, Clone, Debug, Default, Versionize)]
|
||||
pub struct VirtioNetConfig {
|
||||
pub mac: [u8; 6],
|
||||
pub status: u16,
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::result::Result;
|
||||
use std::str::FromStr;
|
||||
|
||||
use serde::de::{Deserialize, Deserializer, Error};
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
use super::{register_listener, unregister_listener, vnet_hdr_len, Tap};
|
||||
use crate::GuestMemoryMmap;
|
||||
use rate_limiter::{RateLimiter, TokenType};
|
||||
use std::io;
|
||||
use std::num::Wrapping;
|
||||
@@ -12,6 +11,7 @@ use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
use virtio_queue::{Queue, QueueOwnedT, QueueT};
|
||||
use vm_memory::bitmap::Bitmap;
|
||||
use vm_memory::{Bytes, GuestMemory};
|
||||
use vm_virtio::{AccessPlatform, Translatable};
|
||||
|
||||
@@ -35,9 +35,9 @@ impl TxVirtio {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_desc_chain(
|
||||
pub fn process_desc_chain<B: Bitmap + 'static>(
|
||||
&mut self,
|
||||
mem: &GuestMemoryMmap,
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
tap: &Tap,
|
||||
queue: &mut Queue,
|
||||
rate_limiter: &mut Option<RateLimiter>,
|
||||
@@ -161,9 +161,9 @@ impl RxVirtio {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn process_desc_chain(
|
||||
pub fn process_desc_chain<B: Bitmap + 'static>(
|
||||
&mut self,
|
||||
mem: &GuestMemoryMmap,
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
tap: &Tap,
|
||||
queue: &mut Queue,
|
||||
rate_limiter: &mut Option<RateLimiter>,
|
||||
@@ -350,9 +350,9 @@ pub struct NetQueuePair {
|
||||
}
|
||||
|
||||
impl NetQueuePair {
|
||||
pub fn process_tx(
|
||||
pub fn process_tx<B: Bitmap + 'static>(
|
||||
&mut self,
|
||||
mem: &GuestMemoryMmap,
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
queue: &mut Queue,
|
||||
) -> Result<bool, NetQueuePairError> {
|
||||
let tx_tap_retry = self.tx.process_desc_chain(
|
||||
@@ -400,9 +400,9 @@ impl NetQueuePair {
|
||||
.map_err(NetQueuePairError::QueueNeedsNotification)
|
||||
}
|
||||
|
||||
pub fn process_rx(
|
||||
pub fn process_rx<B: Bitmap + 'static>(
|
||||
&mut self,
|
||||
mem: &GuestMemoryMmap,
|
||||
mem: &vm_memory::GuestMemoryMmap<B>,
|
||||
queue: &mut Queue,
|
||||
) -> Result<bool, NetQueuePairError> {
|
||||
self.rx_desc_avail = !self.rx.process_desc_chain(
|
||||
|
||||
@@ -290,17 +290,6 @@ impl TupleValue for Vec<u64> {
|
||||
}
|
||||
}
|
||||
|
||||
impl TupleValue for Vec<usize> {
|
||||
fn parse_value(input: &str) -> Result<Self, TupleError> {
|
||||
Ok(IntegerList::from_str(input)
|
||||
.map_err(TupleError::InvalidIntegerList)?
|
||||
.0
|
||||
.iter()
|
||||
.map(|v| *v as usize)
|
||||
.collect())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Tuple<S, T>(pub Vec<(S, T)>);
|
||||
|
||||
pub enum TupleError {
|
||||
|
||||
@@ -10,19 +10,21 @@ kvm = ["vfio-ioctls/kvm"]
|
||||
mshv = ["vfio-ioctls/mshv"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.81"
|
||||
byteorder = "1.5.0"
|
||||
anyhow = "1.0.75"
|
||||
byteorder = "1.4.3"
|
||||
hypervisor = { path = "../hypervisor" }
|
||||
vfio-bindings = { git = "https://github.com/rust-vmm/vfio", branch = "main", features = ["fam-wrappers"] }
|
||||
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
|
||||
vfio_user = { git = "https://github.com/rust-vmm/vfio-user", branch = "main" }
|
||||
|
||||
vmm-sys-util = "0.12.1"
|
||||
libc = "0.2.153"
|
||||
log = "0.4.21"
|
||||
serde = { version = "1.0.197", features = ["derive"] }
|
||||
thiserror = "1.0.58"
|
||||
libc = "0.2.147"
|
||||
log = "0.4.20"
|
||||
serde = { version = "1.0.168", features = ["derive"] }
|
||||
thiserror = "1.0.52"
|
||||
versionize = "0.2.0"
|
||||
versionize_derive = "0.1.6"
|
||||
vm-allocator = { path = "../vm-allocator" }
|
||||
vm-device = { path = "../vm-device" }
|
||||
vm-memory = { version = "0.14.1", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
vm-memory = { version = "0.14.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
|
||||
vm-migration = { path = "../vm-migration" }
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
use crate::configuration::{
|
||||
PciBarRegionType, PciBridgeSubclass, PciClassCode, PciConfiguration, PciHeaderType,
|
||||
|
||||
@@ -1,17 +1,16 @@
|
||||
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
use crate::device::BarReprogrammingParams;
|
||||
use crate::{MsixConfig, PciInterruptPin};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::fmt::{self, Display};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use versionize::{VersionMap, Versionize, VersionizeError, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_device::PciBarType;
|
||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable};
|
||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
|
||||
|
||||
// The number of 32bit registers in the config space, 4096 bytes.
|
||||
const NUM_CONFIGURATION_REGISTERS: usize = 1024;
|
||||
@@ -397,7 +396,7 @@ fn decode_64_bits_bar_size(bar_size_hi: u32, bar_size_lo: u32) -> Option<u64> {
|
||||
None
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, Serialize, Deserialize)]
|
||||
#[derive(Debug, Default, Clone, Copy, Versionize)]
|
||||
struct PciBar {
|
||||
addr: u32,
|
||||
size: u32,
|
||||
@@ -405,7 +404,7 @@ struct PciBar {
|
||||
r#type: Option<PciBarRegionType>,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Versionize)]
|
||||
pub struct PciConfigurationState {
|
||||
registers: Vec<u32>,
|
||||
writable_bits: Vec<u32>,
|
||||
@@ -417,6 +416,8 @@ pub struct PciConfigurationState {
|
||||
msix_cap_reg_idx: Option<usize>,
|
||||
}
|
||||
|
||||
impl VersionMapped for PciConfigurationState {}
|
||||
|
||||
/// Contains the configuration space of a PCI node.
|
||||
/// See the [specification](https://en.wikipedia.org/wiki/PCI_configuration_space).
|
||||
/// The configuration space is accessed with DWORD reads and writes from the guest.
|
||||
@@ -434,7 +435,7 @@ pub struct PciConfiguration {
|
||||
}
|
||||
|
||||
/// See pci_regs.h in kernel
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Serialize, Deserialize, Debug)]
|
||||
#[derive(Copy, Clone, PartialEq, Eq, Versionize, Debug)]
|
||||
pub enum PciBarRegionType {
|
||||
Memory32BitRegion = 0,
|
||||
IoRegion = 0x01,
|
||||
@@ -1069,7 +1070,7 @@ impl Snapshottable for PciConfiguration {
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,15 +1,13 @@
|
||||
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
use crate::configuration::{self, PciBarRegionType};
|
||||
use crate::PciBarConfiguration;
|
||||
use std::any::Any;
|
||||
use std::fmt::{self, Display};
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use std::{io, result};
|
||||
use std::{self, io, result};
|
||||
use vm_allocator::{AddressAllocator, SystemAllocator};
|
||||
use vm_device::{BusDevice, Resource};
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
// Copyright 2018 The Chromium OS Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE-BSD-3-Clause file.
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 AND BSD-3-Clause
|
||||
|
||||
//! Implements pci devices and busses.
|
||||
#[macro_use]
|
||||
@@ -28,7 +26,7 @@ pub use self::device::{
|
||||
};
|
||||
pub use self::msi::{msi_num_enabled_vectors, MsiCap, MsiConfig};
|
||||
pub use self::msix::{MsixCap, MsixConfig, MsixTableEntry, MSIX_CONFIG_ID, MSIX_TABLE_ENTRY_SIZE};
|
||||
pub use self::vfio::{MmioRegion, VfioDmaMapping, VfioPciDevice, VfioPciError};
|
||||
pub use self::vfio::{VfioPciDevice, VfioPciError};
|
||||
pub use self::vfio_user::{VfioUserDmaMapping, VfioUserPciDevice, VfioUserPciDeviceError};
|
||||
use serde::de::Visitor;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
@@ -4,14 +4,15 @@
|
||||
//
|
||||
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::io;
|
||||
use std::sync::Arc;
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_device::interrupt::{
|
||||
InterruptIndex, InterruptSourceConfig, InterruptSourceGroup, MsiIrqSourceConfig,
|
||||
};
|
||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable};
|
||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
|
||||
|
||||
// MSI control masks
|
||||
const MSI_CTL_ENABLE: u16 = 0x1;
|
||||
@@ -46,7 +47,7 @@ pub enum Error {
|
||||
|
||||
pub const MSI_CONFIG_ID: &str = "msi_config";
|
||||
|
||||
#[derive(Clone, Copy, Default, Serialize, Deserialize)]
|
||||
#[derive(Clone, Copy, Default, Versionize)]
|
||||
pub struct MsiCap {
|
||||
// Message Control Register
|
||||
// 0: MSI enable.
|
||||
@@ -171,11 +172,13 @@ impl MsiCap {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Versionize)]
|
||||
pub struct MsiConfigState {
|
||||
cap: MsiCap,
|
||||
}
|
||||
|
||||
impl VersionMapped for MsiConfigState {}
|
||||
|
||||
pub struct MsiConfig {
|
||||
pub cap: MsiCap,
|
||||
interrupt_source_group: Arc<dyn InterruptSourceGroup>,
|
||||
@@ -291,6 +294,6 @@ impl Snapshottable for MsiConfig {
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,16 +5,16 @@
|
||||
|
||||
use crate::{PciCapability, PciCapabilityId};
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use serde::Deserialize;
|
||||
use serde::Serialize;
|
||||
use std::io;
|
||||
use std::result;
|
||||
use std::sync::Arc;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vm_device::interrupt::{
|
||||
InterruptIndex, InterruptSourceConfig, InterruptSourceGroup, MsiIrqSourceConfig,
|
||||
};
|
||||
use vm_memory::ByteValued;
|
||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable};
|
||||
use vm_migration::{MigratableError, Pausable, Snapshot, Snapshottable, VersionMapped};
|
||||
|
||||
const MAX_MSIX_VECTORS_PER_DEVICE: u16 = 2048;
|
||||
const MSIX_TABLE_ENTRIES_MODULO: u64 = 16;
|
||||
@@ -35,7 +35,7 @@ pub enum Error {
|
||||
UpdateInterruptRoute(io::Error),
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize, Eq, PartialEq)]
|
||||
#[derive(Debug, Clone, Versionize, Eq, PartialEq)]
|
||||
pub struct MsixTableEntry {
|
||||
pub msg_addr_lo: u32,
|
||||
pub msg_addr_hi: u32,
|
||||
@@ -60,7 +60,7 @@ impl Default for MsixTableEntry {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Versionize)]
|
||||
pub struct MsixConfigState {
|
||||
table_entries: Vec<MsixTableEntry>,
|
||||
pba_entries: Vec<u64>,
|
||||
@@ -68,6 +68,8 @@ pub struct MsixConfigState {
|
||||
enabled: bool,
|
||||
}
|
||||
|
||||
impl VersionMapped for MsixConfigState {}
|
||||
|
||||
pub struct MsixConfig {
|
||||
pub table_entries: Vec<MsixTableEntry>,
|
||||
pub pba_entries: Vec<u64>,
|
||||
@@ -434,13 +436,13 @@ impl Snapshottable for MsixConfig {
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
Snapshot::new_from_state(&self.state())
|
||||
Snapshot::new_from_versioned_state(&self.state())
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
#[repr(packed)]
|
||||
#[derive(Clone, Copy, Default, Serialize, Deserialize)]
|
||||
#[derive(Clone, Copy, Default, Versionize)]
|
||||
pub struct MsixCap {
|
||||
// Message Control Register
|
||||
// 10-0: MSI-X Table size
|
||||
|
||||
255
pci/src/vfio.rs
255
pci/src/vfio.rs
@@ -15,7 +15,6 @@ use anyhow::anyhow;
|
||||
use byteorder::{ByteOrder, LittleEndian};
|
||||
use hypervisor::HypervisorVmError;
|
||||
use libc::{sysconf, _SC_PAGESIZE};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::any::Any;
|
||||
use std::collections::{BTreeMap, HashMap};
|
||||
use std::io;
|
||||
@@ -23,6 +22,8 @@ use std::os::unix::io::AsRawFd;
|
||||
use std::ptr::null_mut;
|
||||
use std::sync::{Arc, Barrier, Mutex};
|
||||
use thiserror::Error;
|
||||
use versionize::{VersionMap, Versionize, VersionizeResult};
|
||||
use versionize_derive::Versionize;
|
||||
use vfio_bindings::bindings::vfio::*;
|
||||
use vfio_ioctls::{
|
||||
VfioContainer, VfioDevice, VfioIrq, VfioRegionInfoCap, VfioRegionSparseMmapArea,
|
||||
@@ -31,13 +32,14 @@ use vm_allocator::page_size::{
|
||||
align_page_size_down, align_page_size_up, is_4k_aligned, is_4k_multiple, is_page_size_aligned,
|
||||
};
|
||||
use vm_allocator::{AddressAllocator, SystemAllocator};
|
||||
use vm_device::dma_mapping::ExternalDmaMapping;
|
||||
use vm_device::interrupt::{
|
||||
InterruptIndex, InterruptManager, InterruptSourceGroup, MsiIrqGroupConfig,
|
||||
};
|
||||
use vm_device::{BusDevice, Resource};
|
||||
use vm_memory::{Address, GuestAddress, GuestAddressSpace, GuestMemory, GuestUsize};
|
||||
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
|
||||
use vm_memory::{Address, GuestAddress, GuestUsize};
|
||||
use vm_migration::{
|
||||
Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable, VersionMapped,
|
||||
};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
pub(crate) const VFIO_COMMON_ID: &str = "vfio_common";
|
||||
@@ -92,7 +94,7 @@ enum InterruptUpdateAction {
|
||||
DisableMsix,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Versionize)]
|
||||
struct IntxState {
|
||||
enabled: bool,
|
||||
}
|
||||
@@ -102,7 +104,7 @@ pub(crate) struct VfioIntx {
|
||||
enabled: bool,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Versionize)]
|
||||
struct MsiState {
|
||||
cap: MsiCap,
|
||||
cap_offset: u32,
|
||||
@@ -134,7 +136,7 @@ impl VfioMsi {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Versionize)]
|
||||
struct MsixState {
|
||||
cap: MsixCap,
|
||||
cap_offset: u32,
|
||||
@@ -272,48 +274,6 @@ pub struct MmioRegion {
|
||||
pub(crate) index: u32,
|
||||
pub(crate) user_memory_regions: Vec<UserMemoryRegion>,
|
||||
}
|
||||
|
||||
trait MmioRegionRange {
|
||||
fn check_range(&self, guest_addr: u64, size: u64) -> bool;
|
||||
fn find_user_address(&self, guest_addr: u64) -> Result<u64, io::Error>;
|
||||
}
|
||||
|
||||
impl MmioRegionRange for Vec<MmioRegion> {
|
||||
// Check if a guest address is within the range of mmio regions
|
||||
fn check_range(&self, guest_addr: u64, size: u64) -> bool {
|
||||
for region in self.iter() {
|
||||
let Some(guest_addr_end) = guest_addr.checked_add(size) else {
|
||||
return false;
|
||||
};
|
||||
let Some(region_end) = region.start.raw_value().checked_add(region.length) else {
|
||||
return false;
|
||||
};
|
||||
if guest_addr >= region.start.raw_value() && guest_addr_end <= region_end {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
// Locate the user region address for a guest address within all mmio regions
|
||||
fn find_user_address(&self, guest_addr: u64) -> Result<u64, io::Error> {
|
||||
for region in self.iter() {
|
||||
for user_region in region.user_memory_regions.iter() {
|
||||
if guest_addr >= user_region.start
|
||||
&& guest_addr < user_region.start + user_region.size
|
||||
{
|
||||
return Ok(user_region.host_addr + (guest_addr - user_region.start));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("unable to find user address: 0x{guest_addr:x}"),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum VfioError {
|
||||
#[error("Kernel VFIO error: {0}")]
|
||||
@@ -437,13 +397,15 @@ impl Vfio for VfioDeviceWrapper {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
#[derive(Versionize)]
|
||||
struct VfioCommonState {
|
||||
intx_state: Option<IntxState>,
|
||||
msi_state: Option<MsiState>,
|
||||
msix_state: Option<MsixState>,
|
||||
}
|
||||
|
||||
impl VersionMapped for VfioCommonState {}
|
||||
|
||||
pub(crate) struct ConfigPatch {
|
||||
mask: u32,
|
||||
patch: u32,
|
||||
@@ -457,7 +419,6 @@ pub(crate) struct VfioCommon {
|
||||
pub(crate) legacy_interrupt_group: Option<Arc<dyn InterruptSourceGroup>>,
|
||||
pub(crate) vfio_wrapper: Arc<dyn Vfio>,
|
||||
pub(crate) patches: HashMap<usize, ConfigPatch>,
|
||||
x_nv_gpudirect_clique: Option<u8>,
|
||||
}
|
||||
|
||||
impl VfioCommon {
|
||||
@@ -468,15 +429,15 @@ impl VfioCommon {
|
||||
subclass: &dyn PciSubclass,
|
||||
bdf: PciBdf,
|
||||
snapshot: Option<Snapshot>,
|
||||
x_nv_gpudirect_clique: Option<u8>,
|
||||
) -> Result<Self, VfioPciError> {
|
||||
let pci_configuration_state =
|
||||
vm_migration::state_from_id(snapshot.as_ref(), PCI_CONFIGURATION_ID).map_err(|e| {
|
||||
VfioPciError::RetrievePciConfigurationState(anyhow!(
|
||||
"Failed to get PciConfigurationState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
vm_migration::versioned_state_from_id(snapshot.as_ref(), PCI_CONFIGURATION_ID)
|
||||
.map_err(|e| {
|
||||
VfioPciError::RetrievePciConfigurationState(anyhow!(
|
||||
"Failed to get PciConfigurationState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
|
||||
let configuration = PciConfiguration::new(
|
||||
0,
|
||||
@@ -504,12 +465,11 @@ impl VfioCommon {
|
||||
legacy_interrupt_group,
|
||||
vfio_wrapper,
|
||||
patches: HashMap::new(),
|
||||
x_nv_gpudirect_clique,
|
||||
};
|
||||
|
||||
let state: Option<VfioCommonState> = snapshot
|
||||
.as_ref()
|
||||
.map(|s| s.to_state())
|
||||
.map(|s| s.to_versioned_state())
|
||||
.transpose()
|
||||
.map_err(|e| {
|
||||
VfioPciError::RetrieveVfioCommonState(anyhow!(
|
||||
@@ -517,20 +477,20 @@ impl VfioCommon {
|
||||
e
|
||||
))
|
||||
})?;
|
||||
let msi_state =
|
||||
vm_migration::state_from_id(snapshot.as_ref(), MSI_CONFIG_ID).map_err(|e| {
|
||||
let msi_state = vm_migration::versioned_state_from_id(snapshot.as_ref(), MSI_CONFIG_ID)
|
||||
.map_err(|e| {
|
||||
VfioPciError::RetrieveMsiConfigState(anyhow!(
|
||||
"Failed to get MsiConfigState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
let msix_state =
|
||||
vm_migration::state_from_id(snapshot.as_ref(), MSIX_CONFIG_ID).map_err(|e| {
|
||||
VfioPciError::RetrieveMsixConfigState(anyhow!(
|
||||
"Failed to get MsixConfigState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
let msix_state = vm_migration::versioned_state_from_id(snapshot.as_ref(), MSIX_CONFIG_ID)
|
||||
.map_err(|e| {
|
||||
VfioPciError::RetrieveMsixConfigState(anyhow!(
|
||||
"Failed to get MsixConfigState from Snapshot: {}",
|
||||
e
|
||||
))
|
||||
})?;
|
||||
|
||||
if let Some(state) = state.as_ref() {
|
||||
vfio_common.set_state(state, msi_state, msix_state)?;
|
||||
@@ -899,15 +859,15 @@ impl VfioCommon {
|
||||
}
|
||||
|
||||
pub(crate) fn parse_capabilities(&mut self, bdf: PciBdf) {
|
||||
let mut cap_iter = self
|
||||
let mut cap_next = self
|
||||
.vfio_wrapper
|
||||
.read_config_byte(PCI_CONFIG_CAPABILITY_OFFSET);
|
||||
|
||||
let mut pci_express_cap_found = false;
|
||||
let mut power_management_cap_found = false;
|
||||
|
||||
while cap_iter != 0 {
|
||||
let cap_id = self.vfio_wrapper.read_config_byte(cap_iter.into());
|
||||
while cap_next != 0 {
|
||||
let cap_id = self.vfio_wrapper.read_config_byte(cap_next.into());
|
||||
|
||||
match PciCapabilityId::from(cap_id) {
|
||||
PciCapabilityId::MessageSignalledInterrupts => {
|
||||
@@ -915,8 +875,8 @@ impl VfioCommon {
|
||||
if irq_info.count > 0 {
|
||||
// Parse capability only if the VFIO device
|
||||
// supports MSI.
|
||||
let msg_ctl = self.parse_msi_capabilities(cap_iter);
|
||||
self.initialize_msi(msg_ctl, cap_iter as u32, None);
|
||||
let msg_ctl = self.parse_msi_capabilities(cap_next);
|
||||
self.initialize_msi(msg_ctl, cap_next as u32, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -926,8 +886,8 @@ impl VfioCommon {
|
||||
if irq_info.count > 0 {
|
||||
// Parse capability only if the VFIO device
|
||||
// supports MSI-X.
|
||||
let msix_cap = self.parse_msix_capabilities(cap_iter);
|
||||
self.initialize_msix(msix_cap, cap_iter as u32, bdf, None);
|
||||
let msix_cap = self.parse_msix_capabilities(cap_next);
|
||||
self.initialize_msix(msix_cap, cap_next as u32, bdf, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -936,16 +896,7 @@ impl VfioCommon {
|
||||
_ => {}
|
||||
};
|
||||
|
||||
let cap_next = self.vfio_wrapper.read_config_byte((cap_iter + 1).into());
|
||||
if cap_next == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
cap_iter = cap_next;
|
||||
}
|
||||
|
||||
if let Some(clique_id) = self.x_nv_gpudirect_clique {
|
||||
self.add_nv_gpudirect_clique_cap(cap_iter, clique_id);
|
||||
cap_next = self.vfio_wrapper.read_config_byte((cap_next + 1).into());
|
||||
}
|
||||
|
||||
if pci_express_cap_found && power_management_cap_found {
|
||||
@@ -953,37 +904,6 @@ impl VfioCommon {
|
||||
}
|
||||
}
|
||||
|
||||
fn add_nv_gpudirect_clique_cap(&mut self, cap_iter: u8, clique_id: u8) {
|
||||
// Turing, Ampere, Hopper, and Lovelace GPUs have dedicated space
|
||||
// at 0xD4 for this capability.
|
||||
let cap_offset = 0xd4u32;
|
||||
|
||||
let reg_idx = (cap_iter / 4) as usize;
|
||||
self.patches.insert(
|
||||
reg_idx,
|
||||
ConfigPatch {
|
||||
mask: 0x0000_ff00,
|
||||
patch: cap_offset << 8,
|
||||
},
|
||||
);
|
||||
|
||||
let reg_idx = (cap_offset / 4) as usize;
|
||||
self.patches.insert(
|
||||
reg_idx,
|
||||
ConfigPatch {
|
||||
mask: 0xffff_ffff,
|
||||
patch: 0x50080009u32,
|
||||
},
|
||||
);
|
||||
self.patches.insert(
|
||||
reg_idx + 1,
|
||||
ConfigPatch {
|
||||
mask: 0xffff_ffff,
|
||||
patch: u32::from(clique_id) << 19 | 0x5032,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
fn parse_extended_capabilities(&mut self) {
|
||||
let mut current_offset = PCI_CONFIG_EXTENDED_CAPABILITY_OFFSET;
|
||||
|
||||
@@ -1382,7 +1302,7 @@ impl Snapshottable for VfioCommon {
|
||||
}
|
||||
|
||||
fn snapshot(&mut self) -> std::result::Result<Snapshot, MigratableError> {
|
||||
let mut vfio_common_snapshot = Snapshot::new_from_state(&self.state())?;
|
||||
let mut vfio_common_snapshot = Snapshot::new_from_versioned_state(&self.state())?;
|
||||
|
||||
// Snapshot PciConfiguration
|
||||
vfio_common_snapshot.add_snapshot(self.configuration.id(), self.configuration.snapshot()?);
|
||||
@@ -1431,7 +1351,6 @@ impl VfioPciDevice {
|
||||
bdf: PciBdf,
|
||||
memory_slot: Arc<dyn Fn() -> u32 + Send + Sync>,
|
||||
snapshot: Option<Snapshot>,
|
||||
x_nv_gpudirect_clique: Option<u8>,
|
||||
) -> Result<Self, VfioPciError> {
|
||||
let device = Arc::new(device);
|
||||
device.reset();
|
||||
@@ -1445,7 +1364,6 @@ impl VfioPciDevice {
|
||||
&PciVfioSubclass::VfioSubclass,
|
||||
bdf,
|
||||
vm_migration::snapshot_from_id(snapshot.as_ref(), VFIO_COMMON_ID),
|
||||
x_nv_gpudirect_clique,
|
||||
)?;
|
||||
|
||||
let vfio_pci_device = VfioPciDevice {
|
||||
@@ -1653,16 +1571,6 @@ impl VfioPciDevice {
|
||||
self.vm
|
||||
.create_user_memory_region(mem_region)
|
||||
.map_err(VfioPciError::CreateUserMemoryRegion)?;
|
||||
|
||||
if !self.iommu_attached {
|
||||
self.container
|
||||
.vfio_dma_map(
|
||||
user_memory_region.start,
|
||||
user_memory_region.size,
|
||||
user_memory_region.host_addr,
|
||||
)
|
||||
.map_err(VfioPciError::DmaMap)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1673,16 +1581,6 @@ impl VfioPciDevice {
|
||||
pub fn unmap_mmio_regions(&mut self) {
|
||||
for region in self.common.mmio_regions.iter() {
|
||||
for user_memory_region in region.user_memory_regions.iter() {
|
||||
// Unmap from vfio container
|
||||
if !self.iommu_attached {
|
||||
if let Err(e) = self
|
||||
.container
|
||||
.vfio_dma_unmap(user_memory_region.start, user_memory_region.size)
|
||||
{
|
||||
error!("Could not unmap mmio region from vfio container: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Remove region
|
||||
let r = self.vm.make_user_memory_region(
|
||||
user_memory_region.slot,
|
||||
@@ -1922,80 +1820,3 @@ impl Snapshottable for VfioPciDevice {
|
||||
}
|
||||
impl Transportable for VfioPciDevice {}
|
||||
impl Migratable for VfioPciDevice {}
|
||||
|
||||
/// This structure implements the ExternalDmaMapping trait. It is meant to
|
||||
/// be used when the caller tries to provide a way to update the mappings
|
||||
/// associated with a specific VFIO container.
|
||||
pub struct VfioDmaMapping<M: GuestAddressSpace> {
|
||||
container: Arc<VfioContainer>,
|
||||
memory: Arc<M>,
|
||||
mmio_regions: Arc<Mutex<Vec<MmioRegion>>>,
|
||||
}
|
||||
|
||||
impl<M: GuestAddressSpace> VfioDmaMapping<M> {
|
||||
/// Create a DmaMapping object.
|
||||
/// # Parameters
|
||||
/// * `container`: VFIO container object.
|
||||
/// * `memory`: guest memory to mmap.
|
||||
/// * `mmio_regions`: mmio_regions to mmap.
|
||||
pub fn new(
|
||||
container: Arc<VfioContainer>,
|
||||
memory: Arc<M>,
|
||||
mmio_regions: Arc<Mutex<Vec<MmioRegion>>>,
|
||||
) -> Self {
|
||||
VfioDmaMapping {
|
||||
container,
|
||||
memory,
|
||||
mmio_regions,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<M: GuestAddressSpace + Sync + Send> ExternalDmaMapping for VfioDmaMapping<M> {
|
||||
fn map(&self, iova: u64, gpa: u64, size: u64) -> std::result::Result<(), io::Error> {
|
||||
let mem = self.memory.memory();
|
||||
let guest_addr = GuestAddress(gpa);
|
||||
let user_addr = if mem.check_range(guest_addr, size as usize) {
|
||||
match mem.get_host_address(guest_addr) {
|
||||
Ok(t) => t as u64,
|
||||
Err(e) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("unable to retrieve user address for gpa 0x{gpa:x} from guest memory region: {e}")
|
||||
));
|
||||
}
|
||||
}
|
||||
} else if self.mmio_regions.lock().unwrap().check_range(gpa, size) {
|
||||
self.mmio_regions.lock().unwrap().find_user_address(gpa)?
|
||||
} else {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!("failed to locate guest address 0x{gpa:x} in guest memory"),
|
||||
));
|
||||
};
|
||||
|
||||
self.container
|
||||
.vfio_dma_map(iova, size, user_addr)
|
||||
.map_err(|e| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!(
|
||||
"failed to map memory for VFIO container, \
|
||||
iova 0x{iova:x}, gpa 0x{gpa:x}, size 0x{size:x}: {e:?}"
|
||||
),
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn unmap(&self, iova: u64, size: u64) -> std::result::Result<(), io::Error> {
|
||||
self.container.vfio_dma_unmap(iova, size).map_err(|e| {
|
||||
io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
format!(
|
||||
"failed to unmap memory for VFIO container, \
|
||||
iova 0x{iova:x}, size 0x{size:x}: {e:?}"
|
||||
),
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,7 +94,6 @@ impl VfioUserPciDevice {
|
||||
&PciVfioUserSubclass::VfioUserSubclass,
|
||||
bdf,
|
||||
vm_migration::snapshot_from_id(snapshot.as_ref(), VFIO_COMMON_ID),
|
||||
None,
|
||||
)
|
||||
.map_err(VfioUserPciDeviceError::CreateVfioCommon)?;
|
||||
|
||||
|
||||
@@ -6,10 +6,10 @@ edition = "2021"
|
||||
build = "../build.rs"
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.5.4", features = ["wrap_help"] }
|
||||
dirs = "5.0.1"
|
||||
serde = { version = "1.0.197", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.115"
|
||||
clap = { version = "4.4.7", features = ["wrap_help"] }
|
||||
dirs = "5.0.0"
|
||||
serde = { version = "1.0.168", features = ["rc", "derive"] }
|
||||
serde_json = "1.0.107"
|
||||
test_infra = { path = "../test_infra" }
|
||||
thiserror = "1.0.58"
|
||||
thiserror = "1.0.40"
|
||||
wait-timeout = "0.2.0"
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
use crate::{mean, PerformanceTestControl};
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
use std::string::String;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
use test_infra::Error as InfraError;
|
||||
|
||||
@@ -4,8 +4,7 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
epoll = "4.3.3"
|
||||
libc = "0.2.153"
|
||||
log = "0.4.21"
|
||||
thiserror = "1.0.58"
|
||||
libc = "0.2.147"
|
||||
log = "0.4.20"
|
||||
thiserror = "1.0.40"
|
||||
vmm-sys-util = "0.12.1"
|
||||
|
||||
@@ -1,526 +0,0 @@
|
||||
// Copyright 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
//
|
||||
// Copyright 2023 Crusoe Energy Systems LLC
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
use crate::{RateLimiter, TokenType};
|
||||
use core::panic::AssertUnwindSafe;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
|
||||
use std::result;
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::thread;
|
||||
use thiserror::Error;
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
/// Errors associated with rate-limiter group.
|
||||
#[derive(Debug, Error)]
|
||||
pub enum Error {
|
||||
/// Cannot create thread
|
||||
#[error("Error spawning rate-limiter thread {0}")]
|
||||
ThreadSpawn(#[source] io::Error),
|
||||
|
||||
/// Cannot create epoll context.
|
||||
#[error("Error creating epoll context: {0}")]
|
||||
Epoll(#[source] io::Error),
|
||||
|
||||
/// Cannot create EventFd.
|
||||
#[error("Error creating EventFd: {0}")]
|
||||
EventFd(#[source] io::Error),
|
||||
|
||||
/// Cannot create RateLimiter.
|
||||
#[error("Error creating RateLimiter: {0}")]
|
||||
RateLimiter(#[source] io::Error),
|
||||
|
||||
/// Cannot read from EventFd.
|
||||
#[error("Error reading from EventFd: {0}")]
|
||||
EventFdRead(#[source] io::Error),
|
||||
|
||||
/// Cannot write to EventFd.
|
||||
#[error("Error writing to EventFd: {0}")]
|
||||
EventFdWrite(#[source] io::Error),
|
||||
}
|
||||
|
||||
/// The RateLimiterGroupHandle is a handle to a RateLimiterGroup that may be
|
||||
/// used in exactly the same way as the RateLimiter type. When the RateLimiter
|
||||
/// within a RateLimiterGroup is unblocked, each RateLimiterGroupHandle will
|
||||
/// be notified.
|
||||
pub struct RateLimiterGroupHandle {
|
||||
eventfd: Arc<EventFd>,
|
||||
inner: Arc<RateLimiterGroupInner>,
|
||||
}
|
||||
|
||||
impl RateLimiterGroupHandle {
|
||||
fn new(inner: Arc<RateLimiterGroupInner>) -> result::Result<Self, Error> {
|
||||
let eventfd = Arc::new(EventFd::new(0).map_err(Error::EventFd)?);
|
||||
inner.handles.lock().unwrap().push(eventfd.clone());
|
||||
Ok(Self { eventfd, inner })
|
||||
}
|
||||
|
||||
/// Attempts to consume tokens and returns whether that is possible.
|
||||
///
|
||||
/// If rate limiting is disabled on provided `token_type`, this function will always succeed.
|
||||
pub fn consume(&self, tokens: u64, token_type: TokenType) -> bool {
|
||||
self.inner.rate_limiter.consume(tokens, token_type)
|
||||
}
|
||||
|
||||
/// Adds tokens of `token_type` to their respective bucket.
|
||||
///
|
||||
/// Can be used to *manually* add tokens to a bucket. Useful for reverting a
|
||||
/// `consume()` if needed.
|
||||
pub fn manual_replenish(&self, tokens: u64, token_type: TokenType) {
|
||||
self.inner.rate_limiter.manual_replenish(tokens, token_type)
|
||||
}
|
||||
|
||||
/// This function needs to be called every time there is an event on the
|
||||
/// FD provided by this object's `AsRawFd` trait implementation.
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// If the rate limiter is disabled or is not blocked, an error is returned.
|
||||
pub fn event_handler(&self) -> Result<(), Error> {
|
||||
self.eventfd.read().map_err(Error::EventFdRead).map(|_| ())
|
||||
}
|
||||
|
||||
/// Returns whether this rate limiter is blocked.
|
||||
///
|
||||
/// The limiter 'blocks' when a `consume()` operation fails because there was not enough
|
||||
/// budget for it.
|
||||
/// An event will be generated on the exported FD when the limiter 'unblocks'.
|
||||
pub fn is_blocked(&self) -> bool {
|
||||
self.inner.rate_limiter.is_blocked()
|
||||
}
|
||||
}
|
||||
|
||||
impl Clone for RateLimiterGroupHandle {
|
||||
fn clone(&self) -> Self {
|
||||
RateLimiterGroupHandle::new(self.inner.clone()).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for RateLimiterGroupHandle {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.eventfd.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for RateLimiterGroupHandle {
|
||||
fn drop(&mut self) {
|
||||
let mut handles = self.inner.handles.lock().unwrap();
|
||||
let index = handles
|
||||
.iter()
|
||||
.position(|handle| handle.as_raw_fd() == self.eventfd.as_raw_fd())
|
||||
.expect("RateLimiterGroupHandle must be subscribed to RateLimiterGroup");
|
||||
handles.remove(index);
|
||||
}
|
||||
}
|
||||
|
||||
struct RateLimiterGroupInner {
|
||||
id: String,
|
||||
rate_limiter: RateLimiter,
|
||||
handles: Mutex<Vec<Arc<EventFd>>>,
|
||||
}
|
||||
|
||||
/// A RateLimiterGroup is an extension of RateLimiter that enables rate-limiting
|
||||
/// the aggregate io consumption of multiple consumers.
|
||||
pub struct RateLimiterGroup {
|
||||
inner: Arc<RateLimiterGroupInner>,
|
||||
epoll_file: File,
|
||||
kill_evt: EventFd,
|
||||
epoll_thread: Option<thread::JoinHandle<()>>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
#[repr(u64)]
|
||||
enum EpollDispatch {
|
||||
Kill = 1,
|
||||
Unblocked = 2,
|
||||
Unknown,
|
||||
}
|
||||
|
||||
impl From<u64> for EpollDispatch {
|
||||
fn from(v: u64) -> Self {
|
||||
use EpollDispatch::*;
|
||||
match v {
|
||||
1 => Kill,
|
||||
2 => Unblocked,
|
||||
_ => Unknown,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl RateLimiterGroup {
|
||||
/// Create a new RateLimiterGroup.
|
||||
pub fn new(
|
||||
id: &str,
|
||||
bytes_total_capacity: u64,
|
||||
bytes_one_time_burst: u64,
|
||||
bytes_complete_refill_time_ms: u64,
|
||||
ops_total_capacity: u64,
|
||||
ops_one_time_burst: u64,
|
||||
ops_complete_refill_time_ms: u64,
|
||||
) -> result::Result<Self, Error> {
|
||||
let rate_limiter = RateLimiter::new(
|
||||
bytes_total_capacity,
|
||||
bytes_one_time_burst,
|
||||
bytes_complete_refill_time_ms,
|
||||
ops_total_capacity,
|
||||
ops_one_time_burst,
|
||||
ops_complete_refill_time_ms,
|
||||
)
|
||||
.map_err(Error::RateLimiter)?;
|
||||
|
||||
let epoll_fd = epoll::create(true).map_err(Error::Epoll)?;
|
||||
let kill_evt = EventFd::new(0).map_err(Error::EventFd)?;
|
||||
|
||||
epoll::ctl(
|
||||
epoll_fd,
|
||||
epoll::ControlOptions::EPOLL_CTL_ADD,
|
||||
kill_evt.as_raw_fd(),
|
||||
epoll::Event::new(epoll::Events::EPOLLIN, EpollDispatch::Kill as u64),
|
||||
)
|
||||
.map_err(Error::Epoll)?;
|
||||
|
||||
epoll::ctl(
|
||||
epoll_fd,
|
||||
epoll::ControlOptions::EPOLL_CTL_ADD,
|
||||
rate_limiter.as_raw_fd(),
|
||||
epoll::Event::new(epoll::Events::EPOLLIN, EpollDispatch::Unblocked as u64),
|
||||
)
|
||||
.map_err(Error::Epoll)?;
|
||||
|
||||
// Use 'File' to enforce closing on 'epoll_fd'
|
||||
// SAFETY: epoll_fd is valid
|
||||
let epoll_file = unsafe { File::from_raw_fd(epoll_fd) };
|
||||
|
||||
Ok(Self {
|
||||
inner: Arc::new(RateLimiterGroupInner {
|
||||
id: id.to_string(),
|
||||
rate_limiter,
|
||||
handles: Mutex::new(Vec::new()),
|
||||
}),
|
||||
epoll_file,
|
||||
kill_evt,
|
||||
epoll_thread: None,
|
||||
})
|
||||
}
|
||||
|
||||
/// Create a new RateLimiterGroupHandle.
|
||||
pub fn new_handle(&self) -> result::Result<RateLimiterGroupHandle, Error> {
|
||||
RateLimiterGroupHandle::new(self.inner.clone())
|
||||
}
|
||||
|
||||
/// Start a worker thread to broadcast an event to each RateLimiterGroupHandle
|
||||
/// when the RateLimiter becomes unblocked.
|
||||
pub fn start_thread(&mut self, exit_evt: EventFd) -> result::Result<(), Error> {
|
||||
let inner = self.inner.clone();
|
||||
let epoll_fd = self.epoll_file.as_raw_fd();
|
||||
thread::Builder::new()
|
||||
.name(format!("rate-limit-group-{}", inner.id))
|
||||
.spawn(move || {
|
||||
let res = std::panic::catch_unwind(AssertUnwindSafe(move || {
|
||||
const EPOLL_EVENTS_LEN: usize = 2;
|
||||
|
||||
let mut events =
|
||||
[epoll::Event::new(epoll::Events::empty(), 0); EPOLL_EVENTS_LEN];
|
||||
|
||||
loop {
|
||||
let num_events = match epoll::wait(epoll_fd, -1, &mut events[..]) {
|
||||
Ok(res) => res,
|
||||
Err(e) => {
|
||||
if e.kind() == io::ErrorKind::Interrupted {
|
||||
continue;
|
||||
} else {
|
||||
return Err(Error::Epoll(e));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for event in events.iter().take(num_events) {
|
||||
let dispatch_event: EpollDispatch = event.data.into();
|
||||
match dispatch_event {
|
||||
EpollDispatch::Unknown => {
|
||||
let event = event.data;
|
||||
warn!("Unknown rate-limiter loop event: {}", event);
|
||||
}
|
||||
EpollDispatch::Unblocked => {
|
||||
inner.rate_limiter.event_handler().unwrap();
|
||||
let handles = inner.handles.lock().unwrap();
|
||||
for handle in handles.iter() {
|
||||
handle.write(1).map_err(Error::EventFdWrite)?
|
||||
}
|
||||
}
|
||||
EpollDispatch::Kill => {
|
||||
info!(
|
||||
"KILL_EVENT received, stopping rate-limit-group epoll loop"
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
|
||||
match res {
|
||||
Ok(res) => {
|
||||
if let Err(e) = res {
|
||||
error!("Error running rate-limit-group worker: {:?}", e);
|
||||
exit_evt.write(1).unwrap();
|
||||
}
|
||||
}
|
||||
Err(_) => {
|
||||
error!("rate-limit-group worker panicked");
|
||||
exit_evt.write(1).unwrap();
|
||||
}
|
||||
};
|
||||
})
|
||||
.map(|thread| self.epoll_thread.insert(thread))
|
||||
.map_err(Error::ThreadSpawn)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for RateLimiterGroup {
|
||||
fn drop(&mut self) {
|
||||
self.kill_evt.write(1).unwrap();
|
||||
|
||||
if let Some(t) = self.epoll_thread.take() {
|
||||
if let Err(e) = t.join() {
|
||||
error!("Error joining thread: {:?}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) mod tests {
|
||||
use super::RateLimiterGroupHandle;
|
||||
use crate::{group::RateLimiterGroup, TokenBucket, TokenType, REFILL_TIMER_INTERVAL_MS};
|
||||
use std::{os::fd::AsRawFd, thread, time::Duration};
|
||||
use vmm_sys_util::eventfd::EventFd;
|
||||
|
||||
impl RateLimiterGroupHandle {
|
||||
pub fn bandwidth(&self) -> Option<TokenBucket> {
|
||||
let guard = self.inner.rate_limiter.inner.lock().unwrap();
|
||||
guard.bandwidth.clone()
|
||||
}
|
||||
|
||||
pub fn ops(&self) -> Option<TokenBucket> {
|
||||
let guard = self.inner.rate_limiter.inner.lock().unwrap();
|
||||
guard.ops.clone()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rate_limiter_group_new() {
|
||||
let l = RateLimiterGroup::new("test", 1000, 1001, 1002, 1003, 1004, 1005).unwrap();
|
||||
let h = l.new_handle().unwrap();
|
||||
let bw = h.bandwidth().unwrap();
|
||||
assert_eq!(bw.capacity(), 1000);
|
||||
assert_eq!(bw.one_time_burst(), 1001);
|
||||
assert_eq!(bw.refill_time_ms(), 1002);
|
||||
assert_eq!(bw.budget(), 1000);
|
||||
|
||||
let ops = h.ops().unwrap();
|
||||
assert_eq!(ops.capacity(), 1003);
|
||||
assert_eq!(ops.one_time_burst(), 1004);
|
||||
assert_eq!(ops.refill_time_ms(), 1005);
|
||||
assert_eq!(ops.budget(), 1003);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rate_limiter_group_manual_replenish() {
|
||||
// rate limiter with limit of 1000 bytes/s and 1000 ops/s
|
||||
let l = RateLimiterGroup::new("test", 1000, 0, 1000, 1000, 0, 1000).unwrap();
|
||||
let h = l.new_handle().unwrap();
|
||||
|
||||
// consume 123 bytes
|
||||
assert!(h.consume(123, TokenType::Bytes));
|
||||
h.manual_replenish(23, TokenType::Bytes);
|
||||
{
|
||||
let bytes_tb = h.bandwidth().unwrap();
|
||||
assert_eq!(bytes_tb.budget(), 900);
|
||||
}
|
||||
// consume 123 ops
|
||||
assert!(h.consume(123, TokenType::Ops));
|
||||
h.manual_replenish(23, TokenType::Ops);
|
||||
{
|
||||
let bytes_tb = h.ops().unwrap();
|
||||
assert_eq!(bytes_tb.budget(), 900);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rate_limiter_group_bandwidth() {
|
||||
// rate limiter with limit of 1000 bytes/s
|
||||
let mut l = RateLimiterGroup::new("test", 1000, 0, 1000, 0, 0, 0).unwrap();
|
||||
l.start_thread(EventFd::new(0).unwrap()).unwrap();
|
||||
|
||||
let h = l.new_handle().unwrap();
|
||||
|
||||
// limiter should not be blocked
|
||||
assert!(!h.is_blocked());
|
||||
// raw FD for this disabled should be valid
|
||||
assert!(h.as_raw_fd() > 0);
|
||||
|
||||
// ops/s limiter should be disabled so consume(whatever) should work
|
||||
assert!(h.consume(u64::max_value(), TokenType::Ops));
|
||||
|
||||
// do full 1000 bytes
|
||||
assert!(h.consume(1000, TokenType::Bytes));
|
||||
// try and fail on another 100
|
||||
assert!(!h.consume(100, TokenType::Bytes));
|
||||
// since consume failed, limiter should be blocked now
|
||||
assert!(h.is_blocked());
|
||||
// wait half the timer period
|
||||
thread::sleep(Duration::from_millis(REFILL_TIMER_INTERVAL_MS / 2));
|
||||
// limiter should still be blocked
|
||||
assert!(h.is_blocked());
|
||||
// wait the other half of the timer period
|
||||
thread::sleep(Duration::from_millis(REFILL_TIMER_INTERVAL_MS / 2));
|
||||
// the timer_fd should have an event on it by now
|
||||
assert!(h.event_handler().is_ok());
|
||||
// limiter should now be unblocked
|
||||
assert!(!h.is_blocked());
|
||||
// try and succeed on another 100 bytes this time
|
||||
assert!(h.consume(100, TokenType::Bytes));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rate_limiter_group_ops() {
|
||||
// rate limiter with limit of 1000 ops/s
|
||||
let mut l = RateLimiterGroup::new("test", 0, 0, 0, 1000, 0, 1000).unwrap();
|
||||
l.start_thread(EventFd::new(0).unwrap()).unwrap();
|
||||
|
||||
let h = l.new_handle().unwrap();
|
||||
|
||||
// limiter should not be blocked
|
||||
assert!(!h.is_blocked());
|
||||
// raw FD for this disabled should be valid
|
||||
assert!(h.as_raw_fd() > 0);
|
||||
|
||||
// bytes/s limiter should be disabled so consume(whatever) should work
|
||||
assert!(h.consume(u64::max_value(), TokenType::Bytes));
|
||||
|
||||
// do full 1000 ops
|
||||
assert!(h.consume(1000, TokenType::Ops));
|
||||
// try and fail on another 100
|
||||
assert!(!h.consume(100, TokenType::Ops));
|
||||
// since consume failed, limiter should be blocked now
|
||||
assert!(h.is_blocked());
|
||||
// wait half the timer period
|
||||
thread::sleep(Duration::from_millis(REFILL_TIMER_INTERVAL_MS / 2));
|
||||
// limiter should still be blocked
|
||||
assert!(h.is_blocked());
|
||||
// wait the other half of the timer period
|
||||
thread::sleep(Duration::from_millis(REFILL_TIMER_INTERVAL_MS / 2));
|
||||
// the timer_fd should have an event on it by now
|
||||
assert!(h.event_handler().is_ok());
|
||||
// limiter should now be unblocked
|
||||
assert!(!h.is_blocked());
|
||||
// try and succeed on another 100 ops this time
|
||||
assert!(h.consume(100, TokenType::Ops));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rate_limiter_group_full() {
|
||||
// rate limiter with limit of 1000 bytes/s and 1000 ops/s
|
||||
let mut l = RateLimiterGroup::new("test", 1000, 0, 1000, 1000, 0, 1000).unwrap();
|
||||
l.start_thread(EventFd::new(0).unwrap()).unwrap();
|
||||
|
||||
let h = l.new_handle().unwrap();
|
||||
|
||||
// limiter should not be blocked
|
||||
assert!(!h.is_blocked());
|
||||
// raw FD for this disabled should be valid
|
||||
assert!(h.as_raw_fd() > 0);
|
||||
|
||||
// do full 1000 bytes
|
||||
assert!(h.consume(1000, TokenType::Ops));
|
||||
// do full 1000 bytes
|
||||
assert!(h.consume(1000, TokenType::Bytes));
|
||||
// try and fail on another 100 ops
|
||||
assert!(!h.consume(100, TokenType::Ops));
|
||||
// try and fail on another 100 bytes
|
||||
assert!(!h.consume(100, TokenType::Bytes));
|
||||
// since consume failed, limiter should be blocked now
|
||||
assert!(h.is_blocked());
|
||||
// wait half the timer period
|
||||
thread::sleep(Duration::from_millis(REFILL_TIMER_INTERVAL_MS / 2));
|
||||
// limiter should still be blocked
|
||||
assert!(h.is_blocked());
|
||||
// wait the other half of the timer period
|
||||
thread::sleep(Duration::from_millis(REFILL_TIMER_INTERVAL_MS / 2));
|
||||
// the timer_fd should have an event on it by now
|
||||
assert!(h.event_handler().is_ok());
|
||||
// limiter should now be unblocked
|
||||
assert!(!h.is_blocked());
|
||||
// try and succeed on another 100 ops this time
|
||||
assert!(h.consume(100, TokenType::Ops));
|
||||
// try and succeed on another 100 bytes this time
|
||||
assert!(h.consume(100, TokenType::Bytes));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_rate_limiter_group_overconsumption() {
|
||||
// initialize the rate limiter
|
||||
let mut l = RateLimiterGroup::new("test", 1000, 0, 1000, 1000, 0, 1000).unwrap();
|
||||
l.start_thread(EventFd::new(0).unwrap()).unwrap();
|
||||
|
||||
let h = l.new_handle().unwrap();
|
||||
|
||||
// try to consume 2.5x the bucket size
|
||||
// we are "borrowing" 1.5x the bucket size in tokens since
|
||||
// the bucket is full
|
||||
assert!(h.consume(2500, TokenType::Bytes));
|
||||
|
||||
// check that even after a whole second passes, the rate limiter
|
||||
// is still blocked
|
||||
thread::sleep(Duration::from_millis(1000));
|
||||
assert!(h.is_blocked());
|
||||
|
||||
// after 1.5x the replenish time has passed, the rate limiter
|
||||
// is available again
|
||||
thread::sleep(Duration::from_millis(500));
|
||||
assert!(h.event_handler().is_ok());
|
||||
assert!(!h.is_blocked());
|
||||
|
||||
// reset the rate limiter
|
||||
let mut l = RateLimiterGroup::new("test", 1000, 0, 1000, 1000, 0, 1000).unwrap();
|
||||
l.start_thread(EventFd::new(0).unwrap()).unwrap();
|
||||
|
||||
let h = l.new_handle().unwrap();
|
||||
// try to consume 1.5x the bucket size
|
||||
// we are "borrowing" 1.5x the bucket size in tokens since
|
||||
// the bucket is full, should arm the timer to 0.5x replenish
|
||||
// time, which is 500 ms
|
||||
assert!(h.consume(1500, TokenType::Bytes));
|
||||
|
||||
// check that after more than the minimum refill time,
|
||||
// the rate limiter is still blocked
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
assert!(h.is_blocked());
|
||||
|
||||
// try to consume some tokens, which should fail as the timer
|
||||
// is still active
|
||||
assert!(!h.consume(100, TokenType::Bytes));
|
||||
assert!(h.is_blocked());
|
||||
|
||||
// check that after the minimum refill time, the timer was not
|
||||
// overwritten and the rate limiter is still blocked from the
|
||||
// borrowing we performed earlier
|
||||
thread::sleep(Duration::from_millis(100));
|
||||
assert!(h.is_blocked());
|
||||
assert!(!h.consume(100, TokenType::Bytes));
|
||||
|
||||
// after waiting out the full duration, rate limiter should be
|
||||
// available again
|
||||
thread::sleep(Duration::from_millis(200));
|
||||
assert!(h.event_handler().is_ok());
|
||||
assert!(!h.is_blocked());
|
||||
assert!(h.consume(100, TokenType::Bytes));
|
||||
}
|
||||
}
|
||||
@@ -53,9 +53,6 @@ use std::sync::Mutex;
|
||||
use std::time::{Duration, Instant};
|
||||
use vmm_sys_util::timerfd::TimerFd;
|
||||
|
||||
/// Module for group rate limiting.
|
||||
pub mod group;
|
||||
|
||||
#[derive(Debug)]
|
||||
/// Describes the errors that may occur while handling rate limiter events.
|
||||
pub enum Error {
|
||||
@@ -522,6 +519,7 @@ pub(crate) mod tests {
|
||||
use super::*;
|
||||
use std::fmt;
|
||||
use std::thread;
|
||||
use std::time::Duration;
|
||||
|
||||
impl TokenBucket {
|
||||
// Resets the token bucket: budget set to max capacity and last-updated set to now.
|
||||
|
||||
278
release-notes.md
278
release-notes.md
@@ -1,27 +1,12 @@
|
||||
- [v39.0](#v390)
|
||||
- [Variable Sizing of PCI Apertures for Segments](#variable-sizing-of-pci-apertures-for-segments)
|
||||
- [Direct Booting with bzImages](#direct-booting-with-bzimages)
|
||||
- [Support for NVIDIA GPUDirect P2P Support](#support-for-nvidia-gpudirect-p2p-support)
|
||||
- [Guest NMI Injection Support](#guest-nmi-injection-support)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes)
|
||||
- [Contributors](#contributors)
|
||||
- [v38.0](#v380)
|
||||
- [Group Rate Limiter on Block Devices](#group-rate-limiter-on-block-devices)
|
||||
- [CPU Pinning Support for Block Device Worker Thread](#cpu-pinning-support-for-block-device-worker-thread)
|
||||
- [Optimized Boot Time with Parallel Memory Prefault](#optimized-boot-time-with-parallel-memory-prefault)
|
||||
- [New 'debug-console' Device](#new-debug-console-device)
|
||||
- [Improved VFIO Device Support](#improved-vfio-device-support)
|
||||
- [Extended CPU Affinity Support](#extended-cpu-affinity-support)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-1)
|
||||
- [Contributors](#contributors-1)
|
||||
- [v37.1](#v371)
|
||||
- [v37.0](#v370)
|
||||
- [Long Term Support (LTS) Release](#long-term-support-lts-release)
|
||||
- [Multiple PCI segments Support for 32-bit VFIO devices](#multiple-pci-segments-support-for-32-bit-vfio-devices)
|
||||
- [Improved VFIO Device Passthrough with Multiple PCI Segments](#improved-vfio-device-passthrough-with-multiple-pci-segments)
|
||||
- [Configurable Named TAP Devices](#configurable-named-tap-devices)
|
||||
- [TTY Output from Both Serial Device and Virtio Console](#tty-output-from-both-serial-device-and-virtio-console)
|
||||
- [Faster VM Restoration from Snapshots](#faster-vm-restoration-from-snapshots)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-2)
|
||||
- [Contributors](#contributors-2)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes)
|
||||
- [Contributors](#contributors)
|
||||
- [v36.0](#v360)
|
||||
- [Command Line Changes](#command-line-changes)
|
||||
- [Enabled Features Reported via API Endpoint and CLI](#enabled-features-reported-via-api-endpoint-and-cli)
|
||||
@@ -30,31 +15,31 @@
|
||||
- [Unix Socket Backend for Serial Port](#unix-socket-backend-for-serial-port)
|
||||
- [AIO Backend for Block Devices](#aio-backend-for-block-devices)
|
||||
- [Documentation Improvements](#documentation-improvements)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-3)
|
||||
- [Contributors](#contributors-3)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-1)
|
||||
- [Contributors](#contributors-1)
|
||||
- [v35.0](#v350)
|
||||
- [`virtio-vsock` Support for Linux Guest Kernel v6.3+](#virtio-vsock-support-for-linux-guest-kernel-v63)
|
||||
- [User Specified Serial Number for `virtio-block`](#user-specified-serial-number-for-virtio-block)
|
||||
- [vCPU TSC Frequency Included in Migration State](#vcpu-tsc-frequency-included-in-migration-state)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-4)
|
||||
- [Contributors](#contributors-4)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-2)
|
||||
- [Contributors](#contributors-2)
|
||||
- [v34.0](#v340)
|
||||
- [Paravirtualised Panic Device Support](#paravirtualised-panic-device-support)
|
||||
- [Improvements to VM Core Dump](#improvements-to-vm-core-dump)
|
||||
- [QCOW2 Support for Backing Files](#qcow2-support-for-backing-files)
|
||||
- [Minimum Host Kernel Bump](#minimum-host-kernel-bump)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-5)
|
||||
- [Contributors](#contributors-5)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-3)
|
||||
- [Contributors](#contributors-3)
|
||||
- [v33.0](#v330)
|
||||
- [D-Bus based API](#d-bus-based-api)
|
||||
- [Expose Host CPU Cache Details for AArch64](#expose-host-cpu-cache-details-for-aarch64)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-6)
|
||||
- [Contributors](#contributors-6)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-4)
|
||||
- [Contributors](#contributors-4)
|
||||
- [v32.0](#v320)
|
||||
- [Increased PCI Segment Limit](#increased-pci-segment-limit)
|
||||
- [API Changes](#api-changes)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-7)
|
||||
- [Contributors](#contributors-7)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-5)
|
||||
- [Contributors](#contributors-5)
|
||||
- [v31.1](#v311)
|
||||
- [v31.0](#v310)
|
||||
- [Update to Latest `acpi_tables`](#update-to-latest-acpi_tables)
|
||||
@@ -62,15 +47,15 @@
|
||||
- [Improvements on Console `SIGWINCH` Handler](#improvements-on-console-sigwinch-handler)
|
||||
- [Remove Directory Support from `MemoryZoneConfig::file`](#remove-directory-support-from-memoryzoneconfigfile)
|
||||
- [Documentation Improvements](#documentation-improvements-1)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-8)
|
||||
- [Contributors](#contributors-8)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-6)
|
||||
- [Contributors](#contributors-6)
|
||||
- [v30.0](#v300)
|
||||
- [Command Line Changes for Reduced Binary Size](#command-line-changes-for-reduced-binary-size)
|
||||
- [Basic vfio-user Server Support](#basic-vfio-user-server-support)
|
||||
- [Heap Profiling Support](#heap-profiling-support)
|
||||
- [Documentation Improvements](#documentation-improvements-2)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-9)
|
||||
- [Contributors](#contributors-9)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-7)
|
||||
- [Contributors](#contributors-7)
|
||||
- [v28.2](#v282)
|
||||
- [v29.0](#v290)
|
||||
- [Release Binary Supports Both MSHV and KVM](#release-binary-supports-both-mshv-and-kvm)
|
||||
@@ -80,10 +65,10 @@
|
||||
- [`AArch64` Documentation Integration](#aarch64-documentation-integration)
|
||||
- [`virtio-block` Counters Enhancement](#virtio-block-counters-enhancement)
|
||||
- [TCP Offload Control](#tcp-offload-control)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-10)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-8)
|
||||
- [Removals](#removals)
|
||||
- [Deprecations](#deprecations)
|
||||
- [Contributors](#contributors-10)
|
||||
- [Contributors](#contributors-8)
|
||||
- [v28.1](#v281)
|
||||
- [v28.0](#v280)
|
||||
- [Community Engagement (Reminder)](#community-engagement-reminder)
|
||||
@@ -91,9 +76,9 @@
|
||||
- [Virtualised TPM Support](#virtualised-tpm-support)
|
||||
- [Transparent Huge Page Support](#transparent-huge-page-support)
|
||||
- [README Quick Start Improved](#readme-quick-start-improved)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-11)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-9)
|
||||
- [Removals](#removals-1)
|
||||
- [Contributors](#contributors-11)
|
||||
- [Contributors](#contributors-9)
|
||||
- [v27.0](#v270)
|
||||
- [Community Engagement](#community-engagement)
|
||||
- [Prebuilt Packages](#prebuilt-packages)
|
||||
@@ -102,41 +87,41 @@
|
||||
- [Simplified Build Feature Flags](#simplified-build-feature-flags)
|
||||
- [Asynchronous Kernel Loading](#asynchronous-kernel-loading)
|
||||
- [GDB Support for AArch64](#gdb-support-for-aarch64)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-12)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-10)
|
||||
- [Deprecations](#deprecations-1)
|
||||
- [Contributors](#contributors-12)
|
||||
- [Contributors](#contributors-10)
|
||||
- [v26.0](#v260)
|
||||
- [SMBIOS Improvements via `--platform`](#smbios-improvements-via---platform)
|
||||
- [Unified Binary MSHV and KVM Support](#unified-binary-mshv-and-kvm-support)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-13)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-11)
|
||||
- [Deprecations](#deprecations-2)
|
||||
- [Removals](#removals-2)
|
||||
- [Contributors](#contributors-13)
|
||||
- [Contributors](#contributors-11)
|
||||
- [v25.0](#v250)
|
||||
- [`ch-remote` Improvements](#ch-remote-improvements-1)
|
||||
- [VM "Coredump" Support](#vm-coredump-support)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-14)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-12)
|
||||
- [Removals](#removals-3)
|
||||
- [Contributors](#contributors-14)
|
||||
- [Contributors](#contributors-12)
|
||||
- [v24.0](#v240)
|
||||
- [Bypass Mode for `virtio-iommu`](#bypass-mode-for-virtio-iommu)
|
||||
- [Ensure Identifiers Uniqueness](#ensure-identifiers-uniqueness)
|
||||
- [Sparse Mmap support](#sparse-mmap-support)
|
||||
- [Expose Platform Serial Number](#expose-platform-serial-number)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-15)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-13)
|
||||
- [Notable Improvements](#notable-improvements)
|
||||
- [Deprecations](#deprecations-3)
|
||||
- [New on the Website](#new-on-the-website)
|
||||
- [Contributors](#contributors-15)
|
||||
- [Contributors](#contributors-13)
|
||||
- [v23.1](#v231)
|
||||
- [v23.0](#v230)
|
||||
- [vDPA Support](#vdpa-support)
|
||||
- [Updated OS Support list](#updated-os-support-list)
|
||||
- [`AArch64` Memory Map Improvements](#aarch64-memory-map-improvements)
|
||||
- [`AMX` Support](#amx-support)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-16)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-14)
|
||||
- [Deprecations](#deprecations-4)
|
||||
- [Contributors](#contributors-16)
|
||||
- [Contributors](#contributors-14)
|
||||
- [v22.1](#v221)
|
||||
- [v22.0](#v220)
|
||||
- [GDB Debug Stub Support](#gdb-debug-stub-support)
|
||||
@@ -147,13 +132,13 @@
|
||||
- [PMU Support for AArch64](#pmu-support-for-aarch64)
|
||||
- [Documentation Under CC-BY-4.0 License](#documentation-under-cc-by-40-license)
|
||||
- [Deprecation of "Classic" `virtiofsd`](#deprecation-of-classic-virtiofsd)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-17)
|
||||
- [Contributors](#contributors-17)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-15)
|
||||
- [Contributors](#contributors-15)
|
||||
- [v21.0](#v210)
|
||||
- [Efficient Local Live Migration (for Live Upgrade)](#efficient-local-live-migration-for-live-upgrade)
|
||||
- [Recommended Kernel is Now 5.15](#recommended-kernel-is-now-515)
|
||||
- [Notable Bug fixes](#notable-bug-fixes-18)
|
||||
- [Contributors](#contributors-18)
|
||||
- [Notable Bug fixes](#notable-bug-fixes-16)
|
||||
- [Contributors](#contributors-16)
|
||||
- [v20.2](#v202)
|
||||
- [v20.1](#v201)
|
||||
- [v20.0](#v200)
|
||||
@@ -162,8 +147,8 @@
|
||||
- [Improved VFIO support](#improved-vfio-support)
|
||||
- [Safer code](#safer-code)
|
||||
- [Extended documentation](#extended-documentation)
|
||||
- [Notable bug fixes](#notable-bug-fixes-19)
|
||||
- [Contributors](#contributors-19)
|
||||
- [Notable bug fixes](#notable-bug-fixes-17)
|
||||
- [Contributors](#contributors-17)
|
||||
- [v19.0](#v190)
|
||||
- [Improved PTY handling for serial and `virtio-console`](#improved-pty-handling-for-serial-and-virtio-console)
|
||||
- [PCI boot time optimisations](#pci-boot-time-optimisations)
|
||||
@@ -171,8 +156,8 @@
|
||||
- [Live migration enhancements](#live-migration-enhancements)
|
||||
- [`virtio-mem` support with `vfio-user`](#virtio-mem-support-with-vfio-user)
|
||||
- [AArch64 for `virtio-iommu`](#aarch64-for-virtio-iommu)
|
||||
- [Notable bug fixes](#notable-bug-fixes-20)
|
||||
- [Contributors](#contributors-20)
|
||||
- [Notable bug fixes](#notable-bug-fixes-18)
|
||||
- [Contributors](#contributors-18)
|
||||
- [v18.0](#v180)
|
||||
- [Experimental User Device (`vfio-user`) support](#experimental-user-device-vfio-user-support)
|
||||
- [Migration support for `vhost-user` devices](#migration-support-for-vhost-user-devices)
|
||||
@@ -182,23 +167,23 @@
|
||||
- [Live migration on MSHV hypervisor](#live-migration-on-mshv-hypervisor)
|
||||
- [AArch64 CPU topology support](#aarch64-cpu-topology-support)
|
||||
- [Power button support on AArch64](#power-button-support-on-aarch64)
|
||||
- [Notable bug fixes](#notable-bug-fixes-21)
|
||||
- [Contributors](#contributors-21)
|
||||
- [Notable bug fixes](#notable-bug-fixes-19)
|
||||
- [Contributors](#contributors-19)
|
||||
- [v17.0](#v170)
|
||||
- [ARM64 NUMA support using ACPI](#arm64-numa-support-using-acpi)
|
||||
- [`Seccomp` support for MSHV backend](#seccomp-support-for-mshv-backend)
|
||||
- [Hotplug of `macvtap` devices](#hotplug-of-macvtap-devices)
|
||||
- [Improved SGX support](#improved-sgx-support)
|
||||
- [Inflight tracking for `vhost-user` devices](#inflight-tracking-for-vhost-user-devices)
|
||||
- [Notable bug fixes](#notable-bug-fixes-22)
|
||||
- [Contributors](#contributors-22)
|
||||
- [Notable bug fixes](#notable-bug-fixes-20)
|
||||
- [Contributors](#contributors-20)
|
||||
- [v16.0](#v160)
|
||||
- [Improved live migration support](#improved-live-migration-support)
|
||||
- [Improved `vhost-user` support](#improved-vhost-user-support)
|
||||
- [ARM64 ACPI and UEFI support](#arm64-acpi-and-uefi-support)
|
||||
- [Notable bug fixes](#notable-bug-fixes-23)
|
||||
- [Notable bug fixes](#notable-bug-fixes-21)
|
||||
- [Removed functionality](#removed-functionality)
|
||||
- [Contributors](#contributors-23)
|
||||
- [Contributors](#contributors-21)
|
||||
- [v15.0](#v150)
|
||||
- [Version numbering and stability guarantees](#version-numbering-and-stability-guarantees)
|
||||
- [Network device rate limiting](#network-device-rate-limiting)
|
||||
@@ -206,7 +191,7 @@
|
||||
- [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter)
|
||||
- [Bug fixes](#bug-fixes)
|
||||
- [Deprecations](#deprecations-5)
|
||||
- [Contributors](#contributors-24)
|
||||
- [Contributors](#contributors-22)
|
||||
- [v0.14.1](#v0141)
|
||||
- [v0.14.0](#v0140)
|
||||
- [Structured event monitoring](#structured-event-monitoring)
|
||||
@@ -216,7 +201,7 @@
|
||||
- [PTY control for serial and `virtio-console`](#pty-control-for-serial-and-virtio-console)
|
||||
- [Block device rate limiting](#block-device-rate-limiting)
|
||||
- [Deprecations](#deprecations-6)
|
||||
- [Contributors](#contributors-25)
|
||||
- [Contributors](#contributors-23)
|
||||
- [v0.13.0](#v0130)
|
||||
- [Wider VFIO device support](#wider-vfio-device-support)
|
||||
- [Improved huge page support](#improved-huge-page-support)
|
||||
@@ -224,13 +209,13 @@
|
||||
- [VHD disk image support](#vhd-disk-image-support)
|
||||
- [Improved Virtio device threading](#improved-virtio-device-threading)
|
||||
- [Clean shutdown support via synthetic power button](#clean-shutdown-support-via-synthetic-power-button)
|
||||
- [Contributors](#contributors-26)
|
||||
- [Contributors](#contributors-24)
|
||||
- [v0.12.0](#v0120)
|
||||
- [ARM64 enhancements](#arm64-enhancements)
|
||||
- [Removal of `vhost-user-net` and `vhost-user-block` self spawning](#removal-of-vhost-user-net-and-vhost-user-block-self-spawning)
|
||||
- [Migration of `vhost-user-fs` backend](#migration-of-vhost-user-fs-backend)
|
||||
- [Enhanced "info" API](#enhanced-info-api)
|
||||
- [Contributors](#contributors-27)
|
||||
- [Contributors](#contributors-25)
|
||||
- [v0.11.0](#v0110)
|
||||
- [`io_uring` support by default for `virtio-block`](#io_uring-support-by-default-for-virtio-block)
|
||||
- [Windows Guest Support](#windows-guest-support)
|
||||
@@ -242,15 +227,15 @@
|
||||
- [Default Log Level Changed](#default-log-level-changed)
|
||||
- [New `--balloon` Parameter Added](#new---balloon-parameter-added)
|
||||
- [Experimental `virtio-watchdog` Support](#experimental-virtio-watchdog-support)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-24)
|
||||
- [Contributors](#contributors-28)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-22)
|
||||
- [Contributors](#contributors-26)
|
||||
- [v0.10.0](#v0100)
|
||||
- [`virtio-block` Support for Multiple Descriptors](#virtio-block-support-for-multiple-descriptors)
|
||||
- [Memory Zones](#memory-zones)
|
||||
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements)
|
||||
- [Preliminary KVM HyperV Emulation Control](#preliminary-kvm-hyperv-emulation-control)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-25)
|
||||
- [Contributors](#contributors-29)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-23)
|
||||
- [Contributors](#contributors-27)
|
||||
- [v0.9.0](#v090)
|
||||
- [`io_uring` Based Block Device Support](#io_uring-based-block-device-support)
|
||||
- [Block and Network Device Statistics](#block-and-network-device-statistics)
|
||||
@@ -263,17 +248,17 @@
|
||||
- [Enhancements to ARM64 Support](#enhancements-to-arm64-support)
|
||||
- [Intel SGX Support](#intel-sgx-support)
|
||||
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements-1)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-26)
|
||||
- [Contributors](#contributors-30)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-24)
|
||||
- [Contributors](#contributors-28)
|
||||
- [v0.8.0](#v080)
|
||||
- [Experimental Snapshot and Restore Support](#experimental-snapshot-and-restore-support)
|
||||
- [Experimental ARM64 Support](#experimental-arm64-support)
|
||||
- [Support for Using 5-level Paging in Guests](#support-for-using-5-level-paging-in-guests)
|
||||
- [Virtio Device Interrupt Suppression for Network Devices](#virtio-device-interrupt-suppression-for-network-devices)
|
||||
- [`vhost_user_fs` Improvements](#vhost_user_fs-improvements)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-27)
|
||||
- [Notable Bug Fixes](#notable-bug-fixes-25)
|
||||
- [Command Line and API Changes](#command-line-and-api-changes)
|
||||
- [Contributors](#contributors-31)
|
||||
- [Contributors](#contributors-29)
|
||||
- [v0.7.0](#v070)
|
||||
- [Block, Network, Persistent Memory (PMEM), VirtioFS and Vsock hotplug](#block-network-persistent-memory-pmem-virtiofs-and-vsock-hotplug)
|
||||
- [Alternative `libc` Support](#alternative-libc-support)
|
||||
@@ -283,14 +268,14 @@
|
||||
- [`Seccomp` Sandboxing](#seccomp-sandboxing)
|
||||
- [Updated Distribution Support](#updated-distribution-support)
|
||||
- [Command Line and API Changes](#command-line-and-api-changes-1)
|
||||
- [Contributors](#contributors-32)
|
||||
- [Contributors](#contributors-30)
|
||||
- [v0.6.0](#v060)
|
||||
- [Directly Assigned Devices Hotplug](#directly-assigned-devices-hotplug)
|
||||
- [Shared Filesystem Improvements](#shared-filesystem-improvements)
|
||||
- [Block and Networking IO Self Offloading](#block-and-networking-io-self-offloading)
|
||||
- [Command Line Interface](#command-line-interface)
|
||||
- [PVH Boot](#pvh-boot)
|
||||
- [Contributors](#contributors-33)
|
||||
- [Contributors](#contributors-31)
|
||||
- [v0.5.1](#v051)
|
||||
- [v0.5.0](#v050)
|
||||
- [Virtual Machine Dynamic Resizing](#virtual-machine-dynamic-resizing)
|
||||
@@ -298,7 +283,7 @@
|
||||
- [New Interrupt Management Framework](#new-interrupt-management-framework)
|
||||
- [Development Tools](#development-tools)
|
||||
- [Kata Containers Integration](#kata-containers-integration)
|
||||
- [Contributors](#contributors-34)
|
||||
- [Contributors](#contributors-32)
|
||||
- [v0.4.0](#v040)
|
||||
- [Dynamic virtual CPUs addition](#dynamic-virtual-cpus-addition)
|
||||
- [Programmatic firmware tables generation](#programmatic-firmware-tables-generation)
|
||||
@@ -307,7 +292,7 @@
|
||||
- [Userspace IOAPIC by default](#userspace-ioapic-by-default)
|
||||
- [PCI BAR reprogramming](#pci-bar-reprogramming)
|
||||
- [New `cloud-hypervisor` organization](#new-cloud-hypervisor-organization)
|
||||
- [Contributors](#contributors-35)
|
||||
- [Contributors](#contributors-33)
|
||||
- [v0.3.0](#v030)
|
||||
- [Block device offloading](#block-device-offloading)
|
||||
- [Network device backend](#network-device-backend)
|
||||
@@ -334,147 +319,18 @@
|
||||
- [Unit testing](#unit-testing)
|
||||
- [Integration tests parallelization](#integration-tests-parallelization)
|
||||
|
||||
# v39.0
|
||||
# v37.1
|
||||
|
||||
This release has been tracked in our [roadmap
|
||||
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
|
||||
v39.0. The following user visible changes have been made:
|
||||
|
||||
### Variable Sizing of PCI Apertures for Segments
|
||||
|
||||
It is now possible to use `--pci-segment` to adjust the aperture size that
|
||||
devices 32-bit and 64-bit PCI device BARs will be allocated from. Previously
|
||||
the address space was equally distributed across all the segments which may
|
||||
leave insufficient space for devices that require a large 32-bit space. With
|
||||
this change the weighting per segment can be adjusted. (#6387)
|
||||
|
||||
### Direct Booting with bzImages
|
||||
|
||||
Support for directly booting Linux from bzImages has been added.(#6200)
|
||||
|
||||
### Support for NVIDIA GPUDirect P2P Support
|
||||
|
||||
The `x_nv_gpudirect_clique` option was added to `--device` to allow the
|
||||
configuration of device P2P support with NVIDIA GPUs. (#6235)
|
||||
|
||||
### Guest NMI Injection Support
|
||||
|
||||
A new API endpoint and `ch-remote` option added for injecting an NMI into the
|
||||
guest. (#6047)
|
||||
|
||||
### Notable Bug Fixes
|
||||
|
||||
* Workaround for kernel bug affecting guest IRQ masking on AMD (#6353)
|
||||
* Correctly cleanup `sigwinch_listener` process (#6208)
|
||||
* Graceful shutdown of HTTP API thread (#6248, #6247)
|
||||
* Fix `queue_affinity` option in OpenAPI metadata (#6268)
|
||||
* Fix documentation to indicate only stream mode is supported by `virtio-vsock`
|
||||
(#6306)
|
||||
* Fix `virtio-fs` tag validation (#6358, #6359)
|
||||
* Add missing `pvpanic` device to OpenAPI metadata (#6372)
|
||||
* Fixes for nested virtualization with VFIO devices (#6110, #6298, #6297,
|
||||
#6319)
|
||||
* Fix for backing file for `virtio-mem` regions with snapshot/restore (#6337,
|
||||
#6338)
|
||||
* Explicitly mark FDs used for network devices as invalid across
|
||||
snapshot/restore (#6332, #6286)
|
||||
* Improve `event-monitor` events around reboot (#6277, #6274)
|
||||
* Fix potential deadlock around paused devices during live migration (#6293)
|
||||
* Fix panic when running `ch-remote` with no subcommand (#6230)
|
||||
* Fix hotplug of `virtio` devices after snapshot/restore and live migration
|
||||
(#6326, #6265)
|
||||
|
||||
### Contributors
|
||||
|
||||
Many thanks to everyone who has contributed to our release:
|
||||
|
||||
* Alexandru Matei <alexandru.matei@uipath.com>
|
||||
* Andrew Carp <acarp@crusoeenergy.com>
|
||||
* Bo Chen <chen.bo@intel.com>
|
||||
* Bouke van der Bijl <i@bou.ke>
|
||||
* Chris Webb <chris@arachsys.com>
|
||||
* Jinank Jain <jinankjain@microsoft.com>
|
||||
* Lucas Jacques <contact@lucasjacques.com>
|
||||
* Muminul Islam <muislam@microsoft.com>
|
||||
* Nuno Das Neves <nudasnev@microsoft.com>
|
||||
* Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
|
||||
* Rob Bradford <rbradford@rivosinc.com>
|
||||
* Ruslan Mstoi <ruslan.mstoi@intel.com>
|
||||
* Stefan Nuernberger <stefan.nuernberger@cyberus-technology.de>
|
||||
* Thomas Barrett <tbarrett@crusoeenergy.com>
|
||||
* Wei Liu <liuwe@microsoft.com>
|
||||
* Yi Wang <foxywang@tencent.com>
|
||||
|
||||
# v38.0
|
||||
|
||||
This release has been tracked in our [roadmap
|
||||
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
|
||||
v38.0. The following user visible changes have been made:
|
||||
|
||||
### Group Rate Limiter on Block Devices
|
||||
|
||||
Users now can throttle a group of block devices with the new
|
||||
`--rate-limiter-group` option. Details can be found from the [I/O
|
||||
Throttling documentation](docs/io_throttling.md)
|
||||
|
||||
### CPU Pinning Support for Block Device Worker Thread
|
||||
|
||||
Users now have the option to pin virt-queue threads for block devices
|
||||
to specific host cpus.
|
||||
|
||||
### Optimized Boot Time with Parallel Memory Prefault
|
||||
|
||||
The boot time with `prefault` option enabled is optimized via parallel
|
||||
memory prefault.
|
||||
|
||||
### New 'debug-console' Device
|
||||
|
||||
A 'debug-console' device is added to provide a user-configurable debug
|
||||
port for logging guest information. Details can be found from the [Debug
|
||||
IO Ports documentation](docs/debug-port.md).
|
||||
|
||||
### Improved VFIO Device Support
|
||||
|
||||
All non-emulated MMIO regions of VFIO devices are now mapped to the VFIO
|
||||
container, allowing PCIe P2P between all VFIO devices on the same
|
||||
VM. This is required for a wide variety of multi-GPU workloads involving
|
||||
GPUDirect P2P (DMA between two GPUs), GPUDirect RDMA (DMA between a GPU
|
||||
and an IB device).
|
||||
|
||||
### Extended CPU Affinity Support
|
||||
|
||||
Users now can set the vcpu affinity to a host CPU with index larger
|
||||
than 255.
|
||||
|
||||
### Notable Bug Fixes
|
||||
This is a bug fix release. The following issues have been addressed:
|
||||
|
||||
* Fix several security advisories from dependencies (#6134, #6141)
|
||||
* Enable HTT flag to avoid crashing cpu topology enumeration software
|
||||
such as hwloc in the guest (#6146)
|
||||
* Fix several security advisories from dependencies (#6134, #6141)
|
||||
* Handle non-power-of-two CPU topology properly (#6062)
|
||||
* Various bug fixes around `virtio-vsock`(#6080, #6091, #6095)
|
||||
* Enable nested virtualization on AMD if supported (#6106)
|
||||
* Handle non-power-of-two CPU topology properly (#6062)
|
||||
* Various bug fixes around virtio-vsock(#6080, #6091, #6095)
|
||||
* Align VFIO devices PCI BARs naturally (#6196)
|
||||
|
||||
### Contributors
|
||||
|
||||
Many thanks to everyone who has contributed to our release:
|
||||
* Alyssa Ross <hi@alyssa.is>
|
||||
* Bo Chen <chen.bo@intel.com>
|
||||
* Daniel Farina <daniel@ubicloud.com>
|
||||
* Jinank Jain <jinankjain@microsoft.com>
|
||||
* Muminul Islam <muislam@microsoft.com>
|
||||
* Peteris Rudzusiks <rye@stripe.com>
|
||||
* Philipp Schuster <philipp.schuster@cyberus-technology.de>
|
||||
* Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
|
||||
* Rob Bradford <rbradford@rivosinc.com>
|
||||
* Ruslan Mstoi <ruslan.mstoi@intel.com>
|
||||
* Sean Banko <sbanko@crusoeenergy.com>
|
||||
* Thomas Barrett <tbarrett@crusoeenergy.com>
|
||||
* Wei Liu <liuwe@microsoft.com>
|
||||
* Yi Wang <foxywang@tencent.com>
|
||||
* acarp <acarp@crusoeenergy.com>
|
||||
|
||||
# v37.0
|
||||
|
||||
This release has been tracked in our [roadmap
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
# Copyright © 2024 Intel Corporation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
#
|
||||
# When changing this file don't forget to update the tag name in the
|
||||
@@ -8,7 +6,7 @@
|
||||
FROM ubuntu:22.04 as dev
|
||||
|
||||
ARG TARGETARCH
|
||||
ARG RUST_TOOLCHAIN="1.74.1"
|
||||
ARG RUST_TOOLCHAIN="1.70.0"
|
||||
ARG CLH_SRC_DIR="/cloud-hypervisor"
|
||||
ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build"
|
||||
ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user