Compare commits

..

13 Commits

Author SHA1 Message Date
Bo Chen
d725400158 build: Release v36.1 (bug fix release)
Signed-off-by: Bo Chen <chen.bo@intel.com>
2024-01-10 11:36:39 -08:00
Bo Chen
7026a08569 tests: Temporarily disable vhost_user_blk tests on aarch64
See: #5934

Signed-off-by: Bo Chen <chen.bo@intel.com>
(cherry picked from commit 62db13ba0e)
2024-01-10 09:09:15 -08:00
Michael Zhao
b6945b649a scripts: Workaround random wget failures on AArch64
Random failures of downloading `cloud-hypervisor-static-aarch64` with
`wget` were seen. The commit applies a workaround to retry the download
for a few times.

Signed-off-by: Michael Zhao <michael.zhao@arm.com>
(cherry picked from commit f0c5592ba1)
2024-01-10 09:09:15 -08:00
Ravi kumar Veeramally
4c0052f355 tests: Migrate docker container from ubuntu 20.04 to 22.04
The following tests have been temporarily disabled:

1. Live upgrade/migration test with ovs-dpdk (#5532);
2. Disk hotplug tests on windows guests (#6037);

This patch has been tested with PR #6048.

Signed-off-by: Ravi kumar Veeramally <ravikumar.veeramally@intel.com>
Signed-off-by: Michael Zhao <michael.zhao@arm.com>
Tested-by: Bo Chen <chen.bo@intel.com>
(cherry picked from commit 24f384d239)
2024-01-10 09:09:15 -08:00
Bo Chen
758930bc65 virtio-devices: Fix beta clippy issue
error: use of a fallible conversion when an infallible one could be used
Error:    --> virtio-devices/src/vhost_user/vu_common_ctrl.rs:206:51
    |
206 |             let actual_size: usize = queue.size().try_into().unwrap();
    |                                                   ^^^^^^^^^^^^^^^^^^^ help: use: `into()`
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#unnecessary_fallible_conversions
    = note: `-D clippy::unnecessary-fallible-conversions` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::unnecessary_fallible_conversions)]`

error: could not compile `virtio-devices` (lib) due to previous error
Error: warning: build failed, waiting for other jobs to finish...
error: could not compile `virtio-devices` (lib test) due to previous error
Error: The process '/home/runner/.cargo/bin/cargo' failed with exit code 101

Signed-off-by: Bo Chen <chen.bo@intel.com>
(cherry picked from commit d4a163dd39)
2024-01-10 09:09:15 -08:00
Yi Wang
7b46d06171 build: fix clippy ptr arg issue
CI reports errors:

error: writing `&Vec` instead of `&[_]` involves a new object where a slice will do
    --> arch/src/x86_64/mod.rs:1351:19
     |
1351 |     epc_sections: &Vec<SgxEpcSection>,
     |                   ^^^^^^^^^^^^^^^^^^^ help: change this to: `&[SgxEpcSection]`
     |
     = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#ptr_arg
     = note: `-D clippy::ptr-arg` implied by `-D warnings`
     = help: to override `-D warnings` add `#[allow(clippy::ptr_arg)]`

Signed-off-by: Yi Wang <foxywang@tencent.com>
(cherry picked from commit 3d6594a594)
2024-01-10 09:09:15 -08:00
Yi Wang
e16b06f894 build: fix clippy Path::join issue
CI reports clippy errors:

error: argument to `Path::join` starts with a path separator
    --> tests/integration.rs:4076:58
     |
4076 |         let serial_socket = guest.tmp_dir.as_path().join("/tmp/serial.socket");
     |                                                          ^^^^^^^^^^^^^^^^^^^^
     |
     = note: joining a path starting with separator will replace the path instead
     = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#join_absolute_paths

Signed-off-by: Yi Wang <foxywang@tencent.com>
(cherry picked from commit ee2f0c3cb4)
2024-01-10 09:09:15 -08:00
Yi Wang
4e001e2ad5 build: fix clippy complex closures issue
CI reports clippy errors:

error: in a `match` scrutinee, avoid complex blocks or closures with blocks; instead, move the block or closure higher and bind it with a `let`
   --> test_infra/src/lib.rs:93:51
    |
93  |           match (|| -> Result<(), WaitForBootError> {
    |  ___________________________________________________^
94  | |             let listener =
95  | |                 TcpListener::bind(listen_addr.as_str()).map_err(WaitForBootError::Listen)?;
96  | |             listener
...   |
145 | |             }
146 | |         })() {
    | |_________^
    |
    = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#blocks_in_conditions
    = note: `-D clippy::blocks-in-conditions` implied by `-D warnings`
    = help: to override `-D warnings` add `#[allow(clippy::blocks_in_conditions)]`

Signed-off-by: Yi Wang <foxywang@tencent.com>
(cherry picked from commit 9c2d650cb8)
2024-01-10 09:09:15 -08:00
Bo Chen
e309ed0a38 test: Enable live-upgrade based on release v36.0
Signed-off-by: Bo Chen <chen.bo@intel.com>
2024-01-10 09:09:15 -08:00
Bo Chen
948e7ca61a vmm: tdx: Error out early for TD migration
Signed-off-by: Bo Chen <chen.bo@intel.com>
(cherry picked from commit e64b66054e)
2024-01-10 09:09:15 -08:00
Rui Chang
920564b281 vmm: add add-user-device support in cloud-hypervisor.yaml
The change is missed when add "add-user-device" support in
53b2e19934, use this commit to fix it.

Signed-off-by: Rui Chang <rui.chang@arm.com>
(cherry picked from commit 2b457584e0)
2024-01-10 09:09:15 -08:00
Thomas Barrett
014c19e189 devices: fix pv_panic alignment
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
(cherry picked from commit 5f3ff3c44a)
2024-01-10 09:09:15 -08:00
Thomas Barrett
dbf4891eb2 block: fix aio backend behavior when writeback enabled
Signed-off-by: Thomas Barrett <tbarrett@crusoeenergy.com>
(cherry picked from commit d9ed281719)
2024-01-10 09:09:15 -08:00
117 changed files with 1849 additions and 3521 deletions

View File

@@ -4,13 +4,12 @@ on:
paths: paths:
- '**/Cargo.toml' - '**/Cargo.toml'
- '**/Cargo.lock' - '**/Cargo.lock'
jobs: jobs:
security_audit: security_audit:
name: Audit name: Audit
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v1
- uses: actions-rs/audit-check@v1 - uses: actions-rs/audit-check@v1
with: with:
token: ${{ secrets.GITHUB_TOKEN }} token: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -1,11 +1,9 @@
name: Cloud Hypervisor Build name: Cloud Hypervisor Build
on: [pull_request, merge_group] on: [pull_request, create]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs: jobs:
build: build:
if: github.event_name == 'pull_request'
name: Build name: Build
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
@@ -15,13 +13,13 @@ jobs:
- stable - stable
- beta - beta
- nightly - nightly
- "1.70" - "1.66"
target: target:
- x86_64-unknown-linux-gnu - x86_64-unknown-linux-gnu
- x86_64-unknown-linux-musl - x86_64-unknown-linux-musl
steps: steps:
- name: Code checkout - name: Code checkout
uses: actions/checkout@v4 uses: actions/checkout@v2
with: with:
fetch-depth: 0 fetch-depth: 0
@@ -56,9 +54,6 @@ jobs:
- name: Build (sev_snp) - name: Build (sev_snp)
run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "sev_snp" -- -D warnings -D clippy::undocumented_unsafe_blocks run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "sev_snp" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Build (igvm)
run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "igvm" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Build (mshv + kvm) - name: Build (mshv + kvm)
run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "mshv,kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks run: cargo rustc --locked --bin cloud-hypervisor --no-default-features --features "mshv,kvm" -- -D warnings -D clippy::undocumented_unsafe_blocks

View File

@@ -1,18 +1,16 @@
name: DCO name: DCO
on: [pull_request, merge_group] on:
pull_request:
jobs: jobs:
check: check:
name: DCO Check ("Signed-Off-By")
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v2
- name: Set up Python 3.x - name: Set up Python 3.x
uses: actions/setup-python@v1 uses: actions/setup-python@v1
with: with:
python-version: '3.x' python-version: '3.x'
- name: Check DCO - name: Check DCO
if: ${{ github.event_name == 'pull_request' }}
env: env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: | run: |

View File

@@ -1,13 +1,11 @@
name: Cloud Hypervisor's Docker image update name: Cloud Hypervisor's Docker image update
on: on:
push: push:
branches: main branches: main
paths: resources/Dockerfile paths: resources/Dockerfile
pull_request: pull_request:
paths: resources/Dockerfile paths: resources/Dockerfile
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
env: env:
REGISTRY: ghcr.io REGISTRY: ghcr.io
@@ -18,7 +16,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Code checkout - name: Code checkout
uses: actions/checkout@v4 uses: actions/checkout@v2
- name: Set up QEMU - name: Set up QEMU
uses: docker/setup-qemu-action@v1 uses: docker/setup-qemu-action@v1

View File

@@ -1,11 +1,9 @@
name: Cloud Hypervisor Cargo Fuzz Build name: Cloud Hypervisor Cargo Fuzz Build
on: [pull_request, merge_group] on: [pull_request, create]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs: jobs:
build: build:
if: github.event_name == 'pull_request'
name: Cargo Fuzz Build name: Cargo Fuzz Build
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
@@ -16,7 +14,7 @@ jobs:
- x86_64-unknown-linux-gnu - x86_64-unknown-linux-gnu
steps: steps:
- name: Code checkout - name: Code checkout
uses: actions/checkout@v4 uses: actions/checkout@v2
- name: Install Rust toolchain (${{ matrix.rust }}) - name: Install Rust toolchain (${{ matrix.rust }})
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:

View File

@@ -1,25 +0,0 @@
name: Commit messages check
on:
pull_request:
jobs:
gitlint:
name: Check commit messages
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
with:
ref: ${{ github.event.pull_request.head.sha }}
fetch-depth: 0
- name: Set up Python 3.10
uses: actions/setup-python@v3
with:
python-version: "3.10"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install --upgrade gitlint
- name: Lint git commit messages
run: |
gitlint --commits origin/$GITHUB_BASE_REF..

View File

@@ -1,4 +1,5 @@
name: Lint Dockerfile name: Lint Dockerfile
on: on:
push: push:
paths: paths:
@@ -13,7 +14,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - name: Checkout code
uses: actions/checkout@v4 uses: actions/checkout@v3
- name: Lint Dockerfile - name: Lint Dockerfile
uses: hadolint/hadolint-action@master uses: hadolint/hadolint-action@master

View File

@@ -1,54 +0,0 @@
name: Cloud Hypervisor Tests (ARM64)
on: [pull_request, merge_group]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
timeout-minutes: 60
name: Tests (ARM64)
runs-on: focal-arm64
steps:
- name: Fix workspace permissions
run: sudo chown -R github-runner:github-runner ${GITHUB_WORKSPACE}
- name: Code checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run unit tests (musl)
run: scripts/dev_cli.sh tests --unit --libc musl
- name: Load openvswitch module
run: sudo modprobe openvswitch
- name: Run integration tests (musl)
timeout-minutes: 30
run: scripts/dev_cli.sh tests --integration --libc musl
- name: Install Azure CLI
if: ${{ github.event_name != 'pull_request' }}
run: |
sudo apt install -y ca-certificates curl apt-transport-https lsb-release gnupg
curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null
echo "deb [arch=arm64] https://packages.microsoft.com/repos/azure-cli/ focal main" | sudo tee /etc/apt/sources.list.d/azure-cli.list
sudo apt update
sudo apt install -y azure-cli
- name: Download Windows image
if: ${{ github.event_name != 'pull_request' }}
shell: bash
run: |
IMG_BASENAME=windows-11-iot-enterprise-aarch64.raw
IMG_PATH=$HOME/workloads/$IMG_BASENAME
IMG_GZ_PATH=$HOME/workloads/$IMG_BASENAME.gz
IMG_GZ_BLOB_NAME=windows-11-iot-enterprise-aarch64-9-min.raw.gz
cp "scripts/$IMG_BASENAME.sha1" "$HOME/workloads/"
pushd "$HOME/workloads"
if sha1sum "$IMG_BASENAME.sha1" --check; then
exit
fi
popd
mkdir -p "$HOME/workloads"
az storage blob download --container-name private-images --file "$IMG_GZ_PATH" --name "$IMG_GZ_BLOB_NAME" --connection-string "${{ secrets.CH_PRIVATE_IMAGES }}"
gzip -d $IMG_GZ_PATH
- name: Run Windows guest integration tests
if: ${{ github.event_name != 'pull_request' }}
timeout-minutes: 30
run: scripts/dev_cli.sh tests --integration-windows --libc musl

View File

@@ -1,22 +0,0 @@
name: Cloud Hypervisor Tests (Metrics)
on:
push:
branches:
- main
jobs:
build:
name: Tests (Metrics)
runs-on: jammy-metrics
env:
METRICS_PUBLISH_KEY: ${{ secrets.METRICS_PUBLISH_KEY }}
steps:
- name: Code checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run metrics tests
timeout-minutes: 60
run: scripts/dev_cli.sh tests --metrics -- -- --report-file /root/workloads/metrics.json
- name: Upload metrics report
run: 'curl -X PUT https://ch-metrics.azurewebsites.net/api/publishmetrics -H "x-functions-key: $METRICS_PUBLISH_KEY" -T ~/workloads/metrics.json'

View File

@@ -1,28 +0,0 @@
name: Cloud Hypervisor Tests (Rate-Limiter)
on: [merge_group, pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: Tests (Rate-Limiter)
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-latest' || 'jammy-rate-limiter' }}
env:
AUTH_DOWNLOAD_TOKEN: ${{ secrets.AUTH_DOWNLOAD_TOKEN }}
steps:
- name: Fix workspace permissions
if: ${{ github.event_name != 'pull_request' }}
run: sudo chown -R github-runner:github-runner ${GITHUB_WORKSPACE}
- name: Code checkout
if: ${{ github.event_name != 'pull_request' }}
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run rate-limiter integration tests
if: ${{ github.event_name != 'pull_request' }}
timeout-minutes: 10
run: scripts/dev_cli.sh tests --integration-rate-limiter
- name: Skipping build for PR
if: ${{ github.event_name == 'pull_request' }}
run: echo "Skipping build for PR"

View File

@@ -1,32 +0,0 @@
name: Cloud Hypervisor Tests (SGX)
on: [merge_group, pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: Tests (SGX)
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-latest' || 'jammy-sgx' }}
env:
AUTH_DOWNLOAD_TOKEN: ${{ secrets.AUTH_DOWNLOAD_TOKEN }}
steps:
- name: Fix workspace permissions
if: ${{ github.event_name != 'pull_request' }}
run: sudo chown -R github-runner:github-runner ${GITHUB_WORKSPACE}
- name: Code checkout
if: ${{ github.event_name != 'pull_request' }}
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run SGX integration tests
if: ${{ github.event_name != 'pull_request' }}
timeout-minutes: 10
run: scripts/dev_cli.sh tests --integration-sgx
- name: Run SGX integration tests for musl
if: ${{ github.event_name != 'pull_request' }}
timeout-minutes: 10
run: scripts/dev_cli.sh tests --integration-sgx --libc musl
- name: Skipping build for PR
if: ${{ github.event_name == 'pull_request' }}
run: echo "Skipping build for PR"

View File

@@ -1,32 +0,0 @@
name: Cloud Hypervisor Tests (VFIO)
on: [merge_group, pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: Tests (VFIO)
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-latest' || 'jammy-vfio' }}
env:
AUTH_DOWNLOAD_TOKEN: ${{ secrets.AUTH_DOWNLOAD_TOKEN }}
steps:
- name: Fix workspace permissions
if: ${{ github.event_name != 'pull_request' }}
run: sudo chown -R github-runner:github-runner ${GITHUB_WORKSPACE}
- name: Code checkout
if: ${{ github.event_name != 'pull_request' }}
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Run VFIO integration tests
if: ${{ github.event_name != 'pull_request' }}
timeout-minutes: 15
run: scripts/dev_cli.sh tests --integration-vfio
- name: Run VFIO integration tests for musl
if: ${{ github.event_name != 'pull_request' }}
timeout-minutes: 15
run: scripts/dev_cli.sh tests --integration-vfio --libc musl
- name: Skipping build for PR
if: ${{ github.event_name == 'pull_request' }}
run: echo "Skipping build for PR"

View File

@@ -1,50 +0,0 @@
name: Cloud Hypervisor Tests (Windows Guest)
on: [merge_group, pull_request]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: Tests (Windows Guest)
runs-on: ${{ github.event_name == 'pull_request' && 'ubuntu-latest' || 'garm-jammy-16' }}
steps:
- name: Code checkout
if: ${{ github.event_name != 'pull_request' }}
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Docker
if: ${{ github.event_name != 'pull_request' }}
run: |
sudo apt-get update
sudo apt-get -y install ca-certificates curl gnupg
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
sudo chmod a+r /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt install -y docker-ce docker-ce-cli
- name: Install Azure CLI
if: ${{ github.event_name != 'pull_request' }}
run: |
sudo apt install -y ca-certificates curl apt-transport-https lsb-release gnupg
curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null
echo "deb [arch=amd64] https://packages.microsoft.com/repos/azure-cli/ jammy main" | sudo tee /etc/apt/sources.list.d/azure-cli.list
sudo apt update
sudo apt install -y azure-cli
- name: Download Windows image
if: ${{ github.event_name != 'pull_request' }}
run: |
mkdir $HOME/workloads
az storage blob download --container-name private-images --file "$HOME/workloads/windows-server-2022-amd64-2.raw" --name windows-server-2022-amd64-2.raw --connection-string "${{ secrets.CH_PRIVATE_IMAGES }}"
- name: Run Windows guest integration tests
if: ${{ github.event_name != 'pull_request' }}
timeout-minutes: 15
run: scripts/dev_cli.sh tests --integration-windows
- name: Run Windows guest integration tests for musl
if: ${{ github.event_name != 'pull_request' }}
timeout-minutes: 15
run: scripts/dev_cli.sh tests --integration-windows --libc musl
- name: Skipping build for PR
if: ${{ github.event_name == 'pull_request' }}
run: echo "Skipping build for PR"

View File

@@ -1,52 +0,0 @@
name: Cloud Hypervisor Tests (x86-64)
on: [pull_request, merge_group]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
runner: ['garm-jammy', "garm-jammy-amd"]
libc: ["musl", 'gnu']
name: Tests (x86-64)
runs-on: ${{ github.event_name == 'pull_request' && !(matrix.runner == 'garm-jammy' && matrix.libc == 'gnu') && 'ubuntu-latest' || format('{0}-16', matrix.runner) }}
steps:
- name: Code checkout
if: ${{ github.event_name != 'pull_request' || (matrix.runner == 'garm-jammy' && matrix.libc == 'gnu') }}
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Install Docker
if: ${{ github.event_name != 'pull_request' || (matrix.runner == 'garm-jammy' && matrix.libc == 'gnu') }}
run: |
sudo apt-get update
sudo apt-get -y install ca-certificates curl gnupg
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
sudo chmod a+r /usr/share/keyrings/docker-archive-keyring.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
sudo apt install -y docker-ce docker-ce-cli
- name: Prepare for VDPA
if: ${{ github.event_name != 'pull_request' || (matrix.runner == 'garm-jammy' && matrix.libc == 'gnu') }}
run: scripts/prepare_vdpa.sh
- name: Run unit tests
if: ${{ github.event_name != 'pull_request' || (matrix.runner == 'garm-jammy' && matrix.libc == 'gnu') }}
run: scripts/dev_cli.sh tests --unit --libc ${{ matrix.libc }}
- name: Load openvswitch module
if: ${{ github.event_name != 'pull_request' || (matrix.runner == 'garm-jammy' && matrix.libc == 'gnu') }}
run: sudo modprobe openvswitch
- name: Run integration tests
if: ${{ github.event_name != 'pull_request' || (matrix.runner == 'garm-jammy' && matrix.libc == 'gnu') }}
timeout-minutes: 40
run: scripts/dev_cli.sh tests --integration --libc ${{ matrix.libc }}
- name: Run live-migration integration tests
if: ${{ github.event_name != 'pull_request' || (matrix.runner == 'garm-jammy' && matrix.libc == 'gnu') }}
timeout-minutes: 20
run: scripts/dev_cli.sh tests --integration-live-migration --libc ${{ matrix.libc }}
- name: Skipping build for PR
if: ${{ github.event_name == 'pull_request' && matrix.runner != 'garm-jammy' && matrix.libc != 'gnu' }}
run: echo "Skipping build for PR"

View File

@@ -1,14 +0,0 @@
name: Cloud Hypervisor OpenAPI Validation
on: [pull_request, merge_group]
jobs:
Validate:
runs-on: ubuntu-latest
container: openapitools/openapi-generator-cli
steps:
- uses: actions/checkout@v4
- name: Validate OpenAPI
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
/usr/local/bin/docker-entrypoint.sh validate -i vmm/src/api/openapi/cloud-hypervisor.yaml

View File

@@ -1,11 +1,9 @@
name: Cloud Hypervisor Quality Checks name: Cloud Hypervisor Quality Checks
on: [pull_request, merge_group] on: [pull_request, create]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs: jobs:
build: build:
if: github.event_name == 'pull_request'
name: Quality (clippy, rustfmt) name: Quality (clippy, rustfmt)
runs-on: ubuntu-latest runs-on: ubuntu-latest
continue-on-error: ${{ matrix.experimental }} continue-on-error: ${{ matrix.experimental }}
@@ -36,7 +34,7 @@ jobs:
experimental: true experimental: true
steps: steps:
- name: Code checkout - name: Code checkout
uses: actions/checkout@v4 uses: actions/checkout@v3
with: with:
fetch-depth: 0 fetch-depth: 0
@@ -48,8 +46,8 @@ jobs:
override: true override: true
components: rustfmt, clippy components: rustfmt, clippy
- name: Bisectability Check (default features) - name: Debug Check (default features)
if: ${{ github.event_name == 'pull_request' && matrix.target == 'x86_64-unknown-linux-gnu' }} if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
run: | run: |
set -e set -e
commits=$(git rev-list origin/${{ github.base_ref }}..${{ github.sha }}) commits=$(git rev-list origin/${{ github.base_ref }}..${{ github.sha }})
@@ -111,14 +109,6 @@ jobs:
command: clippy command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "sev_snp" -- -D warnings -D clippy::undocumented_unsafe_blocks args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "sev_snp" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Clippy (igvm)
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
uses: actions-rs/cargo@v1
with:
use-cross: ${{ matrix.target != 'x86_64-unknown-linux-gnu' }}
command: clippy
args: --target=${{ matrix.target }} --locked --all --all-targets --no-default-features --tests --examples --features "igvm" -- -D warnings -D clippy::undocumented_unsafe_blocks
- name: Clippy (kvm + tdx) - name: Clippy (kvm + tdx)
if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }} if: ${{ matrix.target == 'x86_64-unknown-linux-gnu' }}
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
@@ -135,6 +125,6 @@ jobs:
name: Typos / Spellcheck name: Typos / Spellcheck
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v3
# Executes "typos ." # Executes "typos ."
- uses: crate-ci/typos@v1.16.11 - uses: crate-ci/typos@v1.16.11

View File

@@ -1,17 +1,14 @@
name: Cloud Hypervisor Release name: Cloud Hypervisor Release
on: [create, merge_group] on: [pull_request, create]
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }}
cancel-in-progress: true
jobs: jobs:
release: release:
if: (github.event_name == 'create' && github.event.ref_type == 'tag') || github.event_name == 'merge_group' if: (github.event_name == 'create' && github.event.ref_type == 'tag') || github.event_name == 'pull_request'
name: Release name: Release
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Code checkout - name: Code checkout
uses: actions/checkout@v4 uses: actions/checkout@v2
- name: Install musl-gcc - name: Install musl-gcc
run: sudo apt install -y musl-tools run: sudo apt install -y musl-tools
- name: Create release directory - name: Create release directory
@@ -19,29 +16,29 @@ jobs:
- name: Install Rust toolchain (x86_64-unknown-linux-gnu) - name: Install Rust toolchain (x86_64-unknown-linux-gnu)
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
toolchain: "1.70" toolchain: "1.67.1"
target: x86_64-unknown-linux-gnu target: x86_64-unknown-linux-gnu
- name: Install Rust toolchain (x86_64-unknown-linux-musl) - name: Install Rust toolchain (x86_64-unknown-linux-musl)
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
toolchain: "1.70" toolchain: "1.67.1"
target: x86_64-unknown-linux-musl target: x86_64-unknown-linux-musl
- name: Build - name: Build
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
toolchain: "1.70" toolchain: "1.67.1"
command: build command: build
args: --all --release --features mshv --target=x86_64-unknown-linux-gnu args: --all --release --features mshv --target=x86_64-unknown-linux-gnu
- name: Static Build - name: Static Build
uses: actions-rs/cargo@v1 uses: actions-rs/cargo@v1
with: with:
toolchain: "1.70" toolchain: "1.67.1"
command: build command: build
args: --all --release --features mshv --target=x86_64-unknown-linux-musl args: --all --release --features mshv --target=x86_64-unknown-linux-musl
- name: Install Rust toolchain (aarch64-unknown-linux-musl) - name: Install Rust toolchain (aarch64-unknown-linux-musl)
uses: actions-rs/toolchain@v1 uses: actions-rs/toolchain@v1
with: with:
toolchain: "1.70" toolchain: "1.67.1"
target: aarch64-unknown-linux-musl target: aarch64-unknown-linux-musl
override: true override: true
- name: Create Release - name: Create Release

View File

@@ -1,15 +0,0 @@
[general]
extra-path=scripts/gitlint/rules.py
regex-style-search=true
[ignore-by-author-name]
regex=dependabot
ignore=all
# default 72
[title-max-length]
line-length=72
# default 80
[body-max-line-length]
line-length=72

474
Cargo.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
[package] [package]
name = "cloud-hypervisor" name = "cloud-hypervisor"
version = "37.1.0" version = "36.1.0"
authors = ["The Cloud Hypervisor Authors"] authors = ["The Cloud Hypervisor Authors"]
edition = "2021" edition = "2021"
default-run = "cloud-hypervisor" default-run = "cloud-hypervisor"
@@ -15,7 +15,7 @@ homepage = "https://github.com/cloud-hypervisor/cloud-hypervisor"
# a.) A dependency requires it, # a.) A dependency requires it,
# b.) If we want to use a new feature and that MSRV is at least 6 months old, # 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. # c.) There is a security issue that is addressed by the toolchain update.
rust-version = "1.70" rust-version = "1.66"
[profile.release] [profile.release]
lto = true lto = true
@@ -31,13 +31,13 @@ debug = true
[dependencies] [dependencies]
anyhow = "1.0.75" anyhow = "1.0.75"
api_client = { path = "api_client" } api_client = { path = "api_client" }
clap = { version = "4.4.7", features = ["string"] } clap = { version = "4.3.11", features = ["string"] }
dhat = { version = "0.3.2", optional = true } dhat = { version = "0.3.2", optional = true }
epoll = "4.3.3" epoll = "4.3.3"
event_monitor = { path = "event_monitor" } event_monitor = { path = "event_monitor" }
hypervisor = { path = "hypervisor" } hypervisor = { path = "hypervisor" }
libc = "0.2.147" libc = "0.2.147"
log = { version = "0.4.20", features = ["std"] } log = { version = "0.4.17", features = ["std"] }
option_parser = { path = "option_parser" } option_parser = { path = "option_parser" }
seccompiler = "0.4.0" seccompiler = "0.4.0"
serde_json = "1.0.107" serde_json = "1.0.107"
@@ -46,14 +46,15 @@ thiserror = "1.0.40"
tpm = { path = "tpm"} tpm = { path = "tpm"}
tracer = { path = "tracer" } tracer = { path = "tracer" }
vmm = { path = "vmm" } vmm = { path = "vmm" }
vmm-sys-util = "0.12.1" vmm-sys-util = "0.11.0"
vm-memory = "0.14.0" vm-memory = "0.12.2"
zbus = { version = "3.11.1", optional = true } zbus = { version = "3.11.1", optional = true }
# List of patched crates # List of patched crates
[patch.crates-io] [patch.crates-io]
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-live-upgrade-stable-37.x" } kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.6.0-tdx" }
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch-0.1.6" } kvm-ioctls = { git = "https://github.com/rust-vmm/kvm-ioctls", branch = "main" }
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch" }
[dev-dependencies] [dev-dependencies]
dirs = "5.0.0" dirs = "5.0.0"
@@ -70,11 +71,10 @@ default = ["kvm", "io_uring"]
dbus_api = ["zbus", "vmm/dbus_api"] dbus_api = ["zbus", "vmm/dbus_api"]
dhat-heap = ["dhat"] # For heap profiling dhat-heap = ["dhat"] # For heap profiling
guest_debug = ["vmm/guest_debug"] guest_debug = ["vmm/guest_debug"]
igvm = ["vmm/igvm", "mshv"]
io_uring = ["vmm/io_uring"] io_uring = ["vmm/io_uring"]
kvm = ["vmm/kvm"] kvm = ["vmm/kvm"]
mshv = ["vmm/mshv"] mshv = ["vmm/mshv"]
sev_snp = ["igvm", "vmm/sev_snp", "mshv"] sev_snp = ["vmm/sev_snp", "mshv"]
tdx = ["vmm/tdx"] tdx = ["vmm/tdx"]
tracing = ["vmm/tracing", "tracer/tracing"] tracing = ["vmm/tracing", "tracer/tracing"]

509
Jenkinsfile vendored Normal file
View File

@@ -0,0 +1,509 @@
def runWorkers = true
pipeline {
agent none
options {
timeout(time: 4, unit: 'HOURS')
}
stages {
stage('Early checks') {
agent { node { label 'built-in' } }
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Check if worker build can be skipped') {
when {
expression {
return skipWorkerBuild()
}
}
steps {
script {
runWorkers = false
echo 'No changes requiring a build'
}
}
}
stage('Check for RFC/WIP builds') {
when {
changeRequest comparator: 'REGEXP', title: '.*(rfc|RFC|wip|WIP).*'
beforeAgent true
}
steps {
error('Failing as this is marked as a WIP or RFC PR.')
}
}
stage('Cancel older builds') {
when { not { branch 'main' } }
steps {
cancelPreviousBuilds()
}
}
}
}
stage('Build') {
parallel {
stage('Worker build') {
agent { node { label 'jammy' } }
when {
beforeAgent true
expression {
return runWorkers
}
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Prepare environment') {
steps {
sh 'scripts/prepare_vdpa.sh'
}
}
stage('Run OpenAPI tests') {
steps {
sh 'scripts/run_openapi_tests.sh'
}
}
stage('Run unit tests') {
steps {
sh 'scripts/dev_cli.sh tests --unit'
}
}
stage('Run integration tests') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'sudo modprobe openvswitch'
sh 'scripts/dev_cli.sh tests --integration'
}
}
stage('Run live-migration integration tests') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'sudo modprobe openvswitch'
sh 'scripts/dev_cli.sh tests --integration-live-migration'
}
}
stage('Run unit tests for musl') {
steps {
sh 'scripts/dev_cli.sh tests --unit --libc musl'
}
}
stage('Run integration tests for musl') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'sudo modprobe openvswitch'
sh 'scripts/dev_cli.sh tests --integration --libc musl'
}
}
stage('Run live-migration integration tests for musl') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'sudo modprobe openvswitch'
sh 'scripts/dev_cli.sh tests --integration-live-migration --libc musl'
}
}
}
}
stage('Worker build - AMD') {
agent { node { label 'jammy-amd' } }
when {
beforeAgent true
expression {
return runWorkers
}
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Prepare environment') {
steps {
sh 'scripts/prepare_vdpa.sh'
}
}
stage('Run integration tests') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'sudo modprobe openvswitch'
sh 'scripts/dev_cli.sh tests --integration -- -- --skip common_parallel::test_vfio'
}
}
stage('Run live-migration integration tests') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'sudo modprobe openvswitch'
sh 'scripts/dev_cli.sh tests --integration-live-migration'
}
}
stage('Run integration tests for musl') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'sudo modprobe openvswitch'
sh 'scripts/dev_cli.sh tests --integration --libc musl -- -- --skip common_parallel::test_vfio'
}
}
stage('Run live-migration integration tests for musl') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'sudo modprobe openvswitch'
sh 'scripts/dev_cli.sh tests --integration-live-migration --libc musl'
}
}
}
}
stage('AArch64 worker build') {
agent { node { label 'bionic-arm64' } }
when {
beforeAgent true
expression {
return runWorkers
}
}
environment {
AZURE_CONNECTION_STRING = credentials('46b4e7d6-315f-4cc1-8333-b58780863b9b')
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Run unit tests') {
steps {
sh 'scripts/dev_cli.sh tests --unit --libc musl'
}
}
stage('Run integration tests') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'sudo modprobe openvswitch'
sh 'scripts/dev_cli.sh tests --integration --libc musl'
}
}
stage('Install azure-cli') {
steps {
installAzureCli('focal', 'arm64')
}
}
stage('Download Windows image') {
steps {
sh '''#!/bin/bash -x
IMG_BASENAME=windows-11-iot-enterprise-aarch64.raw
IMG_PATH=$HOME/workloads/$IMG_BASENAME
IMG_GZ_PATH=$HOME/workloads/$IMG_BASENAME.gz
IMG_GZ_BLOB_NAME=windows-11-iot-enterprise-aarch64-9-min.raw.gz
cp "scripts/$IMG_BASENAME.sha1" "$HOME/workloads/"
pushd "$HOME/workloads"
if sha1sum "$IMG_BASENAME.sha1" --check; then
exit
fi
popd
mkdir -p "$HOME/workloads"
az storage blob download \
--container-name private-images \
--file "$IMG_GZ_PATH" \
--name "$IMG_GZ_BLOB_NAME" \
--connection-string "$AZURE_CONNECTION_STRING"
gzip -d $IMG_GZ_PATH
'''
}
}
stage('Run Windows guest integration tests') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'scripts/dev_cli.sh tests --integration-windows --libc musl'
}
}
}
post {
always {
sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
deleteDir()
}
}
}
stage('Worker build - Windows guest') {
agent { node { label 'jammy' } }
when {
beforeAgent true
expression {
return runWorkers
}
}
environment {
AZURE_CONNECTION_STRING = credentials('46b4e7d6-315f-4cc1-8333-b58780863b9b')
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Install azure-cli') {
steps {
installAzureCli('jammy', 'amd64')
}
}
stage('Download assets') {
steps {
sh "mkdir ${env.HOME}/workloads"
sh 'az storage blob download --container-name private-images --file "$HOME/workloads/windows-server-2022-amd64-2.raw" --name windows-server-2022-amd64-2.raw --connection-string "$AZURE_CONNECTION_STRING"'
}
}
stage('Run Windows guest integration tests') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'scripts/dev_cli.sh tests --integration-windows'
}
}
stage('Run Windows guest integration tests for musl') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'scripts/dev_cli.sh tests --integration-windows --libc musl'
}
}
}
}
stage('Worker build - Metrics') {
agent { node { label 'jammy-metrics' } }
when {
branch 'main'
beforeAgent true
expression {
return runWorkers
}
}
environment {
METRICS_PUBLISH_KEY = credentials('52e0945f-ce7a-43d1-87af-67d1d87cc40f')
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Run metrics tests') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'scripts/dev_cli.sh tests --metrics -- -- --report-file /root/workloads/metrics.json'
}
}
stage('Upload metrics report') {
steps {
sh 'curl -X PUT https://cloud-hypervisor-metrics.azurewebsites.net/api/publishmetrics -H "x-functions-key: $METRICS_PUBLISH_KEY" -T ~/workloads/metrics.json'
}
}
}
}
stage('Worker build - Rate Limiter') {
agent { node { label 'focal-metrics' } }
when {
branch 'main'
beforeAgent true
expression {
return runWorkers
}
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Run rate-limiter integration tests') {
options {
timeout(time: 10, unit: 'MINUTES')
}
steps {
sh 'scripts/dev_cli.sh tests --integration-rate-limiter'
}
}
}
}
stage('Worker build - SGX') {
agent { node { label 'jammy-sgx' } }
when {
beforeAgent true
allOf {
branch 'main'
expression {
return runWorkers
}
}
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Run SGX integration tests') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'scripts/dev_cli.sh tests --integration-sgx'
}
}
stage('Run SGX integration tests for musl') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'scripts/dev_cli.sh tests --integration-sgx --libc musl'
}
}
}
post {
always {
sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
deleteDir()
}
}
}
stage('Worker build - VFIO') {
agent { node { label 'jammy-vfio' } }
when {
beforeAgent true
allOf {
branch 'main'
expression {
return runWorkers
}
}
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Run VFIO integration tests') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'scripts/dev_cli.sh tests --integration-vfio'
}
}
stage('Run VFIO integration tests for musl') {
options {
timeout(time: 1, unit: 'HOURS')
}
steps {
sh 'scripts/dev_cli.sh tests --integration-vfio --libc musl'
}
}
}
post {
always {
sh "sudo chown -R jenkins.jenkins ${WORKSPACE}"
deleteDir()
}
}
}
}
}
}
post {
regression {
script {
if (env.BRANCH_NAME == 'main') {
slackSend(color: '#ff0000', message: '"main" branch build is now failing', channel: '#jenkins-ci')
}
}
}
fixed {
script {
if (env.BRANCH_NAME == 'main') {
slackSend(color: '#00ff00', message: '"main" branch build is now fixed', channel: '#jenkins-ci')
}
}
}
}
}
def cancelPreviousBuilds() {
// Check for other instances of this particular build, cancel any that are older than the current one
def jobName = env.JOB_NAME
def currentBuildNumber = env.BUILD_NUMBER.toInteger()
def currentJob = Jenkins.instance.getItemByFullName(jobName)
// Loop through all instances of this particular job/branch
for (def build : currentJob.builds) {
if (build.isBuilding() && (build.number.toInteger() < currentBuildNumber)) {
echo "Older build still queued. Sending kill signal to build number: ${build.number}"
build.doStop()
}
}
}
def installAzureCli(distro, arch) {
sh 'sudo apt install -y ca-certificates curl apt-transport-https lsb-release gnupg'
sh 'curl -sL https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/microsoft.gpg > /dev/null'
sh "echo \"deb [arch=${arch}] https://packages.microsoft.com/repos/azure-cli/ ${distro} main\" | sudo tee /etc/apt/sources.list.d/azure-cli.list"
sh 'sudo apt update'
sh 'sudo apt install -y azure-cli'
}
def boolean skipWorkerBuild() {
if (env.CHANGE_TARGET == null) {
return false
}
if (sh(
returnStatus: true,
script: "git diff --name-only origin/${env.CHANGE_TARGET}... | grep -v '\\.md'"
) != 0) {
return true
}
if (sh(
returnStatus: true,
script: "git diff --name-only origin/${env.CHANGE_TARGET}... | grep -v -E 'fuzz/'"
) != 0) {
return true
}
if (sh(
returnStatus: true,
script: "git diff --name-only origin/${env.CHANGE_TARGET}... | grep -v -E '.github/'"
) != 0) {
return true
}
return false
}

View File

@@ -5,4 +5,4 @@ authors = ["The Cloud Hypervisor Authors"]
edition = "2021" edition = "2021"
[dependencies] [dependencies]
vmm-sys-util = "0.12.1" vmm-sys-util = "0.11.0"

View File

@@ -14,16 +14,16 @@ anyhow = "1.0.75"
byteorder = "1.4.3" byteorder = "1.4.3"
hypervisor = { path = "../hypervisor" } hypervisor = { path = "../hypervisor" }
libc = "0.2.147" libc = "0.2.147"
linux-loader = { version = "0.11.0", features = ["elf", "bzimage", "pe"] } linux-loader = { version = "0.9.1", features = ["elf", "bzimage", "pe"] }
log = "0.4.20" log = "0.4.17"
serde = { version = "1.0.168", features = ["rc", "derive"] } serde = { version = "1.0.168", features = ["rc", "derive"] }
thiserror = "1.0.40" thiserror = "1.0.40"
uuid = "1.3.4" uuid = "1.3.4"
versionize = "0.2.0" versionize = "0.1.10"
versionize_derive = "0.1.6" versionize_derive = "0.1.4"
vm-memory = { version = "0.14.0", features = ["backend-mmap", "backend-bitmap"] } vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-bitmap"] }
vm-migration = { path = "../vm-migration" } vm-migration = { path = "../vm-migration" }
vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }
[target.'cfg(target_arch = "aarch64")'.dependencies] [target.'cfg(target_arch = "aarch64")'.dependencies]
fdt_parser = { version = "0.1.4", package = "fdt" } fdt_parser = { version = "0.1.4", package = "fdt" }

View File

@@ -1,9 +1,8 @@
// Copyright 2020 Arm Limited (or its affiliates). All rights reserved. // Copyright 2020 Arm Limited (or its affiliates). All rights reserved.
use std::io::{Read, Seek, SeekFrom}; use std::io::{Read, Seek, SeekFrom};
use std::os::fd::AsFd;
use std::result; use std::result;
use vm_memory::{GuestAddress, GuestMemory}; use vm_memory::{Bytes, GuestAddress, GuestMemory};
/// Errors thrown while loading UEFI binary /// Errors thrown while loading UEFI binary
#[derive(Debug)] #[derive(Debug)]
@@ -25,7 +24,7 @@ pub fn load_uefi<F, M: GuestMemory>(
uefi_image: &mut F, uefi_image: &mut F,
) -> Result<()> ) -> Result<()>
where where
F: Read + Seek + AsFd, F: Read + Seek,
{ {
let uefi_size = uefi_image let uefi_size = uefi_image
.seek(SeekFrom::End(0)) .seek(SeekFrom::End(0))
@@ -37,6 +36,6 @@ where
} }
uefi_image.rewind().map_err(|_| Error::SeekUefiStart)?; uefi_image.rewind().map_err(|_| Error::SeekUefiStart)?;
guest_mem guest_mem
.read_exact_volatile_from(guest_addr, &mut uefi_image.as_fd(), uefi_size) .read_exact_from(guest_addr, uefi_image, uefi_size)
.map_err(|_| Error::ReadUefiImage) .map_err(|_| Error::ReadUefiImage)
} }

View File

@@ -91,9 +91,8 @@ pub mod x86_64;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub use x86_64::{ pub use x86_64::{
arch_memory_regions, configure_system, configure_vcpu, generate_common_cpuid, arch_memory_regions, configure_system, configure_vcpu, generate_common_cpuid,
generate_ram_ranges, get_host_cpu_phys_bits, initramfs_load_addr, layout, get_host_cpu_phys_bits, initramfs_load_addr, layout, layout::CMDLINE_MAX_SIZE,
layout::CMDLINE_MAX_SIZE, layout::CMDLINE_START, regs, CpuidConfig, CpuidFeatureEntry, layout::CMDLINE_START, regs, CpuidConfig, CpuidFeatureEntry, EntryPoint, _NSIG,
EntryPoint, _NSIG,
}; };
/// Safe wrapper for `sysconf(_SC_PAGESIZE)`. /// Safe wrapper for `sysconf(_SC_PAGESIZE)`.

View File

@@ -17,13 +17,14 @@ use crate::InitramfsConfig;
use crate::RegionType; use crate::RegionType;
use hypervisor::arch::x86::{CpuIdEntry, CPUID_FLAG_VALID_INDEX}; use hypervisor::arch::x86::{CpuIdEntry, CPUID_FLAG_VALID_INDEX};
use hypervisor::{CpuVendor, HypervisorCpuError, HypervisorError}; use hypervisor::{CpuVendor, HypervisorCpuError, HypervisorError};
use linux_loader::loader::bootparam::boot_params;
use linux_loader::loader::elf::start_info::{ use linux_loader::loader::elf::start_info::{
hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info, hvm_memmap_table_entry, hvm_modlist_entry, hvm_start_info,
}; };
use std::collections::BTreeMap; use std::collections::BTreeMap;
use std::mem; use std::mem;
use vm_memory::{ use vm_memory::{
Address, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic, Address, ByteValued, Bytes, GuestAddress, GuestAddressSpace, GuestMemory, GuestMemoryAtomic,
GuestMemoryRegion, GuestUsize, GuestMemoryRegion, GuestUsize,
}; };
mod smbios; mod smbios;
@@ -115,6 +116,38 @@ impl SgxEpcRegion {
} }
} }
// This is a workaround to the Rust enforcement specifying that any implementation of a foreign
// trait (in this case `DataInit`) where:
// * the type that is implementing the trait is foreign or
// * all of the parameters being passed to the trait (if there are any) are also foreign
// is prohibited.
#[derive(Copy, Clone, Default)]
struct StartInfoWrapper(hvm_start_info);
#[derive(Copy, Clone, Default)]
struct MemmapTableEntryWrapper(hvm_memmap_table_entry);
#[derive(Copy, Clone, Default)]
struct ModlistEntryWrapper(hvm_modlist_entry);
// SAFETY: data structure only contain a series of integers
unsafe impl ByteValued for StartInfoWrapper {}
// SAFETY: data structure only contain a series of integers
unsafe impl ByteValued for MemmapTableEntryWrapper {}
// SAFETY: data structure only contain a series of integers
unsafe impl ByteValued for ModlistEntryWrapper {}
// This is a workaround to the Rust enforcement specifying that any implementation of a foreign
// trait (in this case `DataInit`) where:
// * the type that is implementing the trait is foreign or
// * all of the parameters being passed to the trait (if there are any) are also foreign
// is prohibited.
#[derive(Copy, Clone, Default)]
struct BootParamsWrapper(boot_params);
// SAFETY: BootParamsWrap is a wrapper over `boot_params` (a series of ints).
unsafe impl ByteValued for BootParamsWrapper {}
pub struct CpuidConfig { pub struct CpuidConfig {
pub sgx_epc_sections: Option<Vec<SgxEpcSection>>, pub sgx_epc_sections: Option<Vec<SgxEpcSection>>,
pub phys_bits: u8, pub phys_bits: u8,
@@ -188,26 +221,6 @@ impl From<Error> for super::Error {
} }
} }
pub fn get_x2apic_id(cpu_id: u32, topology: Option<(u8, u8, u8)>) -> u32 {
if let Some(t) = topology {
let thread_mask_width = u8::BITS - (t.0 - 1).leading_zeros();
let core_mask_width = u8::BITS - (t.1 - 1).leading_zeros();
let die_mask_width = u8::BITS - (t.2 - 1).leading_zeros();
let thread_id = cpu_id % (t.0 as u32);
let core_id = cpu_id / (t.0 as u32) % (t.1 as u32);
let die_id = cpu_id / ((t.0 * t.1) as u32) % (t.2 as u32);
let socket_id = cpu_id / ((t.0 * t.1 * t.2) as u32);
return thread_id
| (core_id << thread_mask_width)
| (die_id << (thread_mask_width + core_mask_width))
| (socket_id << (thread_mask_width + core_mask_width + die_mask_width));
}
cpu_id
}
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug)]
pub enum CpuidReg { pub enum CpuidReg {
EAX, EAX,
@@ -227,26 +240,6 @@ pub struct CpuidPatch {
} }
impl CpuidPatch { impl CpuidPatch {
pub fn get_cpuid_reg(
cpuid: &[CpuIdEntry],
function: u32,
index: Option<u32>,
reg: CpuidReg,
) -> Option<u32> {
for entry in cpuid.iter() {
if entry.function == function && (index.is_none() || index.unwrap() == entry.index) {
return match reg {
CpuidReg::EAX => Some(entry.eax),
CpuidReg::EBX => Some(entry.ebx),
CpuidReg::ECX => Some(entry.ecx),
CpuidReg::EDX => Some(entry.edx),
};
}
}
None
}
pub fn set_cpuid_reg( pub fn set_cpuid_reg(
cpuid: &mut Vec<CpuIdEntry>, cpuid: &mut Vec<CpuIdEntry>,
function: u32, function: u32,
@@ -784,27 +777,31 @@ pub fn configure_vcpu(
cpu_vendor: CpuVendor, cpu_vendor: CpuVendor,
topology: Option<(u8, u8, u8)>, topology: Option<(u8, u8, u8)>,
) -> super::Result<()> { ) -> super::Result<()> {
let x2apic_id = get_x2apic_id(id as u32, topology);
// Per vCPU CPUID changes; common are handled via generate_common_cpuid() // Per vCPU CPUID changes; common are handled via generate_common_cpuid()
let mut cpuid = cpuid; let mut cpuid = cpuid;
CpuidPatch::set_cpuid_reg(&mut cpuid, 0xb, None, CpuidReg::EDX, x2apic_id); CpuidPatch::set_cpuid_reg(&mut cpuid, 0xb, None, CpuidReg::EDX, u32::from(id));
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1f, None, CpuidReg::EDX, x2apic_id); CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1f, None, CpuidReg::EDX, u32::from(id));
if matches!(cpu_vendor, CpuVendor::AMD) { if matches!(cpu_vendor, CpuVendor::AMD) {
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x8000_001e, Some(0), CpuidReg::EAX, x2apic_id); CpuidPatch::set_cpuid_reg(
&mut cpuid,
0x8000_001e,
Some(0),
CpuidReg::EAX,
u32::from(id),
);
}
if let Some(t) = topology {
update_cpuid_topology(&mut cpuid, t.0, t.1, t.2, cpu_vendor, id);
} }
// Set ApicId in cpuid for each vcpu // Set ApicId in cpuid for each vcpu
// SAFETY: get host cpuid when eax=1 // SAFETY: get host cpuid when eax=1
let mut cpu_ebx = unsafe { core::arch::x86_64::__cpuid(1) }.ebx; let mut cpu_ebx = unsafe { core::arch::x86_64::__cpuid(1) }.ebx;
cpu_ebx &= 0xffffff; cpu_ebx &= 0xffffff;
cpu_ebx |= x2apic_id << 24; cpu_ebx |= (id as u32) << 24;
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1, None, CpuidReg::EBX, cpu_ebx); CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1, None, CpuidReg::EBX, cpu_ebx);
if let Some(t) = topology {
update_cpuid_topology(&mut cpuid, t.0, t.1, t.2, cpu_vendor, id);
}
// The TSC frequency CPUID leaf should not be included when running with HyperV emulation // The TSC frequency CPUID leaf should not be included when running with HyperV emulation
if !kvm_hyperv { if !kvm_hyperv {
if let Some(tsc_khz) = vcpu.tsc_khz().map_err(Error::GetTscFrequency)? { if let Some(tsc_khz) = vcpu.tsc_khz().map_err(Error::GetTscFrequency)? {
@@ -899,7 +896,6 @@ pub fn configure_system(
serial_number: Option<&str>, serial_number: Option<&str>,
uuid: Option<&str>, uuid: Option<&str>,
oem_strings: Option<&[&str]>, oem_strings: Option<&[&str]>,
topology: Option<(u8, u8, u8)>,
) -> super::Result<()> { ) -> super::Result<()> {
// Write EBDA address to location where ACPICA expects to find it // Write EBDA address to location where ACPICA expects to find it
guest_mem guest_mem
@@ -912,7 +908,7 @@ pub fn configure_system(
// Place the MP table after the SMIOS table aligned to 16 bytes // Place the MP table after the SMIOS table aligned to 16 bytes
let offset = GuestAddress(layout::SMBIOS_START).unchecked_add(size); let offset = GuestAddress(layout::SMBIOS_START).unchecked_add(size);
let offset = GuestAddress((offset.0 + 16) & !0xf); let offset = GuestAddress((offset.0 + 16) & !0xf);
mptable::setup_mptable(offset, guest_mem, _num_cpus, topology).map_err(Error::MpTableSetup)?; mptable::setup_mptable(offset, guest_mem, _num_cpus).map_err(Error::MpTableSetup)?;
// Check that the RAM is not smaller than the RSDP start address // Check that the RAM is not smaller than the RSDP start address
if let Some(rsdp_addr) = rsdp_addr { if let Some(rsdp_addr) = rsdp_addr {
@@ -930,16 +926,52 @@ pub fn configure_system(
) )
} }
type RamRange = (u64, u64); fn configure_pvh(
/// Returns usable physical memory ranges for the guest
/// These should be used to create e820_RAM memory maps
///
/// 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, guest_mem: &GuestMemoryMmap,
) -> super::Result<(RamRange, Option<RamRange>)> { cmdline_addr: GuestAddress,
initramfs: &Option<InitramfsConfig>,
rsdp_addr: Option<GuestAddress>,
sgx_epc_region: Option<SgxEpcRegion>,
) -> super::Result<()> {
const XEN_HVM_START_MAGIC_VALUE: u32 = 0x336ec578;
let mut start_info: StartInfoWrapper = StartInfoWrapper(hvm_start_info::default());
start_info.0.magic = XEN_HVM_START_MAGIC_VALUE;
start_info.0.version = 1; // pvh has version 1
start_info.0.nr_modules = 0;
start_info.0.cmdline_paddr = cmdline_addr.raw_value();
start_info.0.memmap_paddr = layout::MEMMAP_START.raw_value();
if let Some(rsdp_addr) = rsdp_addr {
start_info.0.rsdp_paddr = rsdp_addr.0;
}
if let Some(initramfs_config) = initramfs {
// The initramfs has been written to guest memory already, here we just need to
// create the module structure that describes it.
let ramdisk_mod: ModlistEntryWrapper = ModlistEntryWrapper(hvm_modlist_entry {
paddr: initramfs_config.address.raw_value(),
size: initramfs_config.size as u64,
..Default::default()
});
start_info.0.nr_modules += 1;
start_info.0.modlist_paddr = layout::MODLIST_START.raw_value();
// Write the modlist struct to guest memory.
guest_mem
.write_obj(ramdisk_mod, layout::MODLIST_START)
.map_err(super::Error::ModlistSetup)?;
}
// Vector to hold the memory maps which needs to be written to guest memory
// at MEMMAP_START after all of the mappings are recorded.
let mut memmap: Vec<hvm_memmap_table_entry> = Vec::new();
// Create the memory map entries.
add_memmap_entry(&mut memmap, 0, layout::EBDA_START.raw_value(), E820_RAM);
// Merge continuous memory regions into one region. // Merge continuous memory regions into one region.
// Note: memory regions from "GuestMemory" are sorted and non-zero sized. // Note: memory regions from "GuestMemory" are sorted and non-zero sized.
let ram_regions = { let ram_regions = {
@@ -974,14 +1006,14 @@ pub fn generate_ram_ranges(
if ram_regions.len() > 2 { if ram_regions.len() > 2 {
error!( error!(
"There should be up to two usable physical memory ranges, devidided by the "There should be up to two non-continuous regions, devidided by the
gap at the end of 32bit address space (e.g. between 3G and 4G)." gap at the end of 32bit address space (e.g. between 3G and 4G)."
); );
return Err(super::Error::MemmapTableSetup); return Err(super::Error::MemmapTableSetup);
} }
// Generate the first usable physical memory range before the gap // Create the memory map entry for memory region before the gap
let first_ram_range = { {
let (first_region_start, first_region_end) = let (first_region_start, first_region_end) =
ram_regions.first().ok_or(super::Error::MemmapTableSetup)?; ram_regions.first().ok_or(super::Error::MemmapTableSetup)?;
let high_ram_start = layout::HIGH_RAM_START.raw_value(); let high_ram_start = layout::HIGH_RAM_START.raw_value();
@@ -1001,17 +1033,20 @@ pub fn generate_ram_ranges(
} }
info!( info!(
"first usable physical memory range, start: 0x{:08x}, end: 0x{:08x}", "create_memmap_entry, start: 0x{:08x}, end: 0x{:08x}",
high_ram_start, first_region_end high_ram_start, first_region_end
); );
(high_ram_start, *first_region_end) add_memmap_entry(
}; &mut memmap,
high_ram_start,
first_region_end - high_ram_start,
E820_RAM,
);
}
// Generate the second usable physical memory range after the gap if any // Create the memory map entry for memory region after the gap if any
let second_ram_range = if let Some((second_region_start, second_region_end)) = if let Some((second_region_start, second_region_end)) = ram_regions.get(1) {
ram_regions.get(1)
{
let ram_64bit_start = layout::RAM_64BIT_START.raw_value(); let ram_64bit_start = layout::RAM_64BIT_START.raw_value();
if second_region_start != &ram_64bit_start { if second_region_start != &ram_64bit_start {
@@ -1023,91 +1058,14 @@ pub fn generate_ram_ranges(
return Err(super::Error::MemmapTableSetup); return Err(super::Error::MemmapTableSetup);
} }
info!(
"Second usable physical memory range, start: 0x{:08x}, end: 0x{:08x}",
ram_64bit_start, second_region_end
);
Some((ram_64bit_start, *second_region_end))
} else {
None
};
Ok((first_ram_range, second_ram_range))
}
fn configure_pvh(
guest_mem: &GuestMemoryMmap,
cmdline_addr: GuestAddress,
initramfs: &Option<InitramfsConfig>,
rsdp_addr: Option<GuestAddress>,
sgx_epc_region: Option<SgxEpcRegion>,
) -> super::Result<()> {
const XEN_HVM_START_MAGIC_VALUE: u32 = 0x336ec578;
let mut start_info = hvm_start_info {
magic: XEN_HVM_START_MAGIC_VALUE,
version: 1, // pvh has version 1
nr_modules: 0,
cmdline_paddr: cmdline_addr.raw_value(),
memmap_paddr: layout::MEMMAP_START.raw_value(),
..Default::default()
};
if let Some(rsdp_addr) = rsdp_addr {
start_info.rsdp_paddr = rsdp_addr.0;
}
if let Some(initramfs_config) = initramfs {
// The initramfs has been written to guest memory already, here we just need to
// create the module structure that describes it.
let ramdisk_mod = hvm_modlist_entry {
paddr: initramfs_config.address.raw_value(),
size: initramfs_config.size as u64,
..Default::default()
};
start_info.nr_modules += 1;
start_info.modlist_paddr = layout::MODLIST_START.raw_value();
// Write the modlist struct to guest memory.
guest_mem
.write_obj(ramdisk_mod, layout::MODLIST_START)
.map_err(super::Error::ModlistSetup)?;
}
// Vector to hold the memory maps which needs to be written to guest memory
// at MEMMAP_START after all of the mappings are recorded.
let mut memmap: Vec<hvm_memmap_table_entry> = Vec::new();
// Create the memory map entries.
add_memmap_entry(&mut memmap, 0, layout::EBDA_START.raw_value(), E820_RAM);
// Get usable physical memory ranges
let (first_ram_range, second_ram_range) = generate_ram_ranges(guest_mem)?;
// 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!( info!(
"create_memmap_entry, start: 0x{:08x}, end: 0x{:08x}", "create_memmap_entry, start: 0x{:08x}, end: 0x{:08x}",
second_ram_range.0, second_ram_range.1 ram_64bit_start, second_region_end
); );
add_memmap_entry( add_memmap_entry(
&mut memmap, &mut memmap,
second_ram_range.0, ram_64bit_start,
second_ram_range.1 - second_ram_range.0, second_region_end - ram_64bit_start,
E820_RAM, E820_RAM,
); );
} }
@@ -1128,7 +1086,7 @@ fn configure_pvh(
); );
} }
start_info.memmap_entries = memmap.len() as u32; start_info.0.memmap_entries = memmap.len() as u32;
// Copy the vector with the memmap table to the MEMMAP_START address // Copy the vector with the memmap table to the MEMMAP_START address
// which is already saved in the memmap_paddr field of hvm_start_info struct. // which is already saved in the memmap_paddr field of hvm_start_info struct.
@@ -1137,14 +1095,17 @@ fn configure_pvh(
guest_mem guest_mem
.checked_offset( .checked_offset(
memmap_start_addr, memmap_start_addr,
mem::size_of::<hvm_memmap_table_entry>() * start_info.memmap_entries as usize, mem::size_of::<hvm_memmap_table_entry>() * start_info.0.memmap_entries as usize,
) )
.ok_or(super::Error::MemmapTablePastRamEnd)?; .ok_or(super::Error::MemmapTablePastRamEnd)?;
// For every entry in the memmap vector, write it to guest memory. // For every entry in the memmap vector, create a MemmapTableEntryWrapper
// and write it to guest memory.
for memmap_entry in memmap { for memmap_entry in memmap {
let map_entry_wrapper: MemmapTableEntryWrapper = MemmapTableEntryWrapper(memmap_entry);
guest_mem guest_mem
.write_obj(memmap_entry, memmap_start_addr) .write_obj(map_entry_wrapper, memmap_start_addr)
.map_err(|_| super::Error::MemmapTableSetup)?; .map_err(|_| super::Error::MemmapTableSetup)?;
memmap_start_addr = memmap_start_addr =
memmap_start_addr.unchecked_add(mem::size_of::<hvm_memmap_table_entry>() as u64); memmap_start_addr.unchecked_add(mem::size_of::<hvm_memmap_table_entry>() as u64);
@@ -1230,24 +1191,10 @@ fn update_cpuid_topology(
cpu_vendor: CpuVendor, cpu_vendor: CpuVendor,
id: u8, id: u8,
) { ) {
let x2apic_id = get_x2apic_id(
id as u32,
Some((threads_per_core, cores_per_die, dies_per_package)),
);
let thread_width = 8 - (threads_per_core - 1).leading_zeros(); let thread_width = 8 - (threads_per_core - 1).leading_zeros();
let core_width = (8 - (cores_per_die - 1).leading_zeros()) + thread_width; let core_width = (8 - (cores_per_die - 1).leading_zeros()) + thread_width;
let die_width = (8 - (dies_per_package - 1).leading_zeros()) + core_width; let die_width = (8 - (dies_per_package - 1).leading_zeros()) + core_width;
let mut cpu_ebx = CpuidPatch::get_cpuid_reg(cpuid, 0x1, None, CpuidReg::EBX).unwrap_or(0);
cpu_ebx |= ((dies_per_package as u32) * (cores_per_die as u32) * (threads_per_core as u32))
& 0xff << 16;
CpuidPatch::set_cpuid_reg(cpuid, 0x1, None, CpuidReg::EBX, cpu_ebx);
let mut cpu_edx = CpuidPatch::get_cpuid_reg(cpuid, 0x1, None, CpuidReg::EDX).unwrap_or(0);
cpu_edx |= 1 << 28;
CpuidPatch::set_cpuid_reg(cpuid, 0x1, None, CpuidReg::EDX, cpu_edx);
// CPU Topology leaf 0xb // CPU Topology leaf 0xb
CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(0), CpuidReg::EAX, thread_width); CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(0), CpuidReg::EAX, thread_width);
CpuidPatch::set_cpuid_reg( CpuidPatch::set_cpuid_reg(
@@ -1306,7 +1253,7 @@ fn update_cpuid_topology(
0x8000_001e, 0x8000_001e,
Some(0), Some(0),
CpuidReg::EBX, CpuidReg::EBX,
((threads_per_core as u32 - 1) << 8) | (x2apic_id & 0xff), ((threads_per_core as u32 - 1) << 8) | (id as u32 & 0xff),
); );
CpuidPatch::set_cpuid_reg( CpuidPatch::set_cpuid_reg(
cpuid, cpuid,
@@ -1317,21 +1264,21 @@ fn update_cpuid_topology(
); );
CpuidPatch::set_cpuid_reg(cpuid, 0x8000_001e, Some(0), CpuidReg::EDX, 0); CpuidPatch::set_cpuid_reg(cpuid, 0x8000_001e, Some(0), CpuidReg::EDX, 0);
if cores_per_die * threads_per_core > 1 { if cores_per_die * threads_per_core > 1 {
let ecx =
CpuidPatch::get_cpuid_reg(cpuid, 0x8000_0001, Some(0), CpuidReg::ECX).unwrap_or(0);
CpuidPatch::set_cpuid_reg( CpuidPatch::set_cpuid_reg(
cpuid, cpuid,
0x8000_0001, 0x8000_0001,
Some(0), Some(0),
CpuidReg::ECX, CpuidReg::ECX,
ecx | (1u32 << 1) | (1u32 << 22), (1u32 << 1) | (1u32 << 22),
); );
CpuidPatch::set_cpuid_reg( CpuidPatch::set_cpuid_reg(
cpuid, cpuid,
0x0000_0001, 0x0000_0001,
Some(0), Some(0),
CpuidReg::EBX, CpuidReg::EBX,
(x2apic_id << 24) | (8 << 8) | (((cores_per_die * threads_per_core) as u32) << 16), ((id as u32) << 24)
| (8 << 8)
| (((cores_per_die * threads_per_core) as u32) << 16),
); );
let cpuid_patches = vec![ let cpuid_patches = vec![
// Patch tsc deadline timer bit // Patch tsc deadline timer bit
@@ -1436,7 +1383,6 @@ mod tests {
None, None,
None, None,
None, None,
None,
); );
assert!(config_err.is_err()); assert!(config_err.is_err());
@@ -1459,7 +1405,6 @@ mod tests {
None, None,
None, None,
None, None,
None,
) )
.unwrap(); .unwrap();
@@ -1487,7 +1432,6 @@ mod tests {
None, None,
None, None,
None, None,
None,
) )
.unwrap(); .unwrap();
@@ -1501,7 +1445,6 @@ mod tests {
None, None,
None, None,
None, None,
None,
) )
.unwrap(); .unwrap();
} }
@@ -1530,25 +1473,4 @@ mod tests {
assert_eq!(format!("{memmap:?}"), format!("{expected_memmap:?}")); assert_eq!(format!("{memmap:?}"), format!("{expected_memmap:?}"));
} }
#[test]
fn test_get_x2apic_id() {
let x2apic_id = get_x2apic_id(0, Some((2, 3, 1)));
assert_eq!(x2apic_id, 0);
let x2apic_id = get_x2apic_id(1, Some((2, 3, 1)));
assert_eq!(x2apic_id, 1);
let x2apic_id = get_x2apic_id(2, Some((2, 3, 1)));
assert_eq!(x2apic_id, 2);
let x2apic_id = get_x2apic_id(6, Some((2, 3, 1)));
assert_eq!(x2apic_id, 8);
let x2apic_id = get_x2apic_id(7, Some((2, 3, 1)));
assert_eq!(x2apic_id, 9);
let x2apic_id = get_x2apic_id(8, Some((2, 3, 1)));
assert_eq!(x2apic_id, 10);
}
} }

View File

@@ -6,9 +6,10 @@
// found in the LICENSE-BSD-3-Clause file. // found in the LICENSE-BSD-3-Clause file.
use crate::layout::{APIC_START, HIGH_RAM_START, IOAPIC_START}; use crate::layout::{APIC_START, HIGH_RAM_START, IOAPIC_START};
use crate::x86_64::{get_x2apic_id, mpspec}; use crate::x86_64::mpspec;
use crate::GuestMemoryMmap; use crate::GuestMemoryMmap;
use libc::c_char; use libc::c_char;
use std::io;
use std::mem; use std::mem;
use std::result; use std::result;
use std::slice; use std::slice;
@@ -125,18 +126,9 @@ fn compute_mp_size(num_cpus: u8) -> usize {
} }
/// Performs setup of the MP table for the given `num_cpus`. /// Performs setup of the MP table for the given `num_cpus`.
pub fn setup_mptable( pub fn setup_mptable(offset: GuestAddress, mem: &GuestMemoryMmap, num_cpus: u8) -> Result<()> {
offset: GuestAddress, if num_cpus as u32 > MAX_SUPPORTED_CPUS {
mem: &GuestMemoryMmap, return Err(Error::TooManyCpus);
num_cpus: u8,
topology: Option<(u8, u8, u8)>,
) -> Result<()> {
if num_cpus > 0 {
let cpu_id_max = num_cpus - 1;
let x2apic_id_max = get_x2apic_id(cpu_id_max.into(), topology);
if x2apic_id_max >= MAX_SUPPORTED_CPUS {
return Err(Error::TooManyCpus);
}
} }
// Used to keep track of the next base pointer into the MP table. // Used to keep track of the next base pointer into the MP table.
@@ -150,7 +142,7 @@ pub fn setup_mptable(
} }
let mut checksum: u8 = 0; let mut checksum: u8 = 0;
let ioapicid: u8 = MAX_SUPPORTED_CPUS as u8 + 1; let ioapicid: u8 = num_cpus + 1;
// The checked_add here ensures the all of the following base_mp.unchecked_add's will be without // The checked_add here ensures the all of the following base_mp.unchecked_add's will be without
// overflow. // overflow.
@@ -162,7 +154,7 @@ pub fn setup_mptable(
return Err(Error::AddressOverflow); return Err(Error::AddressOverflow);
} }
mem.read_exact_volatile_from(base_mp, &mut vec![0; mp_size].as_slice(), mp_size) mem.read_exact_from(base_mp, &mut io::repeat(0), mp_size)
.map_err(Error::Clear)?; .map_err(Error::Clear)?;
{ {
@@ -188,7 +180,7 @@ pub fn setup_mptable(
for cpu_id in 0..num_cpus { for cpu_id in 0..num_cpus {
let mut mpc_cpu = MpcCpuWrapper(mpspec::mpc_cpu::default()); let mut mpc_cpu = MpcCpuWrapper(mpspec::mpc_cpu::default());
mpc_cpu.0.type_ = mpspec::MP_PROCESSOR as u8; mpc_cpu.0.type_ = mpspec::MP_PROCESSOR as u8;
mpc_cpu.0.apicid = get_x2apic_id(cpu_id as u32, topology) as u8; mpc_cpu.0.apicid = cpu_id;
mpc_cpu.0.apicver = APIC_VERSION; mpc_cpu.0.apicver = APIC_VERSION;
mpc_cpu.0.cpuflag = mpspec::CPU_ENABLED as u8 mpc_cpu.0.cpuflag = mpspec::CPU_ENABLED as u8
| if cpu_id == 0 { | if cpu_id == 0 {
@@ -299,10 +291,7 @@ pub fn setup_mptable(
mod tests { mod tests {
use super::*; use super::*;
use crate::layout::MPTABLE_START; use crate::layout::MPTABLE_START;
use vm_memory::{ use vm_memory::{GuestAddress, GuestUsize};
bitmap::BitmapSlice, GuestAddress, GuestUsize, VolatileMemoryError, VolatileSlice,
WriteVolatile,
};
fn table_entry_size(type_: u8) -> usize { fn table_entry_size(type_: u8) -> usize {
match type_ as u32 { match type_ as u32 {
@@ -321,7 +310,7 @@ mod tests {
let mem = let mem =
GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus))]).unwrap(); GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus))]).unwrap();
setup_mptable(MPTABLE_START, &mem, num_cpus, None).unwrap(); setup_mptable(MPTABLE_START, &mem, num_cpus).unwrap();
} }
#[test] #[test]
@@ -330,7 +319,7 @@ mod tests {
let mem = GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus) - 1)]) let mem = GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus) - 1)])
.unwrap(); .unwrap();
assert!(setup_mptable(MPTABLE_START, &mem, num_cpus, None).is_err()); assert!(setup_mptable(MPTABLE_START, &mem, num_cpus).is_err());
} }
#[test] #[test]
@@ -339,7 +328,7 @@ mod tests {
let mem = let mem =
GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus))]).unwrap(); GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus))]).unwrap();
setup_mptable(MPTABLE_START, &mem, num_cpus, None).unwrap(); setup_mptable(MPTABLE_START, &mem, num_cpus).unwrap();
let mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap(); let mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap();
@@ -355,31 +344,27 @@ mod tests {
let mem = let mem =
GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus))]).unwrap(); GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(num_cpus))]).unwrap();
setup_mptable(MPTABLE_START, &mem, num_cpus, None).unwrap(); setup_mptable(MPTABLE_START, &mem, num_cpus).unwrap();
let mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap(); let mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap();
let mpc_offset = GuestAddress(mpf_intel.0.physptr as GuestUsize); let mpc_offset = GuestAddress(mpf_intel.0.physptr as GuestUsize);
let mpc_table: MpcTableWrapper = mem.read_obj(mpc_offset).unwrap(); let mpc_table: MpcTableWrapper = mem.read_obj(mpc_offset).unwrap();
struct Sum(u8); struct Sum(u8);
impl WriteVolatile for Sum { impl io::Write for Sum {
fn write_volatile<B: BitmapSlice>( fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
&mut self, for v in buf.iter() {
buf: &VolatileSlice<B>,
) -> result::Result<usize, VolatileMemoryError> {
let mut tmp = vec![0u8; buf.len()];
tmp.write_all_volatile(buf)?;
for v in tmp.iter() {
self.0 = self.0.wrapping_add(*v); self.0 = self.0.wrapping_add(*v);
} }
Ok(buf.len()) Ok(buf.len())
} }
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
} }
let mut sum = Sum(0); let mut sum = Sum(0);
mem.write_volatile_to(mpc_offset, &mut sum, mpc_table.0.length as usize) mem.write_to(mpc_offset, &mut sum, mpc_table.0.length as usize)
.unwrap(); .unwrap();
assert_eq!(sum.0, 0); assert_eq!(sum.0, 0);
} }
@@ -393,7 +378,7 @@ mod tests {
.unwrap(); .unwrap();
for i in 0..MAX_SUPPORTED_CPUS as u8 { for i in 0..MAX_SUPPORTED_CPUS as u8 {
setup_mptable(MPTABLE_START, &mem, i, None).unwrap(); setup_mptable(MPTABLE_START, &mem, i).unwrap();
let mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap(); let mpf_intel: MpfIntelWrapper = mem.read_obj(MPTABLE_START).unwrap();
let mpc_offset = GuestAddress(mpf_intel.0.physptr as GuestUsize); let mpc_offset = GuestAddress(mpf_intel.0.physptr as GuestUsize);
@@ -426,7 +411,7 @@ mod tests {
let mem = let mem =
GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(cpus as u8))]).unwrap(); GuestMemoryMmap::from_ranges(&[(MPTABLE_START, compute_mp_size(cpus as u8))]).unwrap();
let result = setup_mptable(MPTABLE_START, &mem, cpus as u8, None); let result = setup_mptable(MPTABLE_START, &mem, cpus as u8);
assert!(result.is_err()); assert!(result.is_err());
} }
} }

View File

@@ -10,18 +10,18 @@ io_uring = ["dep:io-uring"]
[dependencies] [dependencies]
byteorder = "1.4.3" byteorder = "1.4.3"
crc-any = "2.4.4" crc32c = "0.6.4"
io-uring = { version = "0.6.2", optional = true } io-uring = { version = "0.6.1", optional = true }
libc = "0.2.147" libc = "0.2.147"
log = "0.4.20" log = "0.4.17"
remain = "0.2.11" remain = "0.2.11"
smallvec = "1.11.0" smallvec = "1.11.0"
thiserror = "1.0.40" thiserror = "1.0.40"
uuid = { version = "1.3.4", features = ["v4"] } uuid = { version = "1.3.4", features = ["v4"] }
versionize = "0.2.0" versionize = "0.1.10"
versionize_derive = "0.1.6" versionize_derive = "0.1.4"
virtio-bindings = { version = "0.2.0", features = ["virtio-v5_0_0"] } virtio-bindings = { version = "0.2.0", features = ["virtio-v5_0_0"] }
virtio-queue = "0.11.0" virtio-queue = "0.9.0"
vm-memory = { version = "0.14.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] } vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-virtio = { path = "../vm-virtio" } vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = "0.12.1" vmm-sys-util = "0.11.0"

View File

@@ -143,14 +143,10 @@ pub enum ExecuteError {
Flush(io::Error), Flush(io::Error),
#[error("Failed to read: {0}")] #[error("Failed to read: {0}")]
Read(GuestMemoryError), Read(GuestMemoryError),
#[error("Failed to read_exact: {0}")]
ReadExact(io::Error),
#[error("Failed to seek: {0}")] #[error("Failed to seek: {0}")]
Seek(io::Error), Seek(io::Error),
#[error("Failed to write: {0}")] #[error("Failed to write: {0}")]
Write(GuestMemoryError), Write(GuestMemoryError),
#[error("Failed to write_all: {0}")]
WriteAll(io::Error),
#[error("Unsupported request: {0}")] #[error("Unsupported request: {0}")]
Unsupported(u32), Unsupported(u32),
#[error("Failed to submit io uring: {0}")] #[error("Failed to submit io uring: {0}")]
@@ -173,10 +169,8 @@ impl ExecuteError {
ExecuteError::BadRequest(_) => VIRTIO_BLK_S_IOERR, ExecuteError::BadRequest(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Flush(_) => VIRTIO_BLK_S_IOERR, ExecuteError::Flush(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Read(_) => VIRTIO_BLK_S_IOERR, ExecuteError::Read(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::ReadExact(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Seek(_) => VIRTIO_BLK_S_IOERR, ExecuteError::Seek(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Write(_) => VIRTIO_BLK_S_IOERR, ExecuteError::Write(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::WriteAll(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::Unsupported(_) => VIRTIO_BLK_S_UNSUPP, ExecuteError::Unsupported(_) => VIRTIO_BLK_S_UNSUPP,
ExecuteError::SubmitIoUring(_) => VIRTIO_BLK_S_IOERR, ExecuteError::SubmitIoUring(_) => VIRTIO_BLK_S_IOERR,
ExecuteError::GetHostAddress(_) => VIRTIO_BLK_S_IOERR, ExecuteError::GetHostAddress(_) => VIRTIO_BLK_S_IOERR,
@@ -357,21 +351,13 @@ impl Request {
match self.request_type { match self.request_type {
RequestType::In => { RequestType::In => {
let mut buf = vec![0u8; *data_len as usize]; mem.read_exact_from(*data_addr, disk, *data_len as usize)
disk.read_exact(&mut buf).map_err(ExecuteError::ReadExact)?; .map_err(ExecuteError::Read)?;
mem.read_exact_volatile_from(
*data_addr,
&mut buf.as_slice(),
*data_len as usize,
)
.map_err(ExecuteError::Read)?;
len += data_len; len += data_len;
} }
RequestType::Out => { RequestType::Out => {
let mut buf: Vec<u8> = Vec::new(); mem.write_all_to(*data_addr, disk, *data_len as usize)
mem.write_all_volatile_to(*data_addr, &mut buf, *data_len as usize)
.map_err(ExecuteError::Write)?; .map_err(ExecuteError::Write)?;
disk.write_all(&buf).map_err(ExecuteError::WriteAll)?;
if !self.writeback { if !self.writeback {
disk.flush().map_err(ExecuteError::Flush)?; disk.flush().map_err(ExecuteError::Flush)?;
} }

View File

@@ -136,7 +136,7 @@ impl<T: Cacheable> CacheMap<T> {
mod tests { mod tests {
use super::*; use super::*;
struct NumCache(()); struct NumCache(pub u64);
impl Cacheable for NumCache { impl Cacheable for NumCache {
fn dirty(&self) -> bool { fn dirty(&self) -> bool {
true true
@@ -148,28 +148,28 @@ mod tests {
let mut cache = CacheMap::<NumCache>::new(3); let mut cache = CacheMap::<NumCache>::new(3);
let mut evicted = None; let mut evicted = None;
cache cache
.insert(0, NumCache(()), |index, _| { .insert(0, NumCache(5), |index, _| {
evicted = Some(index); evicted = Some(index);
Ok(()) Ok(())
}) })
.unwrap(); .unwrap();
assert_eq!(evicted, None); assert_eq!(evicted, None);
cache cache
.insert(1, NumCache(()), |index, _| { .insert(1, NumCache(6), |index, _| {
evicted = Some(index); evicted = Some(index);
Ok(()) Ok(())
}) })
.unwrap(); .unwrap();
assert_eq!(evicted, None); assert_eq!(evicted, None);
cache cache
.insert(2, NumCache(()), |index, _| { .insert(2, NumCache(7), |index, _| {
evicted = Some(index); evicted = Some(index);
Ok(()) Ok(())
}) })
.unwrap(); .unwrap();
assert_eq!(evicted, None); assert_eq!(evicted, None);
cache cache
.insert(3, NumCache(()), |index, _| { .insert(3, NumCache(8), |index, _| {
evicted = Some(index); evicted = Some(index);
Ok(()) Ok(())
}) })

View File

@@ -192,9 +192,7 @@ impl Header {
}; };
new_header.get_header_as_buffer(&mut buffer); new_header.get_header_as_buffer(&mut buffer);
let mut crc = crc_any::CRC::crc32c(); new_header.checksum = crc32c::crc32c(&buffer);
crc.digest(&buffer);
new_header.checksum = crc.get_crc() as u32;
new_header.get_header_as_buffer(&mut buffer); new_header.get_header_as_buffer(&mut buffer);
f.seek(SeekFrom::Start(start)) f.seek(SeekFrom::Start(start))
@@ -482,10 +480,7 @@ pub fn calculate_checksum(buffer: &mut [u8], csum_offset: usize) -> Result<u32>
// Zero the checksum in the buffer // Zero the checksum in the buffer
LittleEndian::write_u32(csum_buf, 0); LittleEndian::write_u32(csum_buf, 0);
// Calculate the checksum on the resulting buffer // Calculate the checksum on the resulting buffer
let mut crc = crc_any::CRC::crc32c(); let new_csum = crc32c::crc32c(buffer);
crc.digest(&buffer);
let new_csum = crc.get_crc() as u32;
// Put back the original checksum in the buffer // Put back the original checksum in the buffer
LittleEndian::write_u32(&mut buffer[csum_offset..csum_offset + 4], orig_csum); LittleEndian::write_u32(&mut buffer[csum_offset..csum_offset + 4], orig_csum);

View File

@@ -13,17 +13,17 @@ byteorder = "1.4.3"
event_monitor = { path = "../event_monitor" } event_monitor = { path = "../event_monitor" }
hypervisor = { path = "../hypervisor" } hypervisor = { path = "../hypervisor" }
libc = "0.2.147" libc = "0.2.147"
log = "0.4.20" log = "0.4.17"
pci = { path = "../pci" } pci = { path = "../pci" }
thiserror = "1.0.40" thiserror = "1.0.40"
tpm = { path = "../tpm" } tpm = { path = "../tpm" }
versionize = "0.2.0" versionize = "0.1.10"
versionize_derive = "0.1.6" versionize_derive = "0.1.4"
vm-allocator = { path = "../vm-allocator" } vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" } vm-device = { path = "../vm-device" }
vm-memory = "0.14.0" vm-memory = "0.12.2"
vm-migration = { path = "../vm-migration" } vm-migration = { path = "../vm-migration" }
vmm-sys-util = "0.12.1" vmm-sys-util = "0.11.0"
[target.'cfg(target_arch = "aarch64")'.dependencies] [target.'cfg(target_arch = "aarch64")'.dependencies]
arch = { path = "../arch" } arch = { path = "../arch" }

View File

@@ -181,9 +181,8 @@ impl PciDevice for PvPanicDevice {
fn allocate_bars( fn allocate_bars(
&mut self, &mut self,
_allocator: &Arc<Mutex<SystemAllocator>>, allocator: &Arc<Mutex<SystemAllocator>>,
mmio32_allocator: &mut AddressAllocator, _mmio_allocator: &mut AddressAllocator,
_mmio64_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>, resources: Option<Vec<Resource>>,
) -> std::result::Result<Vec<PciBarConfiguration>, PciDeviceError> { ) -> std::result::Result<Vec<PciBarConfiguration>, PciDeviceError> {
let mut bars = Vec::new(); let mut bars = Vec::new();
@@ -191,8 +190,10 @@ impl PciDevice for PvPanicDevice {
let bar_id = 0; let bar_id = 0;
let region_size = PVPANIC_DEVICE_MMIO_SIZE; let region_size = PVPANIC_DEVICE_MMIO_SIZE;
let restoring = resources.is_some(); let restoring = resources.is_some();
let bar_addr = mmio32_allocator let bar_addr = allocator
.allocate(None, region_size, Some(PVPANIC_DEVICE_MMIO_ALIGNMENT)) .lock()
.unwrap()
.allocate_mmio_hole_addresses(None, region_size, Some(PVPANIC_DEVICE_MMIO_ALIGNMENT))
.ok_or(PciDeviceError::IoAllocationFailed(region_size))?; .ok_or(PciDeviceError::IoAllocationFailed(region_size))?;
let bar = PciBarConfiguration::default() let bar = PciBarConfiguration::default()
@@ -217,12 +218,11 @@ impl PciDevice for PvPanicDevice {
fn free_bars( fn free_bars(
&mut self, &mut self,
_allocator: &mut SystemAllocator, allocator: &mut SystemAllocator,
mmio32_allocator: &mut AddressAllocator, _mmio_allocator: &mut AddressAllocator,
_mmio64_allocator: &mut AddressAllocator,
) -> std::result::Result<(), PciDeviceError> { ) -> std::result::Result<(), PciDeviceError> {
for bar in self.bar_regions.drain(..) { for bar in self.bar_regions.drain(..) {
mmio32_allocator.free(GuestAddress(bar.addr()), bar.size()); allocator.free_mmio_hole_addresses(GuestAddress(bar.addr()), bar.size());
} }
Ok(()) Ok(())

View File

@@ -36,5 +36,3 @@ You can run a SEV-SNP VM using the following command:
--memory size=1G \ --memory size=1G \
--disk path=ubuntu.img --disk path=ubuntu.img
``` ```
For more information related to Microsoft Hypervisor please see [mshv.md](mshv.md)

View File

@@ -170,7 +170,7 @@ We usually start from one of the custom cloud image we have previously created
but we can use a stock cloud image as well. but we can use a stock cloud image as well.
```bash ```bash
wget https://ch-images.azureedge.net/jammy-server-cloudimg-amd64-custom-20230119-0.raw wget https://cloud-hypervisor.azureedge.net/jammy-server-cloudimg-amd64-custom-20230119-0.raw
mv jammy-server-cloudimg-amd64-custom-20230119-0.raw jammy-server-cloudimg-amd64-nvidia.raw mv jammy-server-cloudimg-amd64-custom-20230119-0.raw jammy-server-cloudimg-amd64-nvidia.raw
``` ```

View File

@@ -1,48 +0,0 @@
# Microsoft Hypervisor
The Microsoft Hypervisor is a Type 1 hypervisor which runs on x64 and ARM64 architectures. As the foundation of the Hyper-V virtualization stack, it runs millions of Linux and Windows guests in Azure and on-premises deployments. It supports nested virtualization, and security features like AMD's SEV-SNP. It also supports various features in Windows such as [Device guard and confidential guard](https://techcommunity.microsoft.com/t5/iis-support-blog/windows-10-device-guard-and-credential-guard-demystified/ba-p/376419), and [WSL2](https://docs.microsoft.com/en-us/windows/wsl/wsl2-faq)
Since 2020, Microsoft has been releasing open-source components to support Linux running as root partition on the Microsoft Hypervisor.
1. Kernel patches to support Linux booting as root partition
2. A Linux kernel driver exposing an IOCTL interface for managing guest partitions, via a device node - /dev/mshv
3. Rust bindings and IOCTL wrappers
4. IGVM related crates
## Components
The following components are related to MSHV support with Cloud-Hypervisor:
* [igvm-crates](https://github.com/microsoft/igvm) : Parsing IGVM file
* [mshv-crates](https://github.com/rust-vmm/mshv) : Rust crates to interact with kernel module (/dev/mshv)
* [igvm-tooling](https://github.com/microsoft/igvm-tooling) : Tool to generate IGVM file
## IGVM
Independent Guest Virtual Machine (IGVM) file format.The format specification can be found in the igvm_defs crate, with a Rust implementation of the binary format in the igvm crate.
The IGVM file format is designed to encapsulate all information required to launch a virtual machine on any given virtualization stack, with support for different isolation technologies such as AMD SEV-SNP and Intel TDX.
At a conceptual level, this file format is a set of commands created by the tool that generated the file, used by the loader to construct the initial guest state. The file format also contains measurement information that the underlying platform will use to confirm that the file was loaded correctly and signed by the appropriate authorities.
Cloud Hypervisor can be built using igvm feature flag along with mshv and/or sev-snp. IGVM only works with MSHV.
## SEV-SNP
AMD's [Secure Encrypted Virtualization (SEV)](https://www.amd.com/en/developer/sev.html) and extensions such as Secure Nested Paging (SEV-SNP) encrypt memory and restrict access to a guest VM's memory and registers, securing it against a compromised hypervisor or VMM. They utilize the Platform Security Processor (PSP) to store keys and encrypt/decrypt the data. Microsoft has been continuously adding/improving support for SEV-SNP on Microsoft Hyper-V. Cloud-Hypervisor can be built with the sev_snp feature including mshv and igvm feature.
## Use Cases
Cloud Hypervisor can be built to run on an MSHV root partition by enabling the mshv feature, e.g.:
```cargo build --locked --all --all-targets --no-default-features --tests --examples --features mshv```
Cloud Hypervisor on MSHV can boot Linux guests using an IGVM file. IGVM feature depends on mshv for running legacy VMs.e.g.:
```cargo build --locked --all --all-targets --no-default-features --tests --examples --features igvm```
For running confidential VMs on mshv, you will only need to enable sev_snp, it requires and enables mshv and igvm automatically, eg.:
```cargo build --locked --all --all-targets --no-default-features --tests --examples --features sev_snp```

View File

@@ -49,7 +49,7 @@ qemu-system-x86_64 \
-m 4G \ -m 4G \
-bios ./$OVMF_DIR/OVMF_CODE.fd \ -bios ./$OVMF_DIR/OVMF_CODE.fd \
-cdrom ./$WIN_ISO_FILE \ -cdrom ./$WIN_ISO_FILE \
-drive file=./$VIRTIO_ISO_FILE,index=0,media=cdrom \ -drive file=./$VIRTIO_ISO_FILE,index=0,media=cdrom
-drive if=none,id=root,file=./$IMG_FILE \ -drive if=none,id=root,file=./$IMG_FILE \
-device virtio-blk-pci,drive=root,disable-legacy=on \ -device virtio-blk-pci,drive=root,disable-legacy=on \
-device virtio-net-pci,netdev=mynet0,disable-legacy=on \ -device virtio-net-pci,netdev=mynet0,disable-legacy=on \

284
fuzz/Cargo.lock generated
View File

@@ -12,9 +12,9 @@ dependencies = [
[[package]] [[package]]
name = "anstream" name = "anstream"
version = "0.6.11" version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6e2e1ebcb11de5c03c67de28a7df593d32191b44939c482e97702baaaa6ab6a5" checksum = "2ab91ebe16eb252986481c5b62f6098f3b698a45e34b5b98200cf20dd2484a44"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"anstyle-parse", "anstyle-parse",
@@ -32,27 +32,27 @@ checksum = "7079075b41f533b8c61d2a4d073c4676e1f8b249ff94a393b0595db304e0dd87"
[[package]] [[package]]
name = "anstyle-parse" name = "anstyle-parse"
version = "0.2.3" version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c75ac65da39e5fe5ab759307499ddad880d724eed2f6ce5b5e8a26f4f387928c" checksum = "317b9a89c1868f5ea6ff1d9539a69f45dffc21ce321ac1fd1160dfa48c8e2140"
dependencies = [ dependencies = [
"utf8parse", "utf8parse",
] ]
[[package]] [[package]]
name = "anstyle-query" name = "anstyle-query"
version = "1.0.2" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e28923312444cdd728e4738b3f9c9cac739500909bb3d3c94b43551b16517648" checksum = "5ca11d4be1bab0c8bc8734a9aa7bf4ee8316d462a08c6ac5052f888fef5b494b"
dependencies = [ dependencies = [
"windows-sys", "windows-sys",
] ]
[[package]] [[package]]
name = "anstyle-wincon" name = "anstyle-wincon"
version = "3.0.2" version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cd54b81ec8d6180e24654d0b371ad22fc3dd083b6ff8ba325b72e00c87660a7" checksum = "f0699d10d2f4d628a98ee7b57b289abbc98ff3bad977cb3152709d4bf2330628"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"windows-sys", "windows-sys",
@@ -60,9 +60,9 @@ dependencies = [
[[package]] [[package]]
name = "anyhow" name = "anyhow"
version = "1.0.79" version = "1.0.75"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "080e9890a082662b09c1ad45f567faeeb47f22b5fb23895fbe1e651e718e25ca" checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
[[package]] [[package]]
name = "api_client" name = "api_client"
@@ -73,9 +73,9 @@ dependencies = [
[[package]] [[package]]
name = "arbitrary" name = "arbitrary"
version = "1.3.2" version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" checksum = "a2e1373abdaa212b704512ec2bd8b26bd0b7d5c3f70117411a5d9a451383c859"
[[package]] [[package]]
name = "arc-swap" name = "arc-swap"
@@ -137,7 +137,7 @@ name = "block"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"crc-any", "crc32c",
"io-uring", "io-uring",
"libc", "libc",
"log", "log",
@@ -184,18 +184,18 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
[[package]] [[package]]
name = "clap" name = "clap"
version = "4.4.18" version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e578d6ec4194633722ccf9544794b71b1385c3c027efe0c55db226fc880865c" checksum = "ac495e00dcec98c83465d5ad66c5c4fabd652fd6686e7c6269b117e729a6f17b"
dependencies = [ dependencies = [
"clap_builder", "clap_builder",
] ]
[[package]] [[package]]
name = "clap_builder" name = "clap_builder"
version = "4.4.18" version = "4.4.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4df4df40ec50c46000231c914968278b1eb05098cf8f1b3a518a95030e71d1c7" checksum = "c77ed9a32a62e6ca27175d00d29d05ca32e396ea1eb5fb01d8256b669cec7663"
dependencies = [ dependencies = [
"anstream", "anstream",
"anstyle", "anstyle",
@@ -211,7 +211,7 @@ checksum = "702fc72eb24e5a1e48ce58027a675bc24edd52096d5397d4aea7c6dd9eca0bd1"
[[package]] [[package]]
name = "cloud-hypervisor" name = "cloud-hypervisor"
version = "37.0.0" version = "35.0.0"
dependencies = [ dependencies = [
"anyhow", "anyhow",
"api_client", "api_client",
@@ -252,7 +252,6 @@ dependencies = [
"virtio-queue", "virtio-queue",
"vm-device", "vm-device",
"vm-memory", "vm-memory",
"vm-migration",
"vm-virtio", "vm-virtio",
"vmm", "vmm",
"vmm-sys-util", "vmm-sys-util",
@@ -265,19 +264,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7"
[[package]] [[package]]
name = "crc-any" name = "crc32c"
version = "2.4.4" version = "0.6.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c01a5e1f881f6fb6099a7bdf949e946719fd4f1fefa56264890574febf0eb6d0" checksum = "d8f48d60e5b4d2c53d5c2b1d8a58c849a70ae5e5509b08a48d047e3b65714a74"
dependencies = [ dependencies = [
"debug-helper", "rustc_version",
] ]
[[package]] [[package]]
name = "crc64" name = "crc64"
version = "2.0.0" version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2707e3afba5e19b75d582d88bc79237418f2a2a2d673d01cf9b03633b46e98f3" checksum = "55626594feae15d266d52440b26ff77de0e22230cf0c113abe619084c1ddc910"
[[package]] [[package]]
name = "darling" name = "darling"
@@ -300,7 +299,7 @@ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"strsim", "strsim",
"syn 2.0.47", "syn 2.0.32",
] ]
[[package]] [[package]]
@@ -311,15 +310,9 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
dependencies = [ dependencies = [
"darling_core", "darling_core",
"quote", "quote",
"syn 2.0.47", "syn 2.0.32",
] ]
[[package]]
name = "debug-helper"
version = "0.3.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f578e8e2c440e7297e008bb5486a3a8a194775224bbc23729b0dbdfaeebf162e"
[[package]] [[package]]
name = "devices" name = "devices"
version = "0.1.0" version = "0.1.0"
@@ -393,21 +386,21 @@ checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]] [[package]]
name = "futures-core" name = "futures-core"
version = "0.3.30" version = "0.3.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dfc6580bb841c5a68e9ef15c77ccc837b40a7504914d52e47b8b0e9bbda25a1d" checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c"
[[package]] [[package]]
name = "futures-sink" name = "futures-sink"
version = "0.3.30" version = "0.3.28"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9fb8e00e87438d937621c1c6269e53f536c14d3fbd6a042bb24879e57d474fb5" checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e"
[[package]] [[package]]
name = "getrandom" name = "getrandom"
version = "0.2.11" version = "0.2.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe9006bed769170c11f845cf00c7c1e9092aeb3f268e007c3e760ac68008070f" checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"js-sys", "js-sys",
@@ -452,9 +445,9 @@ dependencies = [
[[package]] [[package]]
name = "itoa" name = "itoa"
version = "1.0.10" version = "1.0.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38"
[[package]] [[package]]
name = "jobserver" name = "jobserver"
@@ -467,17 +460,17 @@ dependencies = [
[[package]] [[package]]
name = "js-sys" name = "js-sys"
version = "0.3.66" version = "0.3.64"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cee9c64da59eae3b50095c18d3e74f8b73c0b86d2792824ff01bbce68ba229ca" checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a"
dependencies = [ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]] [[package]]
name = "kvm-bindings" name = "kvm-bindings"
version = "0.7.0" version = "0.6.0"
source = "git+https://github.com/cloud-hypervisor/kvm-bindings?branch=ch-live-upgrade-stable-37.x#f03fc575cdf20c3af9ca3d4d203f171943d95be4" source = "git+https://github.com/cloud-hypervisor/kvm-bindings?branch=ch-v0.6.0-tdx#7d9ffb47e5b9b1989577258800a0f57c93f1445f"
dependencies = [ dependencies = [
"serde", "serde",
"serde_derive", "serde_derive",
@@ -486,11 +479,10 @@ dependencies = [
[[package]] [[package]]
name = "kvm-ioctls" name = "kvm-ioctls"
version = "0.16.0" version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9002dff009755414f22b962ec6ae6980b07d6d8b06e5297b1062019d72bd6a8c" checksum = "b8f8dc9c1896e5f144ec5d07169bc29f39a047686d29585a91f30489abfaeb6b"
dependencies = [ dependencies = [
"bitflags 2.4.1",
"kvm-bindings", "kvm-bindings",
"libc", "libc",
"vmm-sys-util", "vmm-sys-util",
@@ -498,9 +490,9 @@ dependencies = [
[[package]] [[package]]
name = "libc" name = "libc"
version = "0.2.152" version = "0.2.149"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7" checksum = "a08173bc88b7955d1b3145aa561539096c421ac8debde8cbc3612ec635fee29b"
[[package]] [[package]]
name = "libfuzzer-sys" name = "libfuzzer-sys"
@@ -515,9 +507,9 @@ dependencies = [
[[package]] [[package]]
name = "linux-loader" name = "linux-loader"
version = "0.11.0" version = "0.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "eb68dd3452f25a8defaf0ae593509cff0c777683e4d8924f59ac7c5f89267a83" checksum = "1db6a725c8000971f83fa93ed7ee1b600e55a1471a2a653379d3c84f72effdcf"
dependencies = [ dependencies = [
"vm-memory", "vm-memory",
] ]
@@ -541,7 +533,7 @@ checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
[[package]] [[package]]
name = "micro_http" name = "micro_http"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/firecracker-microvm/micro-http?branch=main#e75dfa1eeea23b69caa7407bc2c3a76d7b7262fb" source = "git+https://github.com/firecracker-microvm/micro-http?branch=main#a4d632f2c5ea45712c0d2002dc909a63879e85c3"
dependencies = [ dependencies = [
"libc", "libc",
"vmm-sys-util", "vmm-sys-util",
@@ -586,9 +578,9 @@ dependencies = [
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.19.0" version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d"
[[package]] [[package]]
name = "option_parser" name = "option_parser"
@@ -634,23 +626,23 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.47", "syn 2.0.32",
] ]
[[package]] [[package]]
name = "proc-macro2" name = "proc-macro2"
version = "1.0.76" version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" checksum = "134c189feb4956b20f6f547d2cf727d4c0fe06722b20a0eec87ed445a97f92da"
dependencies = [ dependencies = [
"unicode-ident", "unicode-ident",
] ]
[[package]] [[package]]
name = "quote" name = "quote"
version = "1.0.35" version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
] ]
@@ -661,26 +653,34 @@ version = "0.1.0"
dependencies = [ dependencies = [
"libc", "libc",
"log", "log",
"thiserror",
"vmm-sys-util", "vmm-sys-util",
] ]
[[package]] [[package]]
name = "remain" name = "remain"
version = "0.2.12" version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1ad5e011230cad274d0532460c5ab69828ea47ae75681b42a841663efffaf794" checksum = "bce3a7139d2ee67d07538ee5dba997364fbc243e7e7143e96eb830c74bfaa082"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.47", "syn 2.0.32",
]
[[package]]
name = "rustc_version"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366"
dependencies = [
"semver",
] ]
[[package]] [[package]]
name = "ryu" name = "ryu"
version = "1.0.16" version = "1.0.15"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f98d2aa92eebf49b69786be48e4477826b256916e84a57ff2a4f21923b48eb4c" checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741"
[[package]] [[package]]
name = "scopeguard" name = "scopeguard"
@@ -698,30 +698,36 @@ dependencies = [
] ]
[[package]] [[package]]
name = "serde" name = "semver"
version = "1.0.195" version = "1.0.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" checksum = "836fa6a3e1e547f9a2c4040802ec865b5d85f4014efe00555d7090a3dcaa1090"
[[package]]
name = "serde"
version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8e422a44e74ad4001bdc8eede9a4570ab52f71190e9c076d14369f38b9200537"
dependencies = [ dependencies = [
"serde_derive", "serde_derive",
] ]
[[package]] [[package]]
name = "serde_derive" name = "serde_derive"
version = "1.0.195" version = "1.0.189"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" checksum = "1e48d1f918009ce3145511378cf68d613e3b3d9137d67272562080d68a2b32d5"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.47", "syn 2.0.32",
] ]
[[package]] [[package]]
name = "serde_json" name = "serde_json"
version = "1.0.111" version = "1.0.108"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "176e46fa42316f18edd598015a5166857fc835ec732f5215eac6b7bdbf0a84f4" checksum = "3d1c7e3eac408d115102c4c24ad393e0821bb3a5df4d506a80f85f7a742a526b"
dependencies = [ dependencies = [
"itoa", "itoa",
"ryu", "ryu",
@@ -747,7 +753,7 @@ dependencies = [
"darling", "darling",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.47", "syn 2.0.32",
] ]
[[package]] [[package]]
@@ -775,9 +781,9 @@ dependencies = [
[[package]] [[package]]
name = "smallvec" name = "smallvec"
version = "1.12.0" version = "1.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2593d31f82ead8df961d8bd23a64c2ccf2eb5dd34b0a34bfb4dd54011c72009e" checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a"
[[package]] [[package]]
name = "spin" name = "spin"
@@ -807,9 +813,9 @@ dependencies = [
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.47" version = "2.0.32"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1726efe18f42ae774cc644f330953a5e7b3c3003d3edcecf18850fe9d4dd9afb" checksum = "239814284fd6f1a4ffe4ca893952cdd93c224b6a1571c9a9eadd670295c0c9e2"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -818,22 +824,22 @@ dependencies = [
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "1.0.56" version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d54378c645627613241d077a3a79db965db602882668f9136ac42af9ecb730ad" checksum = "f9a7210f5c9a7156bb50aa36aed4c95afb51df0df00713949448cf9e97d382d2"
dependencies = [ dependencies = [
"thiserror-impl", "thiserror-impl",
] ]
[[package]] [[package]]
name = "thiserror-impl" name = "thiserror-impl"
version = "1.0.56" version = "1.0.50"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa0faa943b50f3db30a20aa7e265dbc66076993efed8463e8de414e5d06d3471" checksum = "266b2e40bc00e5a6c09c3584011e08b06f123c00362c92b975ba9843aaaa14b8"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.47", "syn 2.0.32",
] ]
[[package]] [[package]]
@@ -874,18 +880,18 @@ checksum = "711b9620af191e0cdc7468a8d14e709c3dcdb115b36f838e601583af800a370a"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.7.0" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f00cc9702ca12d3c81455259621e676d0f7251cec66a21e98fe2e9a37db93b2a" checksum = "88ad59a7560b41a70d191093a945f0b87bc1deeda46fb237479708a1d6b6cdfc"
dependencies = [ dependencies = [
"getrandom", "getrandom",
] ]
[[package]] [[package]]
name = "versionize" name = "versionize"
version = "0.2.0" version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62929d59c7f6730b7298fcb363760550f4db6e353fbac4076d447d0e82799d6d" checksum = "dca4b7062e7e6d685901e815c35f9671e059de97c1c0905eeff8592f3fff442f"
dependencies = [ dependencies = [
"bincode", "bincode",
"crc64", "crc64",
@@ -900,8 +906,8 @@ dependencies = [
[[package]] [[package]]
name = "versionize_derive" name = "versionize_derive"
version = "0.1.6" version = "0.1.4"
source = "git+https://github.com/cloud-hypervisor/versionize_derive?branch=ch-0.1.6#7906da996152e2d0ab08f5526440683bf3ca7834" source = "git+https://github.com/cloud-hypervisor/versionize_derive?branch=ch#e502b1d4aabab342386f0c53780d49f21a6a1df6"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
@@ -911,7 +917,7 @@ dependencies = [
[[package]] [[package]]
name = "vfio-bindings" name = "vfio-bindings"
version = "0.4.0" version = "0.4.0"
source = "git+https://github.com/rust-vmm/vfio?branch=main#0daff4d4c159e842cf18b8b90457a45032b2df5a" source = "git+https://github.com/rust-vmm/vfio?branch=main#847b0aa504ac6367efe42ba7e96a2d050737d4f0"
dependencies = [ dependencies = [
"vmm-sys-util", "vmm-sys-util",
] ]
@@ -919,7 +925,7 @@ dependencies = [
[[package]] [[package]]
name = "vfio-ioctls" name = "vfio-ioctls"
version = "0.2.0" version = "0.2.0"
source = "git+https://github.com/rust-vmm/vfio?branch=main#0daff4d4c159e842cf18b8b90457a45032b2df5a" source = "git+https://github.com/rust-vmm/vfio?branch=main#847b0aa504ac6367efe42ba7e96a2d050737d4f0"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"kvm-bindings", "kvm-bindings",
@@ -935,7 +941,7 @@ dependencies = [
[[package]] [[package]]
name = "vfio_user" name = "vfio_user"
version = "0.1.0" version = "0.1.0"
source = "git+https://github.com/rust-vmm/vfio-user?branch=main#a1f6e52829e069b6d698b2cfeecac742e4653186" source = "git+https://github.com/rust-vmm/vfio-user?branch=main#2d96b90a7279547356ad8f83aaa3115ad5497302"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"libc", "libc",
@@ -951,11 +957,11 @@ dependencies = [
[[package]] [[package]]
name = "vhost" name = "vhost"
version = "0.10.0" version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2b64e816d0d49769fbfaa1494eb77cc2a3ddc526ead05c7f922cb7d64106286f" checksum = "61957aeb36daf0b00b87fff9c10dd28a161bd35ab157553d340d183b3d8756e6"
dependencies = [ dependencies = [
"bitflags 2.4.1", "bitflags 1.3.2",
"libc", "libc",
"vm-memory", "vm-memory",
"vmm-sys-util", "vmm-sys-util",
@@ -963,9 +969,9 @@ dependencies = [
[[package]] [[package]]
name = "virtio-bindings" name = "virtio-bindings"
version = "0.2.2" version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "878bcb1b2812a10c30d53b0ed054999de3d98f25ece91fc173973f9c57aaae86" checksum = "c18d7b74098a946470ea265b5bacbbf877abc3373021388454de0d47735a5b98"
[[package]] [[package]]
name = "virtio-devices" name = "virtio-devices"
@@ -1003,9 +1009,9 @@ dependencies = [
[[package]] [[package]]
name = "virtio-queue" name = "virtio-queue"
version = "0.11.0" version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3f69a13d6610db9312acbb438b0390362af905d37634a2106be70c0f734986d" checksum = "35aca00da06841bd99162c381ec65893cace23ca0fb89254302cfe4bec4c300f"
dependencies = [ dependencies = [
"log", "log",
"virtio-bindings", "virtio-bindings",
@@ -1042,9 +1048,9 @@ source = "git+https://github.com/rust-vmm/vm-fdt?branch=main#c5a99ab71b130435927
[[package]] [[package]]
name = "vm-memory" name = "vm-memory"
version = "0.14.0" version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74ffc42216c32c35f858fa4bfdcd9b61017dfd691e0240268fdc85dbf59e5459" checksum = "9dc276f0d00c17b9aeb584da0f1e1c673df0d183cc2539e3636ec8cbc5eae99b"
dependencies = [ dependencies = [
"arc-swap", "arc-swap",
"libc", "libc",
@@ -1124,9 +1130,9 @@ dependencies = [
[[package]] [[package]]
name = "vmm-sys-util" name = "vmm-sys-util"
version = "0.12.1" version = "0.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1d1435039746e20da4f8d507a72ee1b916f7b4b05af7a91c093d2c6561934ede" checksum = "48b7b084231214f7427041e4220d77dfe726897a6d41fddee450696e66ff2a29"
dependencies = [ dependencies = [
"bitflags 1.3.2", "bitflags 1.3.2",
"libc", "libc",
@@ -1142,9 +1148,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
[[package]] [[package]]
name = "wasm-bindgen" name = "wasm-bindgen"
version = "0.2.89" version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0ed0d4f68a3015cc185aff4db9506a015f4b96f95303897bfa23f846db54064e" checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342"
dependencies = [ dependencies = [
"cfg-if", "cfg-if",
"wasm-bindgen-macro", "wasm-bindgen-macro",
@@ -1152,24 +1158,24 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-backend" name = "wasm-bindgen-backend"
version = "0.2.89" version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b56f625e64f3a1084ded111c4d5f477df9f8c92df113852fa5a374dbda78826" checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd"
dependencies = [ dependencies = [
"bumpalo", "bumpalo",
"log", "log",
"once_cell", "once_cell",
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.47", "syn 2.0.32",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
[[package]] [[package]]
name = "wasm-bindgen-macro" name = "wasm-bindgen-macro"
version = "0.2.89" version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0162dbf37223cd2afce98f3d0785506dcb8d266223983e4b5b525859e6e182b2" checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d"
dependencies = [ dependencies = [
"quote", "quote",
"wasm-bindgen-macro-support", "wasm-bindgen-macro-support",
@@ -1177,22 +1183,22 @@ dependencies = [
[[package]] [[package]]
name = "wasm-bindgen-macro-support" name = "wasm-bindgen-macro-support"
version = "0.2.89" version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f0eb82fcb7930ae6219a7ecfd55b217f5f0893484b7a13022ebb2b2bf20b5283" checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.47", "syn 2.0.32",
"wasm-bindgen-backend", "wasm-bindgen-backend",
"wasm-bindgen-shared", "wasm-bindgen-shared",
] ]
[[package]] [[package]]
name = "wasm-bindgen-shared" name = "wasm-bindgen-shared"
version = "0.2.89" version = "0.2.87"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f" checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1"
[[package]] [[package]]
name = "winapi" name = "winapi"
@@ -1218,18 +1224,18 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
[[package]] [[package]]
name = "windows-sys" name = "windows-sys"
version = "0.52.0" version = "0.48.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
dependencies = [ dependencies = [
"windows-targets", "windows-targets",
] ]
[[package]] [[package]]
name = "windows-targets" name = "windows-targets"
version = "0.52.0" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8a18201040b24831fbb9e4eb208f8892e1f50a37feb53cc7ff887feb8f50e7cd" checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
dependencies = [ dependencies = [
"windows_aarch64_gnullvm", "windows_aarch64_gnullvm",
"windows_aarch64_msvc", "windows_aarch64_msvc",
@@ -1242,51 +1248,51 @@ dependencies = [
[[package]] [[package]]
name = "windows_aarch64_gnullvm" name = "windows_aarch64_gnullvm"
version = "0.52.0" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
[[package]] [[package]]
name = "windows_aarch64_msvc" name = "windows_aarch64_msvc"
version = "0.52.0" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
[[package]] [[package]]
name = "windows_i686_gnu" name = "windows_i686_gnu"
version = "0.52.0" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
[[package]] [[package]]
name = "windows_i686_msvc" name = "windows_i686_msvc"
version = "0.52.0" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
[[package]] [[package]]
name = "windows_x86_64_gnu" name = "windows_x86_64_gnu"
version = "0.52.0" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
[[package]] [[package]]
name = "windows_x86_64_gnullvm" name = "windows_x86_64_gnullvm"
version = "0.52.0" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
[[package]] [[package]]
name = "windows_x86_64_msvc" name = "windows_x86_64_msvc"
version = "0.52.0" version = "0.48.5"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dff9641d1cd4be8d1a070daf9e3773c5f67e78b4d9d42263020c057706765c04" checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
[[package]] [[package]]
name = "zerocopy" name = "zerocopy"
version = "0.7.32" version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74d4d3961e53fa4c9a25a8637fc2bfaf2595b3d3ae34875568a5cf64787716be" checksum = "dd66a62464e3ffd4e37bd09950c2b9dd6c4f8767380fabba0d523f9a775bc85a"
dependencies = [ dependencies = [
"byteorder", "byteorder",
"zerocopy-derive", "zerocopy-derive",
@@ -1294,11 +1300,11 @@ dependencies = [
[[package]] [[package]]
name = "zerocopy-derive" name = "zerocopy-derive"
version = "0.7.32" version = "0.7.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9ce1b18ccd8e73a9321186f97e46f9f04b778851177567b1975109d26a08d2a6" checksum = "255c4596d41e6916ced49cfafea18727b24d67878fa180ddfd69b9df34fd1726"
dependencies = [ dependencies = [
"proc-macro2", "proc-macro2",
"quote", "quote",
"syn 2.0.47", "syn 2.0.32",
] ]

View File

@@ -8,26 +8,22 @@ edition = "2021"
[package.metadata] [package.metadata]
cargo-fuzz = true cargo-fuzz = true
[features]
igvm = []
[dependencies] [dependencies]
block = { path = "../block" } block = { path = "../block" }
devices = { path = "../devices" } devices = { path = "../devices" }
epoll = "4.3.1" epoll = "4.3.1"
libc = "0.2.152" libc = "0.2.149"
libfuzzer-sys = "0.4.7" libfuzzer-sys = "0.4.7"
linux-loader = { version = "0.11.0", features = ["elf", "bzimage", "pe"] } linux-loader = { version = "0.9.1", features = ["elf", "bzimage", "pe"] }
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" } micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" }
net_util = { path = "../net_util" } net_util = { path = "../net_util" }
once_cell = "1.19.0" once_cell = "1.18.0"
seccompiler = "0.4.0" seccompiler = "0.4.0"
virtio-devices = { path = "../virtio-devices" } virtio-devices = { path = "../virtio-devices" }
virtio-queue = "0.11.0" virtio-queue = "0.9.0"
vmm = { path = "../vmm" } vmm = { path = "../vmm" }
vmm-sys-util = "0.12.1" vmm-sys-util = "0.11.2"
vm-memory = "0.14.0" vm-memory = "0.12.2"
vm-migration = { path = "../vm-migration" }
vm-device = { path = "../vm-device" } vm-device = { path = "../vm-device" }
vm-virtio = { path = "../vm-virtio" } vm-virtio = { path = "../vm-virtio" }
@@ -35,8 +31,8 @@ vm-virtio = { path = "../vm-virtio" }
path = ".." path = ".."
[patch.crates-io] [patch.crates-io]
kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-live-upgrade-stable-37.x" } kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.6.0-tdx" }
versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch-0.1.6" } versionize_derive = { git = "https://github.com/cloud-hypervisor/versionize_derive", branch = "ch" }
# Prevent this from interfering with workspaces # Prevent this from interfering with workspaces
[workspace] [workspace]

View File

@@ -23,8 +23,6 @@ fuzz_target!(|bytes| {
kernel: None, kernel: None,
cmdline: Some(String::from_utf8_lossy(&bytes).to_string()), cmdline: Some(String::from_utf8_lossy(&bytes).to_string()),
initramfs: None, initramfs: None,
#[cfg(feature = "igvm")]
igvm: None,
}; };
let kernel_cmdline = match vmm::vm::Vm::generate_cmdline(&payload_config) { let kernel_cmdline = match vmm::vm::Vm::generate_cmdline(&payload_config) {
Ok(cmdline) => cmdline, Ok(cmdline) => cmdline,

View File

@@ -14,20 +14,20 @@ tdx = []
[dependencies] [dependencies]
anyhow = "1.0.75" anyhow = "1.0.75"
byteorder = "1.4.3" byteorder = "1.4.3"
igvm_defs = { git = "https://github.com/microsoft/igvm", branch = "main", package = "igvm_defs", optional = true } 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 } igvm_parser = { git = "https://github.com/microsoft/igvm", branch = "main" , package = "igvm", optional = true }
libc = "0.2.147" libc = "0.2.147"
log = "0.4.20" log = "0.4.17"
kvm-ioctls = { version = "0.16.0", optional = true } kvm-ioctls = { version = "0.13.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 } kvm-bindings = { git = "https://github.com/cloud-hypervisor/kvm-bindings", branch = "ch-v0.6.0-tdx", 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-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} mshv-ioctls = { git = "https://github.com/rust-vmm/mshv", branch = "main", optional = true}
serde = { version = "1.0.168", features = ["rc", "derive"] } serde = { version = "1.0.168", features = ["rc", "derive"] }
serde_with = { version = "3.4.0", default-features = false, features = ["macros"] } 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 } vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
vm-memory = { version = "0.14.0", features = ["backend-mmap", "backend-atomic"] } vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic"] }
vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }
thiserror = "1.0.52" thiserror = "1.0.40"
[target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86] [target.'cfg(target_arch = "x86_64")'.dependencies.iced-x86]
optional = true optional = true

View File

@@ -311,40 +311,3 @@ pub struct MsrEntry {
pub index: u32, pub index: u32,
pub data: u64, pub data: u64,
} }
#[repr(C)]
#[serde_with::serde_as]
#[derive(Debug, Clone)]
pub struct XsaveState {
pub region: [u32; 1024usize],
}
impl Default for XsaveState {
fn default() -> Self {
// SAFETY: this is plain old data structure
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(&region[..]);
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)
}
}

View File

@@ -95,12 +95,12 @@ pub enum HypervisorCpuError {
#[error("Failed to get Msr entries: {0}")] #[error("Failed to get Msr entries: {0}")]
GetMsrEntries(#[source] anyhow::Error), GetMsrEntries(#[source] anyhow::Error),
/// ///
/// Setting multi-processing state error /// Setting MSR entries error
/// ///
#[error("Failed to set MP state: {0}")] #[error("Failed to set MP state: {0}")]
SetMpState(#[source] anyhow::Error), SetMpState(#[source] anyhow::Error),
/// ///
/// Getting multi-processing state error /// Getting Msr entries error
/// ///
#[error("Failed to get MP state: {0}")] #[error("Failed to get MP state: {0}")]
GetMpState(#[source] anyhow::Error), GetMpState(#[source] anyhow::Error),
@@ -267,11 +267,6 @@ pub enum HypervisorCpuError {
/// ///
#[error("Failed to write to GPA: {0}")] #[error("Failed to write to GPA: {0}")]
GpaWrite(#[source] anyhow::Error), GpaWrite(#[source] anyhow::Error),
///
/// Error getting CPUID leaf
///
#[error("Failed to get CPUID entries: {0}")]
GetCpuidVales(#[source] anyhow::Error),
} }
#[derive(Debug)] #[derive(Debug)]
@@ -482,17 +477,4 @@ pub trait Vcpu: Send + Sync {
fn set_tsc_khz(&self, _freq: u32) -> Result<()> { fn set_tsc_khz(&self, _freq: u32) -> Result<()> {
Ok(()) Ok(())
} }
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call to retrieve cpuid leaf
///
fn get_cpuid_values(
&self,
_function: u32,
_index: u32,
_xfem: u64,
_xss: u64,
) -> Result<[u32; 4]> {
unimplemented!()
}
} }

View File

@@ -47,7 +47,7 @@ use vmm_sys_util::eventfd::EventFd;
pub mod x86_64; pub mod x86_64;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use crate::arch::x86::{ use crate::arch::x86::{
CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters, StandardRegisters, XsaveState, CpuIdEntry, FpuState, LapicState, MsrEntry, SpecialRegisters, StandardRegisters,
NUM_IOAPIC_PINS, NUM_IOAPIC_PINS,
}; };
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
@@ -66,11 +66,13 @@ use kvm_bindings::{
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
use x86_64::check_required_kvm_extensions; use x86_64::check_required_kvm_extensions;
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub use x86_64::{CpuId, ExtendedControlRegisters, MsrEntries, VcpuKvmState}; pub use x86_64::{CpuId, ExtendedControlRegisters, MsrEntries, VcpuKvmState, Xsave};
// aarch64 dependencies // aarch64 dependencies
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
pub mod aarch64; pub mod aarch64;
pub use kvm_bindings; pub use kvm_bindings;
#[cfg(feature = "tdx")]
use kvm_bindings::KVMIO;
pub use kvm_bindings::{ pub use kvm_bindings::{
kvm_clock_data, kvm_create_device, kvm_device_type_KVM_DEV_TYPE_VFIO, kvm_guest_debug, kvm_clock_data, kvm_create_device, kvm_device_type_KVM_DEV_TYPE_VFIO, kvm_guest_debug,
kvm_irq_routing, kvm_irq_routing_entry, kvm_mp_state, kvm_userspace_memory_region, kvm_irq_routing, kvm_irq_routing_entry, kvm_mp_state, kvm_userspace_memory_region,
@@ -84,8 +86,6 @@ use kvm_bindings::{
KVM_REG_ARM64_SYSREG_OP0_MASK, KVM_REG_ARM64_SYSREG_OP1_MASK, KVM_REG_ARM64_SYSREG_OP2_MASK, KVM_REG_ARM64_SYSREG_OP0_MASK, KVM_REG_ARM64_SYSREG_OP1_MASK, KVM_REG_ARM64_SYSREG_OP2_MASK,
KVM_REG_ARM_CORE, KVM_REG_SIZE_U128, KVM_REG_SIZE_U32, KVM_REG_SIZE_U64, KVM_REG_ARM_CORE, KVM_REG_SIZE_U128, KVM_REG_SIZE_U32, KVM_REG_SIZE_U64,
}; };
#[cfg(feature = "tdx")]
use kvm_bindings::{kvm_run__bindgen_ty_1, KVMIO};
pub use kvm_ioctls; pub use kvm_ioctls;
pub use kvm_ioctls::{Cap, Kvm}; pub use kvm_ioctls::{Cap, Kvm};
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
@@ -169,52 +169,6 @@ pub struct TdxCapabilities {
pub cpuid_configs: [TdxCpuidConfig; TDX_MAX_NR_CPUID_CONFIGS], pub cpuid_configs: [TdxCpuidConfig; TDX_MAX_NR_CPUID_CONFIGS],
} }
#[cfg(feature = "tdx")]
#[derive(Copy, Clone)]
pub struct KvmTdxExit {
pub type_: u32,
pub pad: u32,
pub u: KvmTdxExitU,
}
#[cfg(feature = "tdx")]
#[repr(C)]
#[derive(Copy, Clone)]
pub union KvmTdxExitU {
pub vmcall: KvmTdxExitVmcall,
}
#[cfg(feature = "tdx")]
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, PartialEq)]
pub struct KvmTdxExitVmcall {
pub type_: u64,
pub subfunction: u64,
pub reg_mask: u64,
pub in_r12: u64,
pub in_r13: u64,
pub in_r14: u64,
pub in_r15: u64,
pub in_rbx: u64,
pub in_rdi: u64,
pub in_rsi: u64,
pub in_r8: u64,
pub in_r9: u64,
pub in_rdx: u64,
pub status_code: u64,
pub out_r11: u64,
pub out_r12: u64,
pub out_r13: u64,
pub out_r14: u64,
pub out_r15: u64,
pub out_rbx: u64,
pub out_rdi: u64,
pub out_rsi: u64,
pub out_r8: u64,
pub out_r9: u64,
pub out_rdx: u64,
}
impl From<kvm_userspace_memory_region> for UserMemoryRegion { impl From<kvm_userspace_memory_region> for UserMemoryRegion {
fn from(region: kvm_userspace_memory_region) -> Self { fn from(region: kvm_userspace_memory_region) -> Self {
let mut flags = USER_MEMORY_REGION_READ; let mut flags = USER_MEMORY_REGION_READ;
@@ -315,7 +269,7 @@ impl From<CpuState> for VcpuKvmState {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
impl From<kvm_clock_data> for ClockData { impl From<kvm_clock_data> for ClockData {
fn from(d: kvm_clock_data) -> Self { fn from(d: kvm_clock_data) -> Self {
ClockData::Kvm(d.into()) ClockData::Kvm(d)
} }
} }
@@ -323,7 +277,7 @@ impl From<kvm_clock_data> for ClockData {
impl From<ClockData> for kvm_clock_data { impl From<ClockData> for kvm_clock_data {
fn from(ms: ClockData) -> Self { fn from(ms: ClockData) -> Self {
match ms { match ms {
ClockData::Kvm(s) => s.into(), ClockData::Kvm(s) => s,
/* Needed in case other hypervisors are enabled */ /* Needed in case other hypervisors are enabled */
#[allow(unreachable_patterns)] #[allow(unreachable_patterns)]
_ => panic!("CpuState is not valid"), _ => panic!("CpuState is not valid"),
@@ -402,7 +356,6 @@ impl vm::Vm for KvmVm {
.set_identity_map_address(address) .set_identity_map_address(address)
.map_err(|e| vm::HypervisorVmError::SetIdentityMapAddress(e.into())) .map_err(|e| vm::HypervisorVmError::SetIdentityMapAddress(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Sets the address of the three-page region in the VM's address space. /// Sets the address of the three-page region in the VM's address space.
@@ -412,7 +365,6 @@ impl vm::Vm for KvmVm {
.set_tss_address(offset) .set_tss_address(offset)
.map_err(|e| vm::HypervisorVmError::SetTssAddress(e.into())) .map_err(|e| vm::HypervisorVmError::SetTssAddress(e.into()))
} }
/// ///
/// Creates an in-kernel interrupt controller. /// Creates an in-kernel interrupt controller.
/// ///
@@ -421,7 +373,6 @@ impl vm::Vm for KvmVm {
.create_irq_chip() .create_irq_chip()
.map_err(|e| vm::HypervisorVmError::CreateIrq(e.into())) .map_err(|e| vm::HypervisorVmError::CreateIrq(e.into()))
} }
/// ///
/// Registers an event that will, when signaled, trigger the `gsi` IRQ. /// Registers an event that will, when signaled, trigger the `gsi` IRQ.
/// ///
@@ -430,7 +381,6 @@ impl vm::Vm for KvmVm {
.register_irqfd(fd, gsi) .register_irqfd(fd, gsi)
.map_err(|e| vm::HypervisorVmError::RegisterIrqFd(e.into())) .map_err(|e| vm::HypervisorVmError::RegisterIrqFd(e.into()))
} }
/// ///
/// Unregisters an event that will, when signaled, trigger the `gsi` IRQ. /// Unregisters an event that will, when signaled, trigger the `gsi` IRQ.
/// ///
@@ -439,7 +389,6 @@ impl vm::Vm for KvmVm {
.unregister_irqfd(fd, gsi) .unregister_irqfd(fd, gsi)
.map_err(|e| vm::HypervisorVmError::UnregisterIrqFd(e.into())) .map_err(|e| vm::HypervisorVmError::UnregisterIrqFd(e.into()))
} }
/// ///
/// Creates a VcpuFd object from a vcpu RawFd. /// Creates a VcpuFd object from a vcpu RawFd.
/// ///
@@ -462,7 +411,6 @@ impl vm::Vm for KvmVm {
}; };
Ok(Arc::new(vcpu)) Ok(Arc::new(vcpu))
} }
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
/// ///
/// Creates a virtual GIC device. /// Creates a virtual GIC device.
@@ -472,7 +420,6 @@ impl vm::Vm for KvmVm {
.map_err(|e| vm::HypervisorVmError::CreateVgic(anyhow!("Vgic error {:?}", e)))?; .map_err(|e| vm::HypervisorVmError::CreateVgic(anyhow!("Vgic error {:?}", e)))?;
Ok(Arc::new(Mutex::new(gic_device))) Ok(Arc::new(Mutex::new(gic_device)))
} }
/// ///
/// Registers an event to be signaled whenever a certain address is written to. /// Registers an event to be signaled whenever a certain address is written to.
/// ///
@@ -500,7 +447,6 @@ impl vm::Vm for KvmVm {
.map_err(|e| vm::HypervisorVmError::RegisterIoEvent(e.into())) .map_err(|e| vm::HypervisorVmError::RegisterIoEvent(e.into()))
} }
} }
/// ///
/// Unregisters an event from a certain address it has been previously registered to. /// Unregisters an event from a certain address it has been previously registered to.
/// ///
@@ -595,7 +541,6 @@ impl vm::Vm for KvmVm {
.set_gsi_routing(&irq_routing[0]) .set_gsi_routing(&irq_routing[0])
.map_err(|e| vm::HypervisorVmError::SetGsiRouting(e.into())) .map_err(|e| vm::HypervisorVmError::SetGsiRouting(e.into()))
} }
/// ///
/// Creates a memory region structure that can be used with {create/remove}_user_memory_region /// Creates a memory region structure that can be used with {create/remove}_user_memory_region
/// ///
@@ -622,7 +567,6 @@ impl vm::Vm for KvmVm {
} }
.into() .into()
} }
/// ///
/// Creates a guest physical memory region. /// Creates a guest physical memory region.
/// ///
@@ -659,7 +603,6 @@ impl vm::Vm for KvmVm {
.map_err(|e| vm::HypervisorVmError::CreateUserMemory(e.into())) .map_err(|e| vm::HypervisorVmError::CreateUserMemory(e.into()))
} }
} }
/// ///
/// Removes a guest physical memory region. /// Removes a guest physical memory region.
/// ///
@@ -678,7 +621,6 @@ impl vm::Vm for KvmVm {
.map_err(|e| vm::HypervisorVmError::RemoveUserMemory(e.into())) .map_err(|e| vm::HypervisorVmError::RemoveUserMemory(e.into()))
} }
} }
/// ///
/// Returns the preferred CPU target type which can be emulated by KVM on underlying host. /// Returns the preferred CPU target type which can be emulated by KVM on underlying host.
/// ///
@@ -688,7 +630,6 @@ impl vm::Vm for KvmVm {
.get_preferred_target(kvi) .get_preferred_target(kvi)
.map_err(|e| vm::HypervisorVmError::GetPreferredTarget(e.into())) .map_err(|e| vm::HypervisorVmError::GetPreferredTarget(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn enable_split_irq(&self) -> vm::Result<()> { fn enable_split_irq(&self) -> vm::Result<()> {
// Create split irqchip // Create split irqchip
@@ -704,7 +645,6 @@ impl vm::Vm for KvmVm {
.map_err(|e| vm::HypervisorVmError::EnableSplitIrq(e.into()))?; .map_err(|e| vm::HypervisorVmError::EnableSplitIrq(e.into()))?;
Ok(()) Ok(())
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn enable_sgx_attribute(&self, file: File) -> vm::Result<()> { fn enable_sgx_attribute(&self, file: File) -> vm::Result<()> {
let mut cap = kvm_enable_cap { let mut cap = kvm_enable_cap {
@@ -717,7 +657,6 @@ impl vm::Vm for KvmVm {
.map_err(|e| vm::HypervisorVmError::EnableSgxAttribute(e.into()))?; .map_err(|e| vm::HypervisorVmError::EnableSgxAttribute(e.into()))?;
Ok(()) Ok(())
} }
/// Retrieve guest clock. /// Retrieve guest clock.
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn get_clock(&self) -> vm::Result<ClockData> { fn get_clock(&self) -> vm::Result<ClockData> {
@@ -727,7 +666,6 @@ impl vm::Vm for KvmVm {
.map_err(|e| vm::HypervisorVmError::GetClock(e.into()))? .map_err(|e| vm::HypervisorVmError::GetClock(e.into()))?
.into()) .into())
} }
/// Set guest clock. /// Set guest clock.
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn set_clock(&self, data: &ClockData) -> vm::Result<()> { fn set_clock(&self, data: &ClockData) -> vm::Result<()> {
@@ -736,7 +674,6 @@ impl vm::Vm for KvmVm {
.set_clock(&data) .set_clock(&data)
.map_err(|e| vm::HypervisorVmError::SetClock(e.into())) .map_err(|e| vm::HypervisorVmError::SetClock(e.into()))
} }
/// Create a device that is used for passthrough /// Create a device that is used for passthrough
fn create_passthrough_device(&self) -> vm::Result<VfioDeviceFd> { fn create_passthrough_device(&self) -> vm::Result<VfioDeviceFd> {
let mut vfio_dev = kvm_create_device { let mut vfio_dev = kvm_create_device {
@@ -748,7 +685,6 @@ impl vm::Vm for KvmVm {
self.create_device(&mut vfio_dev) self.create_device(&mut vfio_dev)
.map_err(|e| vm::HypervisorVmError::CreatePassthroughDevice(e.into())) .map_err(|e| vm::HypervisorVmError::CreatePassthroughDevice(e.into()))
} }
/// ///
/// Start logging dirty pages /// Start logging dirty pages
/// ///
@@ -890,7 +826,6 @@ impl vm::Vm for KvmVm {
) )
.map_err(vm::HypervisorVmError::InitMemRegionTdx) .map_err(vm::HypervisorVmError::InitMemRegionTdx)
} }
/// Downcast to the underlying KvmVm type /// Downcast to the underlying KvmVm type
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self
@@ -957,9 +892,7 @@ pub enum KvmError {
#[error("Capability missing: {0:?}")] #[error("Capability missing: {0:?}")]
CapabilityMissing(Cap), CapabilityMissing(Cap),
} }
pub type KvmResult<T> = result::Result<T, KvmError>; pub type KvmResult<T> = result::Result<T, KvmError>;
impl KvmHypervisor { impl KvmHypervisor {
/// Create a hypervisor based on Kvm /// Create a hypervisor based on Kvm
#[allow(clippy::new_ret_no_self)] #[allow(clippy::new_ret_no_self)]
@@ -973,7 +906,6 @@ impl KvmHypervisor {
Ok(Arc::new(KvmHypervisor { kvm: kvm_obj })) Ok(Arc::new(KvmHypervisor { kvm: kvm_obj }))
} }
/// Check if the hypervisor is available /// Check if the hypervisor is available
pub fn is_available() -> hypervisor::Result<bool> { pub fn is_available() -> hypervisor::Result<bool> {
match std::fs::metadata("/dev/kvm") { match std::fs::metadata("/dev/kvm") {
@@ -985,7 +917,6 @@ impl KvmHypervisor {
} }
} }
} }
/// Implementation of Hypervisor trait for KVM /// Implementation of Hypervisor trait for KVM
/// ///
/// # Examples /// # Examples
@@ -1004,7 +935,6 @@ impl hypervisor::Hypervisor for KvmHypervisor {
fn hypervisor_type(&self) -> HypervisorType { fn hypervisor_type(&self) -> HypervisorType {
HypervisorType::Kvm HypervisorType::Kvm
} }
/// Create a KVM vm object of a specific VM type and return the object as Vm trait object /// Create a KVM vm object of a specific VM type and return the object as Vm trait object
/// ///
/// # Examples /// # Examples
@@ -1160,7 +1090,6 @@ impl hypervisor::Hypervisor for KvmHypervisor {
self.kvm.get_max_vcpus().min(u32::MAX as usize) as u32 self.kvm.get_max_vcpus().min(u32::MAX as usize) as u32
} }
} }
/// Vcpu struct for KVM /// Vcpu struct for KVM
pub struct KvmVcpu { pub struct KvmVcpu {
fd: VcpuFd, fd: VcpuFd,
@@ -1170,7 +1099,6 @@ pub struct KvmVcpu {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
hyperv_synic: AtomicBool, hyperv_synic: AtomicBool,
} }
/// Implementation of Vcpu trait for KVM /// Implementation of Vcpu trait for KVM
/// ///
/// # Examples /// # Examples
@@ -1195,7 +1123,6 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetStandardRegs(e.into()))? .map_err(|e| cpu::HypervisorCpuError::GetStandardRegs(e.into()))?
.into()) .into())
} }
/// ///
/// Returns the vCPU general purpose registers. /// Returns the vCPU general purpose registers.
/// The `KVM_GET_REGS` ioctl is not available on AArch64, `KVM_GET_ONE_REG` /// The `KVM_GET_REGS` ioctl is not available on AArch64, `KVM_GET_ONE_REG`
@@ -1210,64 +1137,71 @@ impl cpu::Vcpu for KvmVcpu {
// These actually are the general-purpose registers of the Armv8-a // These actually are the general-purpose registers of the Armv8-a
// architecture (i.e x0-x30 if used as a 64bit register or w0-30 when used as a 32bit register). // architecture (i.e x0-x30 if used as a 64bit register or w0-30 when used as a 32bit register).
for i in 0..31 { for i in 0..31 {
let mut bytes = [0_u8; 8]; state.regs.regs[i] = self
self.fd .fd
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes) .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off))
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?
state.regs.regs[i] = u64::from_le_bytes(bytes); .try_into()
.unwrap();
off += std::mem::size_of::<u64>(); off += std::mem::size_of::<u64>();
} }
// We are now entering the "Other register" section of the ARMv8-a architecture. // We are now entering the "Other register" section of the ARMv8-a architecture.
// First one, stack pointer. // First one, stack pointer.
let off = offset_of!(user_pt_regs, sp); let off = offset_of!(user_pt_regs, sp);
let mut bytes = [0_u8; 8]; state.regs.sp = self
self.fd .fd
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes) .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off))
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?
state.regs.sp = u64::from_le_bytes(bytes); .try_into()
.unwrap();
// Second one, the program counter. // Second one, the program counter.
let off = offset_of!(user_pt_regs, pc); let off = offset_of!(user_pt_regs, pc);
let mut bytes = [0_u8; 8]; state.regs.pc = self
self.fd .fd
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes) .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off))
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?
state.regs.pc = u64::from_le_bytes(bytes); .try_into()
.unwrap();
// Next is the processor state. // Next is the processor state.
let off = offset_of!(user_pt_regs, pstate); let off = offset_of!(user_pt_regs, pstate);
let mut bytes = [0_u8; 8]; state.regs.pstate = self
self.fd .fd
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes) .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off))
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?
state.regs.pstate = u64::from_le_bytes(bytes); .try_into()
.unwrap();
// The stack pointer associated with EL1 // The stack pointer associated with EL1
let off = offset_of!(kvm_regs, sp_el1); let off = offset_of!(kvm_regs, sp_el1);
let mut bytes = [0_u8; 8]; state.sp_el1 = self
self.fd .fd
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes) .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off))
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?
state.sp_el1 = u64::from_le_bytes(bytes); .try_into()
.unwrap();
// Exception Link Register for EL1, when taking an exception to EL1, this register // Exception Link Register for EL1, when taking an exception to EL1, this register
// holds the address to which to return afterwards. // holds the address to which to return afterwards.
let off = offset_of!(kvm_regs, elr_el1); let off = offset_of!(kvm_regs, elr_el1);
let mut bytes = [0_u8; 8]; state.elr_el1 = self
self.fd .fd
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes) .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off))
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?
state.elr_el1 = u64::from_le_bytes(bytes); .try_into()
.unwrap();
// Saved Program Status Registers, there are 5 of them used in the kernel. // Saved Program Status Registers, there are 5 of them used in the kernel.
let mut off = offset_of!(kvm_regs, spsr); let mut off = offset_of!(kvm_regs, spsr);
for i in 0..KVM_NR_SPSR as usize { for i in 0..KVM_NR_SPSR as usize {
let mut bytes = [0_u8; 8]; state.spsr[i] = self
self.fd .fd
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off), &mut bytes) .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, off))
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?
state.spsr[i] = u64::from_le_bytes(bytes); .try_into()
.unwrap();
off += std::mem::size_of::<u64>(); off += std::mem::size_of::<u64>();
} }
@@ -1275,32 +1209,32 @@ impl cpu::Vcpu for KvmVcpu {
// https://elixir.free-electrons.com/linux/v4.9.62/source/arch/arm64/include/uapi/asm/kvm.h#L53 // https://elixir.free-electrons.com/linux/v4.9.62/source/arch/arm64/include/uapi/asm/kvm.h#L53
let mut off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, vregs); let mut off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, vregs);
for i in 0..32 { for i in 0..32 {
let mut bytes = [0_u8; 16]; state.fp_regs.vregs[i] = self
self.fd .fd
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U128, off), &mut bytes) .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U128, off))
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?;
state.fp_regs.vregs[i] = u128::from_le_bytes(bytes);
off += mem::size_of::<u128>(); off += mem::size_of::<u128>();
} }
// Floating-point Status Register // Floating-point Status Register
let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpsr); let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpsr);
let mut bytes = [0_u8; 4]; state.fp_regs.fpsr = self
self.fd .fd
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off), &mut bytes) .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off))
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?
state.fp_regs.fpsr = u32::from_le_bytes(bytes); .try_into()
.unwrap();
// Floating-point Control Register // Floating-point Control Register
let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpcr); let off = offset_of!(kvm_regs, fp_regs) + offset_of!(user_fpsimd_state, fpcr);
let mut bytes = [0_u8; 4]; state.fp_regs.fpcr = self
self.fd .fd
.get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off), &mut bytes) .get_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U32, off))
.map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::GetCoreRegister(e.into()))?
state.fp_regs.fpcr = u32::from_le_bytes(bytes); .try_into()
.unwrap();
Ok(state) Ok(state)
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Sets the vCPU general purpose registers using the `KVM_SET_REGS` ioctl. /// Sets the vCPU general purpose registers using the `KVM_SET_REGS` ioctl.
@@ -1326,7 +1260,7 @@ impl cpu::Vcpu for KvmVcpu {
self.fd self.fd
.set_one_reg( .set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, off), arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
&state.regs.regs[i].to_le_bytes(), state.regs.regs[i].into(),
) )
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
off += std::mem::size_of::<u64>(); off += std::mem::size_of::<u64>();
@@ -1336,7 +1270,7 @@ impl cpu::Vcpu for KvmVcpu {
self.fd self.fd
.set_one_reg( .set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, off), arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
&state.regs.sp.to_le_bytes(), state.regs.sp.into(),
) )
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
@@ -1344,7 +1278,7 @@ impl cpu::Vcpu for KvmVcpu {
self.fd self.fd
.set_one_reg( .set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, off), arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
&state.regs.pc.to_le_bytes(), state.regs.pc.into(),
) )
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
@@ -1352,7 +1286,7 @@ impl cpu::Vcpu for KvmVcpu {
self.fd self.fd
.set_one_reg( .set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, off), arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
&state.regs.pstate.to_le_bytes(), state.regs.pstate.into(),
) )
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
@@ -1360,7 +1294,7 @@ impl cpu::Vcpu for KvmVcpu {
self.fd self.fd
.set_one_reg( .set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, off), arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
&state.sp_el1.to_le_bytes(), state.sp_el1.into(),
) )
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
@@ -1368,7 +1302,7 @@ impl cpu::Vcpu for KvmVcpu {
self.fd self.fd
.set_one_reg( .set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, off), arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
&state.elr_el1.to_le_bytes(), state.elr_el1.into(),
) )
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
@@ -1377,7 +1311,7 @@ impl cpu::Vcpu for KvmVcpu {
self.fd self.fd
.set_one_reg( .set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, off), arm64_core_reg_id!(KVM_REG_SIZE_U64, off),
&state.spsr[i].to_le_bytes(), state.spsr[i].into(),
) )
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
off += std::mem::size_of::<u64>(); off += std::mem::size_of::<u64>();
@@ -1388,7 +1322,7 @@ impl cpu::Vcpu for KvmVcpu {
self.fd self.fd
.set_one_reg( .set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U128, off), arm64_core_reg_id!(KVM_REG_SIZE_U128, off),
&state.fp_regs.vregs[i].to_le_bytes(), state.fp_regs.vregs[i],
) )
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
off += mem::size_of::<u128>(); off += mem::size_of::<u128>();
@@ -1398,7 +1332,7 @@ impl cpu::Vcpu for KvmVcpu {
self.fd self.fd
.set_one_reg( .set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U32, off), arm64_core_reg_id!(KVM_REG_SIZE_U32, off),
&state.fp_regs.fpsr.to_le_bytes(), state.fp_regs.fpsr.into(),
) )
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
@@ -1406,7 +1340,7 @@ impl cpu::Vcpu for KvmVcpu {
self.fd self.fd
.set_one_reg( .set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U32, off), arm64_core_reg_id!(KVM_REG_SIZE_U32, off),
&state.fp_regs.fpcr.to_le_bytes(), state.fp_regs.fpcr.into(),
) )
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
Ok(()) Ok(())
@@ -1423,7 +1357,6 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetSpecialRegs(e.into()))? .map_err(|e| cpu::HypervisorCpuError::GetSpecialRegs(e.into()))?
.into()) .into())
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Sets the vCPU special registers using the `KVM_SET_SREGS` ioctl. /// Sets the vCPU special registers using the `KVM_SET_SREGS` ioctl.
@@ -1434,7 +1367,6 @@ impl cpu::Vcpu for KvmVcpu {
.set_sregs(&sregs) .set_sregs(&sregs)
.map_err(|e| cpu::HypervisorCpuError::SetSpecialRegs(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetSpecialRegs(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Returns the floating point state (FPU) from the vCPU. /// Returns the floating point state (FPU) from the vCPU.
@@ -1446,7 +1378,6 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetFloatingPointRegs(e.into()))? .map_err(|e| cpu::HypervisorCpuError::GetFloatingPointRegs(e.into()))?
.into()) .into())
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Set the floating point state (FPU) of a vCPU using the `KVM_SET_FPU` ioct. /// Set the floating point state (FPU) of a vCPU using the `KVM_SET_FPU` ioct.
@@ -1457,7 +1388,6 @@ impl cpu::Vcpu for KvmVcpu {
.set_fpu(&fpu) .set_fpu(&fpu)
.map_err(|e| cpu::HypervisorCpuError::SetFloatingPointRegs(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetFloatingPointRegs(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// X86 specific call to setup the CPUID registers. /// X86 specific call to setup the CPUID registers.
@@ -1472,7 +1402,6 @@ impl cpu::Vcpu for KvmVcpu {
.set_cpuid2(&kvm_cpuid) .set_cpuid2(&kvm_cpuid)
.map_err(|e| cpu::HypervisorCpuError::SetCpuid(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetCpuid(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// X86 specific call to enable HyperV SynIC /// X86 specific call to enable HyperV SynIC
@@ -1490,7 +1419,6 @@ impl cpu::Vcpu for KvmVcpu {
.enable_cap(&cap) .enable_cap(&cap)
.map_err(|e| cpu::HypervisorCpuError::EnableHyperVSyncIc(e.into())) .map_err(|e| cpu::HypervisorCpuError::EnableHyperVSyncIc(e.into()))
} }
/// ///
/// X86 specific call to retrieve the CPUID registers. /// X86 specific call to retrieve the CPUID registers.
/// ///
@@ -1505,7 +1433,6 @@ impl cpu::Vcpu for KvmVcpu {
Ok(v) Ok(v)
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller). /// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
@@ -1517,7 +1444,6 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetlapicState(e.into()))? .map_err(|e| cpu::HypervisorCpuError::GetlapicState(e.into()))?
.into()) .into())
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller). /// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
@@ -1528,7 +1454,6 @@ impl cpu::Vcpu for KvmVcpu {
.set_lapic(&klapic) .set_lapic(&klapic)
.map_err(|e| cpu::HypervisorCpuError::SetLapicState(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetLapicState(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Returns the model-specific registers (MSR) for this vCPU. /// Returns the model-specific registers (MSR) for this vCPU.
@@ -1550,7 +1475,6 @@ impl cpu::Vcpu for KvmVcpu {
Ok(succ) Ok(succ)
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Setup the model-specific registers (MSR) for this vCPU. /// Setup the model-specific registers (MSR) for this vCPU.
@@ -1563,7 +1487,6 @@ impl cpu::Vcpu for KvmVcpu {
.set_msrs(&kvm_msrs) .set_msrs(&kvm_msrs)
.map_err(|e| cpu::HypervisorCpuError::SetMsrEntries(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetMsrEntries(e.into()))
} }
/// ///
/// Returns the vcpu's current "multiprocessing state". /// Returns the vcpu's current "multiprocessing state".
/// ///
@@ -1574,7 +1497,6 @@ impl cpu::Vcpu for KvmVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetMpState(e.into()))? .map_err(|e| cpu::HypervisorCpuError::GetMpState(e.into()))?
.into()) .into())
} }
/// ///
/// Sets the vcpu's current "multiprocessing state". /// Sets the vcpu's current "multiprocessing state".
/// ///
@@ -1583,7 +1505,6 @@ impl cpu::Vcpu for KvmVcpu {
.set_mp_state(mp_state.into()) .set_mp_state(mp_state.into())
.map_err(|e| cpu::HypervisorCpuError::SetMpState(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetMpState(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Translates guest virtual address to guest physical address using the `KVM_TRANSLATE` ioctl. /// Translates guest virtual address to guest physical address using the `KVM_TRANSLATE` ioctl.
@@ -1602,7 +1523,6 @@ impl cpu::Vcpu for KvmVcpu {
_ => Ok((tr.physical_address, 0)), _ => Ok((tr.physical_address, 0)),
} }
} }
/// ///
/// Triggers the running of the current virtual CPU returning an exit reason. /// Triggers the running of the current virtual CPU returning an exit reason.
/// ///
@@ -1647,7 +1567,7 @@ impl cpu::Vcpu for KvmVcpu {
Ok(cpu::VmExit::Shutdown) Ok(cpu::VmExit::Shutdown)
} else { } else {
Err(cpu::HypervisorCpuError::RunVcpu(anyhow!( Err(cpu::HypervisorCpuError::RunVcpu(anyhow!(
"Unexpected system event with type 0x{:x}, flags 0x{:x?}", "Unexpected system event with type 0x{:x}, flags 0x{:x}",
event_type, event_type,
flags flags
))) )))
@@ -1694,7 +1614,6 @@ impl cpu::Vcpu for KvmVcpu {
}, },
} }
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Let the guest know that it has been paused, which prevents from /// Let the guest know that it has been paused, which prevents from
@@ -1712,7 +1631,6 @@ impl cpu::Vcpu for KvmVcpu {
Ok(()) Ok(())
} }
/// ///
/// Sets debug registers to set hardware breakpoints and/or enable single step. /// Sets debug registers to set hardware breakpoints and/or enable single step.
/// ///
@@ -1766,14 +1684,12 @@ impl cpu::Vcpu for KvmVcpu {
.set_guest_debug(&dbg) .set_guest_debug(&dbg)
.map_err(|e| cpu::HypervisorCpuError::SetDebugRegs(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetDebugRegs(e.into()))
} }
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
fn vcpu_init(&self, kvi: &VcpuInit) -> cpu::Result<()> { fn vcpu_init(&self, kvi: &VcpuInit) -> cpu::Result<()> {
self.fd self.fd
.vcpu_init(kvi) .vcpu_init(kvi)
.map_err(|e| cpu::HypervisorCpuError::VcpuInit(e.into())) .map_err(|e| cpu::HypervisorCpuError::VcpuInit(e.into()))
} }
/// ///
/// Gets a list of the guest registers that are supported for the /// Gets a list of the guest registers that are supported for the
/// KVM_GET_ONE_REG/KVM_SET_ONE_REG calls. /// KVM_GET_ONE_REG/KVM_SET_ONE_REG calls.
@@ -1784,7 +1700,6 @@ impl cpu::Vcpu for KvmVcpu {
.get_reg_list(reg_list) .get_reg_list(reg_list)
.map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into())) .map_err(|e| cpu::HypervisorCpuError::GetRegList(e.into()))
} }
/// ///
/// Gets the value of a system register /// Gets the value of a system register
/// ///
@@ -1811,13 +1726,13 @@ impl cpu::Vcpu for KvmVcpu {
| KVM_REG_ARM64_SYSREG_CRN_MASK | KVM_REG_ARM64_SYSREG_CRN_MASK
| KVM_REG_ARM64_SYSREG_CRM_MASK | KVM_REG_ARM64_SYSREG_CRM_MASK
| KVM_REG_ARM64_SYSREG_OP2_MASK)) as u64); | KVM_REG_ARM64_SYSREG_OP2_MASK)) as u64);
let mut bytes = [0_u8; 8]; Ok(self
self.fd .fd
.get_one_reg(id, &mut bytes) .get_one_reg(id)
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))?
Ok(u64::from_le_bytes(bytes)) .try_into()
.unwrap())
} }
/// ///
/// Configure core registers for a given CPU. /// Configure core registers for a given CPU.
/// ///
@@ -1842,7 +1757,7 @@ impl cpu::Vcpu for KvmVcpu {
self.fd self.fd
.set_one_reg( .set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, pstate), arm64_core_reg_id!(KVM_REG_SIZE_U64, pstate),
&PSTATE_FAULT_BITS_64.to_le_bytes(), PSTATE_FAULT_BITS_64.into(),
) )
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
@@ -1851,10 +1766,7 @@ impl cpu::Vcpu for KvmVcpu {
// Setting the PC (Processor Counter) to the current program address (kernel address). // Setting the PC (Processor Counter) to the current program address (kernel address).
let pc = offset_of!(user_pt_regs, pc) + kreg_off; let pc = offset_of!(user_pt_regs, pc) + kreg_off;
self.fd self.fd
.set_one_reg( .set_one_reg(arm64_core_reg_id!(KVM_REG_SIZE_U64, pc), boot_ip.into())
arm64_core_reg_id!(KVM_REG_SIZE_U64, pc),
&boot_ip.to_le_bytes(),
)
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
// Last mandatory thing to set -> the address pointing to the FDT (also called DTB). // Last mandatory thing to set -> the address pointing to the FDT (also called DTB).
@@ -1865,7 +1777,7 @@ impl cpu::Vcpu for KvmVcpu {
self.fd self.fd
.set_one_reg( .set_one_reg(
arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0), arm64_core_reg_id!(KVM_REG_SIZE_U64, regs0),
&fdt_start.to_le_bytes(), fdt_start.into(),
) )
.map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::SetCoreRegister(e.into()))?;
} }
@@ -1977,7 +1889,7 @@ impl cpu::Vcpu for KvmVcpu {
msr_entries msr_entries
}; };
let vcpu_events = self.get_vcpu_events()?.into(); let vcpu_events = self.get_vcpu_events()?;
let tsc_khz = self.tsc_khz()?; let tsc_khz = self.tsc_khz()?;
Ok(VcpuKvmState { Ok(VcpuKvmState {
@@ -1995,7 +1907,6 @@ impl cpu::Vcpu for KvmVcpu {
} }
.into()) .into())
} }
/// ///
/// Get the current AArch64 CPU state /// Get the current AArch64 CPU state
/// ///
@@ -2030,13 +1941,14 @@ impl cpu::Vcpu for KvmVcpu {
// register list, we are simply calling KVM_GET_ONE_REG. // register list, we are simply calling KVM_GET_ONE_REG.
let indices = reg_list.as_slice(); let indices = reg_list.as_slice();
for index in indices.iter() { for index in indices.iter() {
let mut bytes = [0_u8; 8];
self.fd
.get_one_reg(*index, &mut bytes)
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))?;
sys_regs.push(kvm_bindings::kvm_one_reg { sys_regs.push(kvm_bindings::kvm_one_reg {
id: *index, id: *index,
addr: u64::from_le_bytes(bytes), addr: self
.fd
.get_one_reg(*index)
.map_err(|e| cpu::HypervisorCpuError::GetSysRegister(e.into()))?
.try_into()
.unwrap(),
}); });
} }
@@ -2044,7 +1956,6 @@ impl cpu::Vcpu for KvmVcpu {
Ok(state.into()) Ok(state.into())
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Restore the previously saved CPU state /// Restore the previously saved CPU state
@@ -2130,11 +2041,10 @@ impl cpu::Vcpu for KvmVcpu {
} }
} }
self.set_vcpu_events(&state.vcpu_events.into())?; self.set_vcpu_events(&state.vcpu_events)?;
Ok(()) Ok(())
} }
/// ///
/// Restore the previously saved AArch64 CPU state /// Restore the previously saved AArch64 CPU state
/// ///
@@ -2146,7 +2056,7 @@ impl cpu::Vcpu for KvmVcpu {
// Set system registers // Set system registers
for reg in &state.sys_regs { for reg in &state.sys_regs {
self.fd self.fd
.set_one_reg(reg.id, &reg.addr.to_le_bytes()) .set_one_reg(reg.id, reg.addr.into())
.map_err(|e| cpu::HypervisorCpuError::SetSysRegister(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::SetSysRegister(e.into()))?;
} }
@@ -2178,12 +2088,7 @@ impl cpu::Vcpu for KvmVcpu {
fn get_tdx_exit_details(&mut self) -> cpu::Result<TdxExitDetails> { fn get_tdx_exit_details(&mut self) -> cpu::Result<TdxExitDetails> {
let kvm_run = self.fd.get_kvm_run(); let kvm_run = self.fd.get_kvm_run();
// SAFETY: accessing a union field in a valid structure // SAFETY: accessing a union field in a valid structure
let tdx_vmcall = unsafe { let tdx_vmcall = unsafe { &mut kvm_run.__bindgen_anon_1.tdx.u.vmcall };
&mut (*((&mut kvm_run.__bindgen_anon_1) as *mut kvm_run__bindgen_ty_1
as *mut KvmTdxExit))
.u
.vmcall
};
tdx_vmcall.status_code = TDG_VP_VMCALL_INVALID_OPERAND; tdx_vmcall.status_code = TDG_VP_VMCALL_INVALID_OPERAND;
@@ -2207,19 +2112,13 @@ impl cpu::Vcpu for KvmVcpu {
fn set_tdx_status(&mut self, status: TdxExitStatus) { fn set_tdx_status(&mut self, status: TdxExitStatus) {
let kvm_run = self.fd.get_kvm_run(); let kvm_run = self.fd.get_kvm_run();
// SAFETY: accessing a union field in a valid structure // SAFETY: accessing a union field in a valid structure
let tdx_vmcall = unsafe { let tdx_vmcall = unsafe { &mut kvm_run.__bindgen_anon_1.tdx.u.vmcall };
&mut (*((&mut kvm_run.__bindgen_anon_1) as *mut kvm_run__bindgen_ty_1
as *mut KvmTdxExit))
.u
.vmcall
};
tdx_vmcall.status_code = match status { tdx_vmcall.status_code = match status {
TdxExitStatus::Success => TDG_VP_VMCALL_SUCCESS, TdxExitStatus::Success => TDG_VP_VMCALL_SUCCESS,
TdxExitStatus::InvalidOperand => TDG_VP_VMCALL_INVALID_OPERAND, TdxExitStatus::InvalidOperand => TDG_VP_VMCALL_INVALID_OPERAND,
}; };
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Return the list of initial MSR entries for a VCPU /// Return the list of initial MSR entries for a VCPU
@@ -2245,7 +2144,6 @@ impl cpu::Vcpu for KvmVcpu {
] ]
.to_vec() .to_vec()
} }
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
fn has_pmu_support(&self) -> bool { fn has_pmu_support(&self) -> bool {
let cpu_attr = kvm_bindings::kvm_device_attr { let cpu_attr = kvm_bindings::kvm_device_attr {
@@ -2256,7 +2154,6 @@ impl cpu::Vcpu for KvmVcpu {
}; };
self.fd.has_device_attr(&cpu_attr).is_ok() self.fd.has_device_attr(&cpu_attr).is_ok()
} }
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
fn init_pmu(&self, irq: u32) -> cpu::Result<()> { fn init_pmu(&self, irq: u32) -> cpu::Result<()> {
let cpu_attr = kvm_bindings::kvm_device_attr { let cpu_attr = kvm_bindings::kvm_device_attr {
@@ -2319,25 +2216,20 @@ impl KvmVcpu {
/// ///
/// X86 specific call that returns the vcpu's current "xsave struct". /// X86 specific call that returns the vcpu's current "xsave struct".
/// ///
fn get_xsave(&self) -> cpu::Result<XsaveState> { fn get_xsave(&self) -> cpu::Result<Xsave> {
Ok(self self.fd
.fd
.get_xsave() .get_xsave()
.map_err(|e| cpu::HypervisorCpuError::GetXsaveState(e.into()))? .map_err(|e| cpu::HypervisorCpuError::GetXsaveState(e.into()))
.into())
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// X86 specific call that sets the vcpu's current "xsave struct". /// X86 specific call that sets the vcpu's current "xsave struct".
/// ///
fn set_xsave(&self, xsave: &XsaveState) -> cpu::Result<()> { fn set_xsave(&self, xsave: &Xsave) -> cpu::Result<()> {
let xsave: kvm_bindings::kvm_xsave = (*xsave).clone().into();
self.fd self.fd
.set_xsave(&xsave) .set_xsave(xsave)
.map_err(|e| cpu::HypervisorCpuError::SetXsaveState(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetXsaveState(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// X86 specific call that returns the vcpu's current "xcrs". /// X86 specific call that returns the vcpu's current "xcrs".
@@ -2347,7 +2239,6 @@ impl KvmVcpu {
.get_xcrs() .get_xcrs()
.map_err(|e| cpu::HypervisorCpuError::GetXcsr(e.into())) .map_err(|e| cpu::HypervisorCpuError::GetXcsr(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// X86 specific call that sets the vcpu's current "xcrs". /// X86 specific call that sets the vcpu's current "xcrs".
@@ -2357,7 +2248,6 @@ impl KvmVcpu {
.set_xcrs(xcrs) .set_xcrs(xcrs)
.map_err(|e| cpu::HypervisorCpuError::SetXcsr(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetXcsr(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Returns currently pending exceptions, interrupts, and NMIs as well as related /// Returns currently pending exceptions, interrupts, and NMIs as well as related
@@ -2368,7 +2258,6 @@ impl KvmVcpu {
.get_vcpu_events() .get_vcpu_events()
.map_err(|e| cpu::HypervisorCpuError::GetVcpuEvents(e.into())) .map_err(|e| cpu::HypervisorCpuError::GetVcpuEvents(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Sets pending exceptions, interrupts, and NMIs as well as related states /// Sets pending exceptions, interrupts, and NMIs as well as related states

View File

@@ -10,7 +10,7 @@
use crate::arch::x86::{ use crate::arch::x86::{
CpuIdEntry, DescriptorTable, FpuState, LapicState, MsrEntry, SegmentRegister, SpecialRegisters, CpuIdEntry, DescriptorTable, FpuState, LapicState, MsrEntry, SegmentRegister, SpecialRegisters,
StandardRegisters, XsaveState, CPUID_FLAG_VALID_INDEX, StandardRegisters, CPUID_FLAG_VALID_INDEX,
}; };
use crate::kvm::{Cap, Kvm, KvmError, KvmResult}; use crate::kvm::{Cap, Kvm, KvmError, KvmResult};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
@@ -22,8 +22,8 @@ pub use {
kvm_bindings::kvm_cpuid_entry2, kvm_bindings::kvm_dtable, kvm_bindings::kvm_fpu, 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_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_msr_entry, kvm_bindings::kvm_regs, kvm_bindings::kvm_segment,
kvm_bindings::kvm_sregs, kvm_bindings::kvm_vcpu_events_old as VcpuEvents, kvm_bindings::kvm_sregs, kvm_bindings::kvm_vcpu_events as VcpuEvents,
kvm_bindings::kvm_xcrs as ExtendedControlRegisters, kvm_bindings::kvm_xsave, kvm_bindings::kvm_xcrs as ExtendedControlRegisters, kvm_bindings::kvm_xsave as Xsave,
kvm_bindings::CpuId, kvm_bindings::MsrList, kvm_bindings::Msrs as MsrEntries, kvm_bindings::CpuId, kvm_bindings::MsrList, kvm_bindings::Msrs as MsrEntries,
kvm_bindings::KVM_CPUID_FLAG_SIGNIFCANT_INDEX, kvm_bindings::KVM_CPUID_FLAG_SIGNIFCANT_INDEX,
}; };
@@ -64,7 +64,7 @@ pub struct VcpuKvmState {
pub sregs: kvm_sregs, pub sregs: kvm_sregs,
pub fpu: FpuState, pub fpu: FpuState,
pub lapic_state: LapicState, pub lapic_state: LapicState,
pub xsave: XsaveState, pub xsave: Xsave,
pub xcrs: ExtendedControlRegisters, pub xcrs: ExtendedControlRegisters,
pub mp_state: MpState, pub mp_state: MpState,
pub tsc_khz: Option<u32>, pub tsc_khz: Option<u32>,
@@ -330,18 +330,3 @@ impl From<MsrEntry> for kvm_msr_entry {
} }
} }
} }
impl From<kvm_xsave> for XsaveState {
fn from(s: kvm_xsave) -> Self {
Self { region: s.region }
}
}
impl From<XsaveState> for kvm_xsave {
fn from(s: XsaveState) -> Self {
Self {
region: s.region,
extra: Default::default(),
}
}
}

View File

@@ -162,7 +162,7 @@ pub enum CpuState {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
pub enum ClockData { pub enum ClockData {
#[cfg(feature = "kvm")] #[cfg(feature = "kvm")]
Kvm(kvm_bindings::kvm_clock_data_old), Kvm(kvm_bindings::kvm_clock_data),
#[cfg(feature = "mshv")] #[cfg(feature = "mshv")]
Mshv, /* MSHV does not support ClockData yet */ Mshv, /* MSHV does not support ClockData yet */
} }

View File

@@ -200,7 +200,6 @@ impl MshvHypervisor {
} }
} }
} }
/// Implementation of Hypervisor trait for Mshv /// Implementation of Hypervisor trait for Mshv
/// ///
/// # Examples /// # Examples
@@ -339,8 +338,6 @@ pub struct MshvVcpu {
cpuid: Vec<CpuIdEntry>, cpuid: Vec<CpuIdEntry>,
msrs: Vec<MsrEntry>, msrs: Vec<MsrEntry>,
vm_ops: Option<Arc<dyn vm::VmOps>>, vm_ops: Option<Arc<dyn vm::VmOps>>,
#[cfg(feature = "sev_snp")]
vm_fd: Arc<VmFd>,
} }
/// Implementation of Vcpu trait for Microsoft Hypervisor /// Implementation of Vcpu trait for Microsoft Hypervisor
@@ -367,7 +364,6 @@ impl cpu::Vcpu for MshvVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetStandardRegs(e.into()))? .map_err(|e| cpu::HypervisorCpuError::GetStandardRegs(e.into()))?
.into()) .into())
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Sets the vCPU general purpose registers. /// Sets the vCPU general purpose registers.
@@ -378,7 +374,6 @@ impl cpu::Vcpu for MshvVcpu {
.set_regs(&regs) .set_regs(&regs)
.map_err(|e| cpu::HypervisorCpuError::SetStandardRegs(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetStandardRegs(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Returns the vCPU special registers. /// Returns the vCPU special registers.
@@ -390,7 +385,6 @@ impl cpu::Vcpu for MshvVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetSpecialRegs(e.into()))? .map_err(|e| cpu::HypervisorCpuError::GetSpecialRegs(e.into()))?
.into()) .into())
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Sets the vCPU special registers. /// Sets the vCPU special registers.
@@ -401,7 +395,6 @@ impl cpu::Vcpu for MshvVcpu {
.set_sregs(&sregs) .set_sregs(&sregs)
.map_err(|e| cpu::HypervisorCpuError::SetSpecialRegs(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetSpecialRegs(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Returns the floating point state (FPU) from the vCPU. /// Returns the floating point state (FPU) from the vCPU.
@@ -413,7 +406,6 @@ impl cpu::Vcpu for MshvVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetFloatingPointRegs(e.into()))? .map_err(|e| cpu::HypervisorCpuError::GetFloatingPointRegs(e.into()))?
.into()) .into())
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Set the floating point state (FPU) of a vCPU. /// Set the floating point state (FPU) of a vCPU.
@@ -446,7 +438,6 @@ impl cpu::Vcpu for MshvVcpu {
Ok(succ) Ok(succ)
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Setup the model-specific registers (MSR) for this vCPU. /// Setup the model-specific registers (MSR) for this vCPU.
@@ -468,7 +459,6 @@ impl cpu::Vcpu for MshvVcpu {
/* We always have SynIC enabled on MSHV */ /* We always have SynIC enabled on MSHV */
Ok(()) Ok(())
} }
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
fn run(&self) -> std::result::Result<cpu::VmExit, cpu::HypervisorCpuError> { fn run(&self) -> std::result::Result<cpu::VmExit, cpu::HypervisorCpuError> {
let hv_message: hv_message = hv_message::default(); let hv_message: hv_message = hv_message::default();
@@ -986,59 +976,6 @@ impl cpu::Vcpu for MshvVcpu {
})?; })?;
} }
} }
SVM_EXITCODE_SNP_GUEST_REQUEST => {
let req_gpa =
info.__bindgen_anon_2.__bindgen_anon_1.sw_exit_info1;
let rsp_gpa =
info.__bindgen_anon_2.__bindgen_anon_1.sw_exit_info2;
let mshv_psp_req =
mshv_issue_psp_guest_request { req_gpa, rsp_gpa };
self.vm_fd
.psp_issue_guest_request(&mshv_psp_req)
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
debug!(
"SNP guest request: req_gpa {:0x} rsp_gpa {:0x}",
req_gpa, rsp_gpa
);
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 swei2_rw_gpa_arg)
.map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?;
}
SVM_EXITCODE_SNP_AP_CREATION => {
let vmsa_gpa =
info.__bindgen_anon_2.__bindgen_anon_1.sw_exit_info2;
let apic_id =
info.__bindgen_anon_2.__bindgen_anon_1.sw_exit_info1 >> 32;
debug!(
"SNP AP CREATE REQUEST with VMSA GPA {:0x}, and APIC ID {:?}",
vmsa_gpa, apic_id
);
let mshv_ap_create_req = mshv_sev_snp_ap_create {
vp_id: apic_id,
vmsa_gpa,
};
self.vm_fd
.sev_snp_ap_create(&mshv_ap_create_req)
.map_err(|e| cpu::HypervisorCpuError::RunVcpu(e.into()))?;
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 swei2_rw_gpa_arg)
.map_err(|e| cpu::HypervisorCpuError::GpaWrite(e.into()))?;
}
_ => panic!( _ => panic!(
"GHCB_INFO_NORMAL: Unhandled exit code: {:0x}", "GHCB_INFO_NORMAL: Unhandled exit code: {:0x}",
exit_code exit_code
@@ -1065,7 +1002,6 @@ impl cpu::Vcpu for MshvVcpu {
}, },
} }
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// X86 specific call to setup the CPUID registers. /// X86 specific call to setup the CPUID registers.
@@ -1079,7 +1015,6 @@ impl cpu::Vcpu for MshvVcpu {
.register_intercept_result_cpuid(&mshv_cpuid) .register_intercept_result_cpuid(&mshv_cpuid)
.map_err(|e| cpu::HypervisorCpuError::SetCpuid(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetCpuid(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// X86 specific call to retrieve the CPUID registers. /// X86 specific call to retrieve the CPUID registers.
@@ -1087,23 +1022,6 @@ impl cpu::Vcpu for MshvVcpu {
fn get_cpuid2(&self, _num_entries: usize) -> cpu::Result<Vec<CpuIdEntry>> { fn get_cpuid2(&self, _num_entries: usize) -> cpu::Result<Vec<CpuIdEntry>> {
Ok(self.cpuid.clone()) Ok(self.cpuid.clone())
} }
#[cfg(target_arch = "x86_64")]
///
/// X86 specific call to retrieve cpuid leaf
///
fn get_cpuid_values(
&self,
function: u32,
index: u32,
xfem: u64,
xss: u64,
) -> cpu::Result<[u32; 4]> {
self.fd
.get_cpuid_values(function, index, xfem, xss)
.map_err(|e| cpu::HypervisorCpuError::GetCpuidVales(e.into()))
}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller). /// Returns the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
@@ -1115,7 +1033,6 @@ impl cpu::Vcpu for MshvVcpu {
.map_err(|e| cpu::HypervisorCpuError::GetlapicState(e.into()))? .map_err(|e| cpu::HypervisorCpuError::GetlapicState(e.into()))?
.into()) .into())
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller). /// Sets the state of the LAPIC (Local Advanced Programmable Interrupt Controller).
@@ -1126,21 +1043,18 @@ impl cpu::Vcpu for MshvVcpu {
.set_lapic(&lapic) .set_lapic(&lapic)
.map_err(|e| cpu::HypervisorCpuError::SetLapicState(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetLapicState(e.into()))
} }
/// ///
/// Returns the vcpu's current "multiprocessing state". /// Returns the vcpu's current "multiprocessing state".
/// ///
fn get_mp_state(&self) -> cpu::Result<MpState> { fn get_mp_state(&self) -> cpu::Result<MpState> {
Ok(MpState::Mshv) Ok(MpState::Mshv)
} }
/// ///
/// Sets the vcpu's current "multiprocessing state". /// Sets the vcpu's current "multiprocessing state".
/// ///
fn set_mp_state(&self, _mp_state: MpState) -> cpu::Result<()> { fn set_mp_state(&self, _mp_state: MpState) -> cpu::Result<()> {
Ok(()) Ok(())
} }
/// ///
/// Set CPU state /// Set CPU state
/// ///
@@ -1166,7 +1080,6 @@ impl cpu::Vcpu for MshvVcpu {
.map_err(|e| cpu::HypervisorCpuError::SetDebugRegs(e.into()))?; .map_err(|e| cpu::HypervisorCpuError::SetDebugRegs(e.into()))?;
Ok(()) Ok(())
} }
/// ///
/// Get CPU State /// Get CPU State
/// ///
@@ -1203,7 +1116,6 @@ impl cpu::Vcpu for MshvVcpu {
} }
.into()) .into())
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Translate guest virtual address to guest physical address /// Translate guest virtual address to guest physical address
@@ -1220,7 +1132,6 @@ impl cpu::Vcpu for MshvVcpu {
Ok((gpa, result_code)) Ok((gpa, result_code))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Return the list of initial MSR entries for a VCPU /// Return the list of initial MSR entries for a VCPU
@@ -1253,7 +1164,6 @@ impl MshvVcpu {
.get_xsave() .get_xsave()
.map_err(|e| cpu::HypervisorCpuError::GetXsaveState(e.into())) .map_err(|e| cpu::HypervisorCpuError::GetXsaveState(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// X86 specific call that sets the vcpu's current "xsave struct". /// X86 specific call that sets the vcpu's current "xsave struct".
@@ -1263,7 +1173,6 @@ impl MshvVcpu {
.set_xsave(xsave) .set_xsave(xsave)
.map_err(|e| cpu::HypervisorCpuError::SetXsaveState(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetXsaveState(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// X86 specific call that returns the vcpu's current "xcrs". /// X86 specific call that returns the vcpu's current "xcrs".
@@ -1273,7 +1182,6 @@ impl MshvVcpu {
.get_xcrs() .get_xcrs()
.map_err(|e| cpu::HypervisorCpuError::GetXcsr(e.into())) .map_err(|e| cpu::HypervisorCpuError::GetXcsr(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// X86 specific call that sets the vcpu's current "xcrs". /// X86 specific call that sets the vcpu's current "xcrs".
@@ -1283,7 +1191,6 @@ impl MshvVcpu {
.set_xcrs(xcrs) .set_xcrs(xcrs)
.map_err(|e| cpu::HypervisorCpuError::SetXcsr(e.into())) .map_err(|e| cpu::HypervisorCpuError::SetXcsr(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Returns currently pending exceptions, interrupts, and NMIs as well as related /// Returns currently pending exceptions, interrupts, and NMIs as well as related
@@ -1294,7 +1201,6 @@ impl MshvVcpu {
.get_vcpu_events() .get_vcpu_events()
.map_err(|e| cpu::HypervisorCpuError::GetVcpuEvents(e.into())) .map_err(|e| cpu::HypervisorCpuError::GetVcpuEvents(e.into()))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Sets pending exceptions, interrupts, and NMIs as well as related states /// Sets pending exceptions, interrupts, and NMIs as well as related states
@@ -1474,7 +1380,6 @@ impl vm::Vm for MshvVm {
fn set_identity_map_address(&self, _address: u64) -> vm::Result<()> { fn set_identity_map_address(&self, _address: u64) -> vm::Result<()> {
Ok(()) Ok(())
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// ///
/// Sets the address of the three-page region in the VM's address space. /// Sets the address of the three-page region in the VM's address space.
@@ -1482,14 +1387,12 @@ impl vm::Vm for MshvVm {
fn set_tss_address(&self, _offset: usize) -> vm::Result<()> { fn set_tss_address(&self, _offset: usize) -> vm::Result<()> {
Ok(()) Ok(())
} }
/// ///
/// Creates an in-kernel interrupt controller. /// Creates an in-kernel interrupt controller.
/// ///
fn create_irq_chip(&self) -> vm::Result<()> { fn create_irq_chip(&self) -> vm::Result<()> {
Ok(()) Ok(())
} }
/// ///
/// Registers an event that will, when signaled, trigger the `gsi` IRQ. /// Registers an event that will, when signaled, trigger the `gsi` IRQ.
/// ///
@@ -1502,7 +1405,6 @@ impl vm::Vm for MshvVm {
Ok(()) Ok(())
} }
/// ///
/// Unregisters an event that will, when signaled, trigger the `gsi` IRQ. /// Unregisters an event that will, when signaled, trigger the `gsi` IRQ.
/// ///
@@ -1515,7 +1417,6 @@ impl vm::Vm for MshvVm {
Ok(()) Ok(())
} }
/// ///
/// Creates a VcpuFd object from a vcpu RawFd. /// Creates a VcpuFd object from a vcpu RawFd.
/// ///
@@ -1534,22 +1435,17 @@ impl vm::Vm for MshvVm {
cpuid: Vec::new(), cpuid: Vec::new(),
msrs: self.msrs.clone(), msrs: self.msrs.clone(),
vm_ops, vm_ops,
#[cfg(feature = "sev_snp")]
vm_fd: self.fd.clone(),
}; };
Ok(Arc::new(vcpu)) Ok(Arc::new(vcpu))
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn enable_split_irq(&self) -> vm::Result<()> { fn enable_split_irq(&self) -> vm::Result<()> {
Ok(()) Ok(())
} }
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn enable_sgx_attribute(&self, _file: File) -> vm::Result<()> { fn enable_sgx_attribute(&self, _file: File) -> vm::Result<()> {
Ok(()) Ok(())
} }
fn register_ioevent( fn register_ioevent(
&self, &self,
fd: &EventFd, fd: &EventFd,
@@ -1580,7 +1476,6 @@ impl vm::Vm for MshvVm {
.map_err(|e| vm::HypervisorVmError::RegisterIoEvent(e.into())) .map_err(|e| vm::HypervisorVmError::RegisterIoEvent(e.into()))
} }
} }
/// Unregister an event from a certain address it has been previously registered to. /// Unregister an event from a certain address it has been previously registered to.
fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> vm::Result<()> { fn unregister_ioevent(&self, fd: &EventFd, addr: &IoEventAddress) -> vm::Result<()> {
let addr = &mshv_ioctls::IoEventAddress::from(*addr); let addr = &mshv_ioctls::IoEventAddress::from(*addr);
@@ -1705,7 +1600,6 @@ impl vm::Vm for MshvVm {
.set_msi_routing(&msi_routing[0]) .set_msi_routing(&msi_routing[0])
.map_err(|e| vm::HypervisorVmError::SetGsiRouting(e.into())) .map_err(|e| vm::HypervisorVmError::SetGsiRouting(e.into()))
} }
/// ///
/// Start logging dirty pages /// Start logging dirty pages
/// ///
@@ -1714,7 +1608,6 @@ impl vm::Vm for MshvVm {
.enable_dirty_page_tracking() .enable_dirty_page_tracking()
.map_err(|e| vm::HypervisorVmError::StartDirtyLog(e.into())) .map_err(|e| vm::HypervisorVmError::StartDirtyLog(e.into()))
} }
/// ///
/// Stop logging dirty pages /// Stop logging dirty pages
/// ///
@@ -1733,7 +1626,6 @@ impl vm::Vm for MshvVm {
.map_err(|e| vm::HypervisorVmError::StartDirtyLog(e.into()))?; .map_err(|e| vm::HypervisorVmError::StartDirtyLog(e.into()))?;
Ok(()) Ok(())
} }
/// ///
/// Get dirty pages bitmap (one bit per page) /// Get dirty pages bitmap (one bit per page)
/// ///
@@ -1746,24 +1638,20 @@ impl vm::Vm for MshvVm {
) )
.map_err(|e| vm::HypervisorVmError::GetDirtyLog(e.into())) .map_err(|e| vm::HypervisorVmError::GetDirtyLog(e.into()))
} }
/// Retrieve guest clock. /// Retrieve guest clock.
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn get_clock(&self) -> vm::Result<ClockData> { fn get_clock(&self) -> vm::Result<ClockData> {
Ok(ClockData::Mshv) Ok(ClockData::Mshv)
} }
/// Set guest clock. /// Set guest clock.
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn set_clock(&self, _data: &ClockData) -> vm::Result<()> { fn set_clock(&self, _data: &ClockData) -> vm::Result<()> {
Ok(()) Ok(())
} }
/// Downcast to the underlying MshvVm type /// Downcast to the underlying MshvVm type
fn as_any(&self) -> &dyn Any { fn as_any(&self) -> &dyn Any {
self self
} }
/// Initialize the SEV-SNP VM /// Initialize the SEV-SNP VM
#[cfg(feature = "sev_snp")] #[cfg(feature = "sev_snp")]
fn sev_snp_init(&self) -> vm::Result<()> { fn sev_snp_init(&self) -> vm::Result<()> {
@@ -1775,9 +1663,6 @@ impl vm::Vm for MshvVm {
.map_err(|e| vm::HypervisorVmError::InitializeSevSnp(e.into())) .map_err(|e| vm::HypervisorVmError::InitializeSevSnp(e.into()))
} }
///
/// Importing isolated pages, these pages will be used
/// for the PSP(Platform Security Processor) measurement.
#[cfg(feature = "sev_snp")] #[cfg(feature = "sev_snp")]
fn import_isolated_pages( fn import_isolated_pages(
&self, &self,
@@ -1805,11 +1690,6 @@ impl vm::Vm for MshvVm {
.import_isolated_pages(&isolated_pages[0]) .import_isolated_pages(&isolated_pages[0])
.map_err(|e| vm::HypervisorVmError::ImportIsolatedPages(e.into())) .map_err(|e| vm::HypervisorVmError::ImportIsolatedPages(e.into()))
} }
///
/// Complete isolated import, telling the hypervisor that
/// importing the pages to guest memory is complete.
///
#[cfg(feature = "sev_snp")] #[cfg(feature = "sev_snp")]
fn complete_isolated_import( fn complete_isolated_import(
&self, &self,

View File

@@ -5,4 +5,4 @@ authors = ["The Chromium OS Authors"]
edition = "2021" edition = "2021"
[dependencies] [dependencies]
vmm-sys-util = "0.12.1" vmm-sys-util = "0.11.0"

View File

@@ -8,18 +8,18 @@ edition = "2021"
epoll = "4.3.3" epoll = "4.3.3"
getrandom = "0.2.10" getrandom = "0.2.10"
libc = "0.2.147" libc = "0.2.147"
log = "0.4.20" log = "0.4.17"
net_gen = { path = "../net_gen" } net_gen = { path = "../net_gen" }
rate_limiter = { path = "../rate_limiter" } rate_limiter = { path = "../rate_limiter" }
serde = "1.0.168" serde = "1.0.168"
thiserror = "1.0.52" thiserror = "1.0.40"
versionize = "0.2.0" versionize = "0.1.10"
versionize_derive = "0.1.6" versionize_derive = "0.1.4"
virtio-bindings = "0.2.0" virtio-bindings = "0.2.0"
virtio-queue = "0.11.0" virtio-queue = "0.9.0"
vm-memory = { version = "0.14.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] } vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-virtio = { path = "../vm-virtio" } vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = "0.12.1" vmm-sys-util = "0.11.0"
[dev-dependencies] [dev-dependencies]
once_cell = "1.18.0" once_cell = "1.18.0"

View File

@@ -72,10 +72,6 @@ pub fn open_tap(
let mut taps: Vec<Tap> = Vec::new(); let mut taps: Vec<Tap> = Vec::new();
let mut ifname: String = String::new(); let mut ifname: String = String::new();
let vnet_hdr_size = vnet_hdr_len() as i32; let vnet_hdr_size = vnet_hdr_len() as i32;
// Check if the given interface exists before we create it.
let tap_existed = if_name.map_or(false, |n| {
Path::new(&format!("/sys/class/net/{n}")).exists()
});
// In case the tap interface already exists, check if the number of // In case the tap interface already exists, check if the number of
// queues is appropriate. The tap might not support multiqueue while // queues is appropriate. The tap might not support multiqueue while
@@ -91,19 +87,11 @@ pub fn open_tap(
Some(name) => Tap::open_named(name, num_rx_q, flags).map_err(Error::TapOpen)?, Some(name) => Tap::open_named(name, num_rx_q, flags).map_err(Error::TapOpen)?,
None => Tap::new(num_rx_q).map_err(Error::TapOpen)?, None => Tap::new(num_rx_q).map_err(Error::TapOpen)?,
}; };
// Don't overwrite ip configuration of existing interfaces: if let Some(ip) = ip_addr {
if !tap_existed { tap.set_ip_addr(ip).map_err(Error::TapSetIp)?;
if let Some(ip) = ip_addr { }
tap.set_ip_addr(ip).map_err(Error::TapSetIp)?; if let Some(mask) = netmask {
} tap.set_netmask(mask).map_err(Error::TapSetNetmask)?;
if let Some(mask) = netmask {
tap.set_netmask(mask).map_err(Error::TapSetNetmask)?;
}
} else {
warn!(
"Tap {} already exists. IP configuration will not be overwritten.",
if_name.unwrap_or_default()
);
} }
if let Some(mac) = host_mac { if let Some(mac) = host_mac {
tap.set_mac_addr(*mac).map_err(Error::TapSetMac)? tap.set_mac_addr(*mac).map_err(Error::TapSetMac)?

View File

@@ -17,14 +17,14 @@ vfio-bindings = { git = "https://github.com/rust-vmm/vfio", branch = "main", fea
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false } 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" } vfio_user = { git = "https://github.com/rust-vmm/vfio-user", branch = "main" }
vmm-sys-util = "0.12.1" vmm-sys-util = "0.11.0"
libc = "0.2.147" libc = "0.2.147"
log = "0.4.20" log = "0.4.17"
serde = { version = "1.0.168", features = ["derive"] } serde = { version = "1.0.168", features = ["derive"] }
thiserror = "1.0.52" thiserror = "1.0.40"
versionize = "0.2.0" versionize = "0.1.10"
versionize_derive = "0.1.6" versionize_derive = "0.1.4"
vm-allocator = { path = "../vm-allocator" } vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" } vm-device = { path = "../vm-device" }
vm-memory = { version = "0.14.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] } vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-migration = { path = "../vm-migration" } vm-migration = { path = "../vm-migration" }

View File

@@ -58,8 +58,7 @@ pub trait PciDevice: BusDevice {
fn allocate_bars( fn allocate_bars(
&mut self, &mut self,
_allocator: &Arc<Mutex<SystemAllocator>>, _allocator: &Arc<Mutex<SystemAllocator>>,
_mmio32_allocator: &mut AddressAllocator, _mmio_allocator: &mut AddressAllocator,
_mmio64_allocator: &mut AddressAllocator,
_resources: Option<Vec<Resource>>, _resources: Option<Vec<Resource>>,
) -> Result<Vec<PciBarConfiguration>> { ) -> Result<Vec<PciBarConfiguration>> {
Ok(Vec::new()) Ok(Vec::new())
@@ -69,8 +68,7 @@ pub trait PciDevice: BusDevice {
fn free_bars( fn free_bars(
&mut self, &mut self,
_allocator: &mut SystemAllocator, _allocator: &mut SystemAllocator,
_mmio32_allocator: &mut AddressAllocator, _mmio_allocator: &mut AddressAllocator,
_mmio64_allocator: &mut AddressAllocator,
) -> Result<()> { ) -> Result<()> {
Ok(()) Ok(())
} }

View File

@@ -529,13 +529,10 @@ impl VfioCommon {
} }
} }
// The `allocator` argument is unused on `aarch64`
#[allow(unused_variables)]
pub(crate) fn allocate_bars( pub(crate) fn allocate_bars(
&mut self, &mut self,
allocator: &Arc<Mutex<SystemAllocator>>, allocator: &Arc<Mutex<SystemAllocator>>,
mmio32_allocator: &mut AddressAllocator, mmio_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>, resources: Option<Vec<Resource>>,
) -> Result<Vec<PciBarConfiguration>, PciDeviceError> { ) -> Result<Vec<PciBarConfiguration>, PciDeviceError> {
let mut bars = Vec::new(); let mut bars = Vec::new();
@@ -684,23 +681,26 @@ impl VfioCommon {
} }
PciBarRegionType::Memory32BitRegion => { PciBarRegionType::Memory32BitRegion => {
// BAR allocation must be naturally aligned // BAR allocation must be naturally aligned
mmio32_allocator allocator
.allocate(restored_bar_addr, region_size, Some(region_size)) .lock()
.unwrap()
.allocate_mmio_hole_addresses(
restored_bar_addr,
region_size,
Some(region_size),
)
.ok_or(PciDeviceError::IoAllocationFailed(region_size))? .ok_or(PciDeviceError::IoAllocationFailed(region_size))?
} }
PciBarRegionType::Memory64BitRegion => { PciBarRegionType::Memory64BitRegion => {
// We need do some fixup to keep MMIO RW region and msix cap region page size // We need do some fixup to keep MMIO RW region and msix cap region page size
// aligned. // aligned.
region_size = self.fixup_msix_region(bar_id, region_size); region_size = self.fixup_msix_region(bar_id, region_size);
mmio64_allocator mmio_allocator
.allocate( .allocate(
restored_bar_addr, restored_bar_addr,
region_size, region_size,
Some(std::cmp::max( // SAFETY: FFI call. Trivially safe.
// SAFETY: FFI call. Trivially safe. Some(unsafe { sysconf(_SC_PAGESIZE) as GuestUsize }),
unsafe { sysconf(_SC_PAGESIZE) as GuestUsize },
region_size,
)),
) )
.ok_or(PciDeviceError::IoAllocationFailed(region_size))? .ok_or(PciDeviceError::IoAllocationFailed(region_size))?
} }
@@ -742,13 +742,10 @@ impl VfioCommon {
Ok(bars) Ok(bars)
} }
// The `allocator` argument is unused on `aarch64`
#[allow(unused_variables)]
pub(crate) fn free_bars( pub(crate) fn free_bars(
&mut self, &mut self,
allocator: &mut SystemAllocator, allocator: &mut SystemAllocator,
mmio32_allocator: &mut AddressAllocator, mmio_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
) -> Result<(), PciDeviceError> { ) -> Result<(), PciDeviceError> {
for region in self.mmio_regions.iter() { for region in self.mmio_regions.iter() {
match region.type_ { match region.type_ {
@@ -759,10 +756,10 @@ impl VfioCommon {
error!("I/O region is not supported"); error!("I/O region is not supported");
} }
PciBarRegionType::Memory32BitRegion => { PciBarRegionType::Memory32BitRegion => {
mmio32_allocator.free(region.start, region.length); allocator.free_mmio_hole_addresses(region.start, region.length);
} }
PciBarRegionType::Memory64BitRegion => { PciBarRegionType::Memory64BitRegion => {
mmio64_allocator.free(region.start, region.length); mmio_allocator.free(region.start, region.length);
} }
} }
} }
@@ -1697,22 +1694,19 @@ impl PciDevice for VfioPciDevice {
fn allocate_bars( fn allocate_bars(
&mut self, &mut self,
allocator: &Arc<Mutex<SystemAllocator>>, allocator: &Arc<Mutex<SystemAllocator>>,
mmio32_allocator: &mut AddressAllocator, mmio_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>, resources: Option<Vec<Resource>>,
) -> Result<Vec<PciBarConfiguration>, PciDeviceError> { ) -> Result<Vec<PciBarConfiguration>, PciDeviceError> {
self.common self.common
.allocate_bars(allocator, mmio32_allocator, mmio64_allocator, resources) .allocate_bars(allocator, mmio_allocator, resources)
} }
fn free_bars( fn free_bars(
&mut self, &mut self,
allocator: &mut SystemAllocator, allocator: &mut SystemAllocator,
mmio32_allocator: &mut AddressAllocator, mmio_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
) -> Result<(), PciDeviceError> { ) -> Result<(), PciDeviceError> {
self.common self.common.free_bars(allocator, mmio_allocator)
.free_bars(allocator, mmio32_allocator, mmio64_allocator)
} }
fn write_config_register( fn write_config_register(

View File

@@ -397,22 +397,19 @@ impl PciDevice for VfioUserPciDevice {
fn allocate_bars( fn allocate_bars(
&mut self, &mut self,
allocator: &Arc<Mutex<SystemAllocator>>, allocator: &Arc<Mutex<SystemAllocator>>,
mmio32_allocator: &mut AddressAllocator, mmio_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>, resources: Option<Vec<Resource>>,
) -> Result<Vec<PciBarConfiguration>, PciDeviceError> { ) -> Result<Vec<PciBarConfiguration>, PciDeviceError> {
self.common self.common
.allocate_bars(allocator, mmio32_allocator, mmio64_allocator, resources) .allocate_bars(allocator, mmio_allocator, resources)
} }
fn free_bars( fn free_bars(
&mut self, &mut self,
allocator: &mut SystemAllocator, allocator: &mut SystemAllocator,
mmio32_allocator: &mut AddressAllocator, mmio_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
) -> Result<(), PciDeviceError> { ) -> Result<(), PciDeviceError> {
self.common self.common.free_bars(allocator, mmio_allocator)
.free_bars(allocator, mmio32_allocator, mmio64_allocator)
} }
fn as_any(&mut self) -> &mut dyn Any { fn as_any(&mut self) -> &mut dyn Any {

View File

@@ -6,7 +6,7 @@ edition = "2021"
build = "../build.rs" build = "../build.rs"
[dependencies] [dependencies]
clap = { version = "4.4.7", features = ["wrap_help"] } clap = { version = "4.0.32", features = ["wrap_help"] }
dirs = "5.0.0" dirs = "5.0.0"
serde = { version = "1.0.168", features = ["rc", "derive"] } serde = { version = "1.0.168", features = ["rc", "derive"] }
serde_json = "1.0.107" serde_json = "1.0.107"

View File

@@ -19,7 +19,6 @@ pub const FOCAL_IMAGE_NAME: &str = "focal-server-cloudimg-amd64-custom-20210609-
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
pub const FOCAL_IMAGE_NAME: &str = "focal-server-cloudimg-arm64-custom-20210929-0-update-tool.raw"; pub const FOCAL_IMAGE_NAME: &str = "focal-server-cloudimg-arm64-custom-20210929-0-update-tool.raw";
#[allow(dead_code)]
#[derive(Debug)] #[derive(Debug)]
enum Error { enum Error {
BootTimeParse, BootTimeParse,

View File

@@ -5,6 +5,5 @@ edition = "2021"
[dependencies] [dependencies]
libc = "0.2.147" libc = "0.2.147"
log = "0.4.20" log = "0.4.17"
thiserror = "1.0.40" vmm-sys-util = "0.11.0"
vmm-sys-util = "0.12.1"

View File

@@ -1,12 +1,4 @@
- [v37.1](#v371) - [v36.1](#v361)
- [v37.0](#v370)
- [Long Term Support (LTS) Release](#long-term-support-lts-release)
- [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)
- [Contributors](#contributors)
- [v36.0](#v360) - [v36.0](#v360)
- [Command Line Changes](#command-line-changes) - [Command Line Changes](#command-line-changes)
- [Enabled Features Reported via API Endpoint and CLI](#enabled-features-reported-via-api-endpoint-and-cli) - [Enabled Features Reported via API Endpoint and CLI](#enabled-features-reported-via-api-endpoint-and-cli)
@@ -15,31 +7,31 @@
- [Unix Socket Backend for Serial Port](#unix-socket-backend-for-serial-port) - [Unix Socket Backend for Serial Port](#unix-socket-backend-for-serial-port)
- [AIO Backend for Block Devices](#aio-backend-for-block-devices) - [AIO Backend for Block Devices](#aio-backend-for-block-devices)
- [Documentation Improvements](#documentation-improvements) - [Documentation Improvements](#documentation-improvements)
- [Notable Bug Fixes](#notable-bug-fixes-1) - [Notable Bug Fixes](#notable-bug-fixes)
- [Contributors](#contributors-1) - [Contributors](#contributors)
- [v35.0](#v350) - [v35.0](#v350)
- [`virtio-vsock` Support for Linux Guest Kernel v6.3+](#virtio-vsock-support-for-linux-guest-kernel-v63) - [`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) - [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) - [vCPU TSC Frequency Included in Migration State](#vcpu-tsc-frequency-included-in-migration-state)
- [Notable Bug Fixes](#notable-bug-fixes-2) - [Notable Bug Fixes](#notable-bug-fixes-1)
- [Contributors](#contributors-2) - [Contributors](#contributors-1)
- [v34.0](#v340) - [v34.0](#v340)
- [Paravirtualised Panic Device Support](#paravirtualised-panic-device-support) - [Paravirtualised Panic Device Support](#paravirtualised-panic-device-support)
- [Improvements to VM Core Dump](#improvements-to-vm-core-dump) - [Improvements to VM Core Dump](#improvements-to-vm-core-dump)
- [QCOW2 Support for Backing Files](#qcow2-support-for-backing-files) - [QCOW2 Support for Backing Files](#qcow2-support-for-backing-files)
- [Minimum Host Kernel Bump](#minimum-host-kernel-bump) - [Minimum Host Kernel Bump](#minimum-host-kernel-bump)
- [Notable Bug Fixes](#notable-bug-fixes-3) - [Notable Bug Fixes](#notable-bug-fixes-2)
- [Contributors](#contributors-3) - [Contributors](#contributors-2)
- [v33.0](#v330) - [v33.0](#v330)
- [D-Bus based API](#d-bus-based-api) - [D-Bus based API](#d-bus-based-api)
- [Expose Host CPU Cache Details for AArch64](#expose-host-cpu-cache-details-for-aarch64) - [Expose Host CPU Cache Details for AArch64](#expose-host-cpu-cache-details-for-aarch64)
- [Notable Bug Fixes](#notable-bug-fixes-4) - [Notable Bug Fixes](#notable-bug-fixes-3)
- [Contributors](#contributors-4) - [Contributors](#contributors-3)
- [v32.0](#v320) - [v32.0](#v320)
- [Increased PCI Segment Limit](#increased-pci-segment-limit) - [Increased PCI Segment Limit](#increased-pci-segment-limit)
- [API Changes](#api-changes) - [API Changes](#api-changes)
- [Notable Bug Fixes](#notable-bug-fixes-5) - [Notable Bug Fixes](#notable-bug-fixes-4)
- [Contributors](#contributors-5) - [Contributors](#contributors-4)
- [v31.1](#v311) - [v31.1](#v311)
- [v31.0](#v310) - [v31.0](#v310)
- [Update to Latest `acpi_tables`](#update-to-latest-acpi_tables) - [Update to Latest `acpi_tables`](#update-to-latest-acpi_tables)
@@ -47,15 +39,15 @@
- [Improvements on Console `SIGWINCH` Handler](#improvements-on-console-sigwinch-handler) - [Improvements on Console `SIGWINCH` Handler](#improvements-on-console-sigwinch-handler)
- [Remove Directory Support from `MemoryZoneConfig::file`](#remove-directory-support-from-memoryzoneconfigfile) - [Remove Directory Support from `MemoryZoneConfig::file`](#remove-directory-support-from-memoryzoneconfigfile)
- [Documentation Improvements](#documentation-improvements-1) - [Documentation Improvements](#documentation-improvements-1)
- [Notable Bug Fixes](#notable-bug-fixes-6) - [Notable Bug Fixes](#notable-bug-fixes-5)
- [Contributors](#contributors-6) - [Contributors](#contributors-5)
- [v30.0](#v300) - [v30.0](#v300)
- [Command Line Changes for Reduced Binary Size](#command-line-changes-for-reduced-binary-size) - [Command Line Changes for Reduced Binary Size](#command-line-changes-for-reduced-binary-size)
- [Basic vfio-user Server Support](#basic-vfio-user-server-support) - [Basic vfio-user Server Support](#basic-vfio-user-server-support)
- [Heap Profiling Support](#heap-profiling-support) - [Heap Profiling Support](#heap-profiling-support)
- [Documentation Improvements](#documentation-improvements-2) - [Documentation Improvements](#documentation-improvements-2)
- [Notable Bug Fixes](#notable-bug-fixes-7) - [Notable Bug Fixes](#notable-bug-fixes-6)
- [Contributors](#contributors-7) - [Contributors](#contributors-6)
- [v28.2](#v282) - [v28.2](#v282)
- [v29.0](#v290) - [v29.0](#v290)
- [Release Binary Supports Both MSHV and KVM](#release-binary-supports-both-mshv-and-kvm) - [Release Binary Supports Both MSHV and KVM](#release-binary-supports-both-mshv-and-kvm)
@@ -65,20 +57,20 @@
- [`AArch64` Documentation Integration](#aarch64-documentation-integration) - [`AArch64` Documentation Integration](#aarch64-documentation-integration)
- [`virtio-block` Counters Enhancement](#virtio-block-counters-enhancement) - [`virtio-block` Counters Enhancement](#virtio-block-counters-enhancement)
- [TCP Offload Control](#tcp-offload-control) - [TCP Offload Control](#tcp-offload-control)
- [Notable Bug Fixes](#notable-bug-fixes-8) - [Notable Bug Fixes](#notable-bug-fixes-7)
- [Removals](#removals) - [Removals](#removals)
- [Deprecations](#deprecations) - [Deprecations](#deprecations)
- [Contributors](#contributors-8) - [Contributors](#contributors-7)
- [v28.1](#v281) - [v28.1](#v281)
- [v28.0](#v280) - [v28.0](#v280)
- [Community Engagement (Reminder)](#community-engagement-reminder) - [Community Engagement (Reminder)](#community-engagement-reminder)
- [Long Term Support (LTS) Release](#long-term-support-lts-release-1) - [Long Term Support (LTS) Release](#long-term-support-lts-release)
- [Virtualised TPM Support](#virtualised-tpm-support) - [Virtualised TPM Support](#virtualised-tpm-support)
- [Transparent Huge Page Support](#transparent-huge-page-support) - [Transparent Huge Page Support](#transparent-huge-page-support)
- [README Quick Start Improved](#readme-quick-start-improved) - [README Quick Start Improved](#readme-quick-start-improved)
- [Notable Bug Fixes](#notable-bug-fixes-9) - [Notable Bug Fixes](#notable-bug-fixes-8)
- [Removals](#removals-1) - [Removals](#removals-1)
- [Contributors](#contributors-9) - [Contributors](#contributors-8)
- [v27.0](#v270) - [v27.0](#v270)
- [Community Engagement](#community-engagement) - [Community Engagement](#community-engagement)
- [Prebuilt Packages](#prebuilt-packages) - [Prebuilt Packages](#prebuilt-packages)
@@ -87,41 +79,41 @@
- [Simplified Build Feature Flags](#simplified-build-feature-flags) - [Simplified Build Feature Flags](#simplified-build-feature-flags)
- [Asynchronous Kernel Loading](#asynchronous-kernel-loading) - [Asynchronous Kernel Loading](#asynchronous-kernel-loading)
- [GDB Support for AArch64](#gdb-support-for-aarch64) - [GDB Support for AArch64](#gdb-support-for-aarch64)
- [Notable Bug Fixes](#notable-bug-fixes-10) - [Notable Bug Fixes](#notable-bug-fixes-9)
- [Deprecations](#deprecations-1) - [Deprecations](#deprecations-1)
- [Contributors](#contributors-10) - [Contributors](#contributors-9)
- [v26.0](#v260) - [v26.0](#v260)
- [SMBIOS Improvements via `--platform`](#smbios-improvements-via---platform) - [SMBIOS Improvements via `--platform`](#smbios-improvements-via---platform)
- [Unified Binary MSHV and KVM Support](#unified-binary-mshv-and-kvm-support) - [Unified Binary MSHV and KVM Support](#unified-binary-mshv-and-kvm-support)
- [Notable Bug Fixes](#notable-bug-fixes-11) - [Notable Bug Fixes](#notable-bug-fixes-10)
- [Deprecations](#deprecations-2) - [Deprecations](#deprecations-2)
- [Removals](#removals-2) - [Removals](#removals-2)
- [Contributors](#contributors-11) - [Contributors](#contributors-10)
- [v25.0](#v250) - [v25.0](#v250)
- [`ch-remote` Improvements](#ch-remote-improvements-1) - [`ch-remote` Improvements](#ch-remote-improvements-1)
- [VM "Coredump" Support](#vm-coredump-support) - [VM "Coredump" Support](#vm-coredump-support)
- [Notable Bug Fixes](#notable-bug-fixes-12) - [Notable Bug Fixes](#notable-bug-fixes-11)
- [Removals](#removals-3) - [Removals](#removals-3)
- [Contributors](#contributors-12) - [Contributors](#contributors-11)
- [v24.0](#v240) - [v24.0](#v240)
- [Bypass Mode for `virtio-iommu`](#bypass-mode-for-virtio-iommu) - [Bypass Mode for `virtio-iommu`](#bypass-mode-for-virtio-iommu)
- [Ensure Identifiers Uniqueness](#ensure-identifiers-uniqueness) - [Ensure Identifiers Uniqueness](#ensure-identifiers-uniqueness)
- [Sparse Mmap support](#sparse-mmap-support) - [Sparse Mmap support](#sparse-mmap-support)
- [Expose Platform Serial Number](#expose-platform-serial-number) - [Expose Platform Serial Number](#expose-platform-serial-number)
- [Notable Bug Fixes](#notable-bug-fixes-13) - [Notable Bug Fixes](#notable-bug-fixes-12)
- [Notable Improvements](#notable-improvements) - [Notable Improvements](#notable-improvements)
- [Deprecations](#deprecations-3) - [Deprecations](#deprecations-3)
- [New on the Website](#new-on-the-website) - [New on the Website](#new-on-the-website)
- [Contributors](#contributors-13) - [Contributors](#contributors-12)
- [v23.1](#v231) - [v23.1](#v231)
- [v23.0](#v230) - [v23.0](#v230)
- [vDPA Support](#vdpa-support) - [vDPA Support](#vdpa-support)
- [Updated OS Support list](#updated-os-support-list) - [Updated OS Support list](#updated-os-support-list)
- [`AArch64` Memory Map Improvements](#aarch64-memory-map-improvements) - [`AArch64` Memory Map Improvements](#aarch64-memory-map-improvements)
- [`AMX` Support](#amx-support) - [`AMX` Support](#amx-support)
- [Notable Bug Fixes](#notable-bug-fixes-14) - [Notable Bug Fixes](#notable-bug-fixes-13)
- [Deprecations](#deprecations-4) - [Deprecations](#deprecations-4)
- [Contributors](#contributors-14) - [Contributors](#contributors-13)
- [v22.1](#v221) - [v22.1](#v221)
- [v22.0](#v220) - [v22.0](#v220)
- [GDB Debug Stub Support](#gdb-debug-stub-support) - [GDB Debug Stub Support](#gdb-debug-stub-support)
@@ -132,13 +124,13 @@
- [PMU Support for AArch64](#pmu-support-for-aarch64) - [PMU Support for AArch64](#pmu-support-for-aarch64)
- [Documentation Under CC-BY-4.0 License](#documentation-under-cc-by-40-license) - [Documentation Under CC-BY-4.0 License](#documentation-under-cc-by-40-license)
- [Deprecation of "Classic" `virtiofsd`](#deprecation-of-classic-virtiofsd) - [Deprecation of "Classic" `virtiofsd`](#deprecation-of-classic-virtiofsd)
- [Notable Bug Fixes](#notable-bug-fixes-15) - [Notable Bug Fixes](#notable-bug-fixes-14)
- [Contributors](#contributors-15) - [Contributors](#contributors-14)
- [v21.0](#v210) - [v21.0](#v210)
- [Efficient Local Live Migration (for Live Upgrade)](#efficient-local-live-migration-for-live-upgrade) - [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) - [Recommended Kernel is Now 5.15](#recommended-kernel-is-now-515)
- [Notable Bug fixes](#notable-bug-fixes-16) - [Notable Bug fixes](#notable-bug-fixes-15)
- [Contributors](#contributors-16) - [Contributors](#contributors-15)
- [v20.2](#v202) - [v20.2](#v202)
- [v20.1](#v201) - [v20.1](#v201)
- [v20.0](#v200) - [v20.0](#v200)
@@ -147,8 +139,8 @@
- [Improved VFIO support](#improved-vfio-support) - [Improved VFIO support](#improved-vfio-support)
- [Safer code](#safer-code) - [Safer code](#safer-code)
- [Extended documentation](#extended-documentation) - [Extended documentation](#extended-documentation)
- [Notable bug fixes](#notable-bug-fixes-17) - [Notable bug fixes](#notable-bug-fixes-16)
- [Contributors](#contributors-17) - [Contributors](#contributors-16)
- [v19.0](#v190) - [v19.0](#v190)
- [Improved PTY handling for serial and `virtio-console`](#improved-pty-handling-for-serial-and-virtio-console) - [Improved PTY handling for serial and `virtio-console`](#improved-pty-handling-for-serial-and-virtio-console)
- [PCI boot time optimisations](#pci-boot-time-optimisations) - [PCI boot time optimisations](#pci-boot-time-optimisations)
@@ -156,8 +148,8 @@
- [Live migration enhancements](#live-migration-enhancements) - [Live migration enhancements](#live-migration-enhancements)
- [`virtio-mem` support with `vfio-user`](#virtio-mem-support-with-vfio-user) - [`virtio-mem` support with `vfio-user`](#virtio-mem-support-with-vfio-user)
- [AArch64 for `virtio-iommu`](#aarch64-for-virtio-iommu) - [AArch64 for `virtio-iommu`](#aarch64-for-virtio-iommu)
- [Notable bug fixes](#notable-bug-fixes-18) - [Notable bug fixes](#notable-bug-fixes-17)
- [Contributors](#contributors-18) - [Contributors](#contributors-17)
- [v18.0](#v180) - [v18.0](#v180)
- [Experimental User Device (`vfio-user`) support](#experimental-user-device-vfio-user-support) - [Experimental User Device (`vfio-user`) support](#experimental-user-device-vfio-user-support)
- [Migration support for `vhost-user` devices](#migration-support-for-vhost-user-devices) - [Migration support for `vhost-user` devices](#migration-support-for-vhost-user-devices)
@@ -167,23 +159,23 @@
- [Live migration on MSHV hypervisor](#live-migration-on-mshv-hypervisor) - [Live migration on MSHV hypervisor](#live-migration-on-mshv-hypervisor)
- [AArch64 CPU topology support](#aarch64-cpu-topology-support) - [AArch64 CPU topology support](#aarch64-cpu-topology-support)
- [Power button support on AArch64](#power-button-support-on-aarch64) - [Power button support on AArch64](#power-button-support-on-aarch64)
- [Notable bug fixes](#notable-bug-fixes-19) - [Notable bug fixes](#notable-bug-fixes-18)
- [Contributors](#contributors-19) - [Contributors](#contributors-18)
- [v17.0](#v170) - [v17.0](#v170)
- [ARM64 NUMA support using ACPI](#arm64-numa-support-using-acpi) - [ARM64 NUMA support using ACPI](#arm64-numa-support-using-acpi)
- [`Seccomp` support for MSHV backend](#seccomp-support-for-mshv-backend) - [`Seccomp` support for MSHV backend](#seccomp-support-for-mshv-backend)
- [Hotplug of `macvtap` devices](#hotplug-of-macvtap-devices) - [Hotplug of `macvtap` devices](#hotplug-of-macvtap-devices)
- [Improved SGX support](#improved-sgx-support) - [Improved SGX support](#improved-sgx-support)
- [Inflight tracking for `vhost-user` devices](#inflight-tracking-for-vhost-user-devices) - [Inflight tracking for `vhost-user` devices](#inflight-tracking-for-vhost-user-devices)
- [Notable bug fixes](#notable-bug-fixes-20) - [Notable bug fixes](#notable-bug-fixes-19)
- [Contributors](#contributors-20) - [Contributors](#contributors-19)
- [v16.0](#v160) - [v16.0](#v160)
- [Improved live migration support](#improved-live-migration-support) - [Improved live migration support](#improved-live-migration-support)
- [Improved `vhost-user` support](#improved-vhost-user-support) - [Improved `vhost-user` support](#improved-vhost-user-support)
- [ARM64 ACPI and UEFI support](#arm64-acpi-and-uefi-support) - [ARM64 ACPI and UEFI support](#arm64-acpi-and-uefi-support)
- [Notable bug fixes](#notable-bug-fixes-21) - [Notable bug fixes](#notable-bug-fixes-20)
- [Removed functionality](#removed-functionality) - [Removed functionality](#removed-functionality)
- [Contributors](#contributors-21) - [Contributors](#contributors-20)
- [v15.0](#v150) - [v15.0](#v150)
- [Version numbering and stability guarantees](#version-numbering-and-stability-guarantees) - [Version numbering and stability guarantees](#version-numbering-and-stability-guarantees)
- [Network device rate limiting](#network-device-rate-limiting) - [Network device rate limiting](#network-device-rate-limiting)
@@ -191,7 +183,7 @@
- [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter) - [`--api-socket` supports file descriptor parameter](#--api-socket-supports-file-descriptor-parameter)
- [Bug fixes](#bug-fixes) - [Bug fixes](#bug-fixes)
- [Deprecations](#deprecations-5) - [Deprecations](#deprecations-5)
- [Contributors](#contributors-22) - [Contributors](#contributors-21)
- [v0.14.1](#v0141) - [v0.14.1](#v0141)
- [v0.14.0](#v0140) - [v0.14.0](#v0140)
- [Structured event monitoring](#structured-event-monitoring) - [Structured event monitoring](#structured-event-monitoring)
@@ -201,7 +193,7 @@
- [PTY control for serial and `virtio-console`](#pty-control-for-serial-and-virtio-console) - [PTY control for serial and `virtio-console`](#pty-control-for-serial-and-virtio-console)
- [Block device rate limiting](#block-device-rate-limiting) - [Block device rate limiting](#block-device-rate-limiting)
- [Deprecations](#deprecations-6) - [Deprecations](#deprecations-6)
- [Contributors](#contributors-23) - [Contributors](#contributors-22)
- [v0.13.0](#v0130) - [v0.13.0](#v0130)
- [Wider VFIO device support](#wider-vfio-device-support) - [Wider VFIO device support](#wider-vfio-device-support)
- [Improved huge page support](#improved-huge-page-support) - [Improved huge page support](#improved-huge-page-support)
@@ -209,13 +201,13 @@
- [VHD disk image support](#vhd-disk-image-support) - [VHD disk image support](#vhd-disk-image-support)
- [Improved Virtio device threading](#improved-virtio-device-threading) - [Improved Virtio device threading](#improved-virtio-device-threading)
- [Clean shutdown support via synthetic power button](#clean-shutdown-support-via-synthetic-power-button) - [Clean shutdown support via synthetic power button](#clean-shutdown-support-via-synthetic-power-button)
- [Contributors](#contributors-24) - [Contributors](#contributors-23)
- [v0.12.0](#v0120) - [v0.12.0](#v0120)
- [ARM64 enhancements](#arm64-enhancements) - [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) - [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) - [Migration of `vhost-user-fs` backend](#migration-of-vhost-user-fs-backend)
- [Enhanced "info" API](#enhanced-info-api) - [Enhanced "info" API](#enhanced-info-api)
- [Contributors](#contributors-25) - [Contributors](#contributors-24)
- [v0.11.0](#v0110) - [v0.11.0](#v0110)
- [`io_uring` support by default for `virtio-block`](#io_uring-support-by-default-for-virtio-block) - [`io_uring` support by default for `virtio-block`](#io_uring-support-by-default-for-virtio-block)
- [Windows Guest Support](#windows-guest-support) - [Windows Guest Support](#windows-guest-support)
@@ -227,15 +219,15 @@
- [Default Log Level Changed](#default-log-level-changed) - [Default Log Level Changed](#default-log-level-changed)
- [New `--balloon` Parameter Added](#new---balloon-parameter-added) - [New `--balloon` Parameter Added](#new---balloon-parameter-added)
- [Experimental `virtio-watchdog` Support](#experimental-virtio-watchdog-support) - [Experimental `virtio-watchdog` Support](#experimental-virtio-watchdog-support)
- [Notable Bug Fixes](#notable-bug-fixes-22) - [Notable Bug Fixes](#notable-bug-fixes-21)
- [Contributors](#contributors-26) - [Contributors](#contributors-25)
- [v0.10.0](#v0100) - [v0.10.0](#v0100)
- [`virtio-block` Support for Multiple Descriptors](#virtio-block-support-for-multiple-descriptors) - [`virtio-block` Support for Multiple Descriptors](#virtio-block-support-for-multiple-descriptors)
- [Memory Zones](#memory-zones) - [Memory Zones](#memory-zones)
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements) - [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements)
- [Preliminary KVM HyperV Emulation Control](#preliminary-kvm-hyperv-emulation-control) - [Preliminary KVM HyperV Emulation Control](#preliminary-kvm-hyperv-emulation-control)
- [Notable Bug Fixes](#notable-bug-fixes-23) - [Notable Bug Fixes](#notable-bug-fixes-22)
- [Contributors](#contributors-27) - [Contributors](#contributors-26)
- [v0.9.0](#v090) - [v0.9.0](#v090)
- [`io_uring` Based Block Device Support](#io_uring-based-block-device-support) - [`io_uring` Based Block Device Support](#io_uring-based-block-device-support)
- [Block and Network Device Statistics](#block-and-network-device-statistics) - [Block and Network Device Statistics](#block-and-network-device-statistics)
@@ -248,17 +240,17 @@
- [Enhancements to ARM64 Support](#enhancements-to-arm64-support) - [Enhancements to ARM64 Support](#enhancements-to-arm64-support)
- [Intel SGX Support](#intel-sgx-support) - [Intel SGX Support](#intel-sgx-support)
- [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements-1) - [`Seccomp` Sandbox Improvements](#seccomp-sandbox-improvements-1)
- [Notable Bug Fixes](#notable-bug-fixes-24) - [Notable Bug Fixes](#notable-bug-fixes-23)
- [Contributors](#contributors-28) - [Contributors](#contributors-27)
- [v0.8.0](#v080) - [v0.8.0](#v080)
- [Experimental Snapshot and Restore Support](#experimental-snapshot-and-restore-support) - [Experimental Snapshot and Restore Support](#experimental-snapshot-and-restore-support)
- [Experimental ARM64 Support](#experimental-arm64-support) - [Experimental ARM64 Support](#experimental-arm64-support)
- [Support for Using 5-level Paging in Guests](#support-for-using-5-level-paging-in-guests) - [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) - [Virtio Device Interrupt Suppression for Network Devices](#virtio-device-interrupt-suppression-for-network-devices)
- [`vhost_user_fs` Improvements](#vhost_user_fs-improvements) - [`vhost_user_fs` Improvements](#vhost_user_fs-improvements)
- [Notable Bug Fixes](#notable-bug-fixes-25) - [Notable Bug Fixes](#notable-bug-fixes-24)
- [Command Line and API Changes](#command-line-and-api-changes) - [Command Line and API Changes](#command-line-and-api-changes)
- [Contributors](#contributors-29) - [Contributors](#contributors-28)
- [v0.7.0](#v070) - [v0.7.0](#v070)
- [Block, Network, Persistent Memory (PMEM), VirtioFS and Vsock hotplug](#block-network-persistent-memory-pmem-virtiofs-and-vsock-hotplug) - [Block, Network, Persistent Memory (PMEM), VirtioFS and Vsock hotplug](#block-network-persistent-memory-pmem-virtiofs-and-vsock-hotplug)
- [Alternative `libc` Support](#alternative-libc-support) - [Alternative `libc` Support](#alternative-libc-support)
@@ -268,14 +260,14 @@
- [`Seccomp` Sandboxing](#seccomp-sandboxing) - [`Seccomp` Sandboxing](#seccomp-sandboxing)
- [Updated Distribution Support](#updated-distribution-support) - [Updated Distribution Support](#updated-distribution-support)
- [Command Line and API Changes](#command-line-and-api-changes-1) - [Command Line and API Changes](#command-line-and-api-changes-1)
- [Contributors](#contributors-30) - [Contributors](#contributors-29)
- [v0.6.0](#v060) - [v0.6.0](#v060)
- [Directly Assigned Devices Hotplug](#directly-assigned-devices-hotplug) - [Directly Assigned Devices Hotplug](#directly-assigned-devices-hotplug)
- [Shared Filesystem Improvements](#shared-filesystem-improvements) - [Shared Filesystem Improvements](#shared-filesystem-improvements)
- [Block and Networking IO Self Offloading](#block-and-networking-io-self-offloading) - [Block and Networking IO Self Offloading](#block-and-networking-io-self-offloading)
- [Command Line Interface](#command-line-interface) - [Command Line Interface](#command-line-interface)
- [PVH Boot](#pvh-boot) - [PVH Boot](#pvh-boot)
- [Contributors](#contributors-31) - [Contributors](#contributors-30)
- [v0.5.1](#v051) - [v0.5.1](#v051)
- [v0.5.0](#v050) - [v0.5.0](#v050)
- [Virtual Machine Dynamic Resizing](#virtual-machine-dynamic-resizing) - [Virtual Machine Dynamic Resizing](#virtual-machine-dynamic-resizing)
@@ -283,7 +275,7 @@
- [New Interrupt Management Framework](#new-interrupt-management-framework) - [New Interrupt Management Framework](#new-interrupt-management-framework)
- [Development Tools](#development-tools) - [Development Tools](#development-tools)
- [Kata Containers Integration](#kata-containers-integration) - [Kata Containers Integration](#kata-containers-integration)
- [Contributors](#contributors-32) - [Contributors](#contributors-31)
- [v0.4.0](#v040) - [v0.4.0](#v040)
- [Dynamic virtual CPUs addition](#dynamic-virtual-cpus-addition) - [Dynamic virtual CPUs addition](#dynamic-virtual-cpus-addition)
- [Programmatic firmware tables generation](#programmatic-firmware-tables-generation) - [Programmatic firmware tables generation](#programmatic-firmware-tables-generation)
@@ -292,7 +284,7 @@
- [Userspace IOAPIC by default](#userspace-ioapic-by-default) - [Userspace IOAPIC by default](#userspace-ioapic-by-default)
- [PCI BAR reprogramming](#pci-bar-reprogramming) - [PCI BAR reprogramming](#pci-bar-reprogramming)
- [New `cloud-hypervisor` organization](#new-cloud-hypervisor-organization) - [New `cloud-hypervisor` organization](#new-cloud-hypervisor-organization)
- [Contributors](#contributors-33) - [Contributors](#contributors-32)
- [v0.3.0](#v030) - [v0.3.0](#v030)
- [Block device offloading](#block-device-offloading) - [Block device offloading](#block-device-offloading)
- [Network device backend](#network-device-backend) - [Network device backend](#network-device-backend)
@@ -319,80 +311,16 @@
- [Unit testing](#unit-testing) - [Unit testing](#unit-testing)
- [Integration tests parallelization](#integration-tests-parallelization) - [Integration tests parallelization](#integration-tests-parallelization)
# v37.1 # v36.1
This is a bug fix release. The following issues have been addressed: 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)
* 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)
# v37.0
This release has been tracked in our [roadmap
project](https://github.com/orgs/cloud-hypervisor/projects/6) as iteration
v37.0. The following user visible changes have been made:
### Long Term Support (LTS) Release
This release is a LTS release. Point releases for bug fixes will be made
for the next 18 months; live migration and live upgrade will be
supported between the point releases of the LTS.
### Multiple PCI segments Support for 32-bit VFIO devices
Now VFIO devices with 32-bit memory BARs can be attached to non-zero PCI
segments on the guest, allowing users to have more 32-bit devices and
assign such devices to appropriate NUMA nodes for better performance.
### Configurable Named TAP Devices
Named TAP devices now accepts IP configuration from users, such as IP
and MAC address, as long as the named TAP device is created by Cloud
Hypervisor (e.g. not existing TAP devices).
### TTY Output from Both Serial Device and Virtio Console
Now legacy serial device and virtio console can be set as TTY mode as
the same time. This allows users to capture early boot logs with the
legacy serial device without losing performance benefits of using
virtio-console, when appropriate kernel configuration is used (such as
using kernel command-line `console=hvc0 earlyprintk=ttyS0` on x86).
### Faster VM Restoration from Snapshots
The speed of VM restoration from snapshots is improved with a better
implementation of deserializing JSON files.
### Notable Bug Fixes
* Fix aio backend behavior for block devices when writeback cache * Fix aio backend behavior for block devices when writeback cache
disabled (#5930) disabled (#5930)
* Fix PvPanic device PCI BAR alignment (#5956) * Fix PvPanic device PCI BAR alignment (#5956)
* Bug fix to OpenAPI specification file (#5967) * Bug fix to OpenAPI specification file (#5967)
* Error out early for live migration when TDX is enabled (#6025) * Error out early for live migration when TDX is enabled (#6025)
### Contributors
Many thanks to everyone who has contributed to our release:
* Bo Chen <chen.bo@intel.com>
* Jinank Jain <jinankjain@microsoft.com>
* Markus Sütter <markus.suetter@secunet.com>
* Michael Zhao <michael.zhao@arm.com>
* Muminul Islam <muislam@microsoft.com>
* Rob Bradford <rbradford@rivosinc.com>
* Rui Chang <rui.chang@arm.com>
* Ruslan Mstoi <ruslan.mstoi@intel.com>
* Thomas Barrett <tbarrett@crusoeenergy.com>
* Wei Liu <liuwe@microsoft.com>
* Yi Wang <foxywang@tencent.com>
* Yong He <alexyonghe@tencent.com>
# v36.0 # v36.0
This release has been tracked in our [roadmap This release has been tracked in our [roadmap

View File

@@ -6,7 +6,7 @@
FROM ubuntu:22.04 as dev FROM ubuntu:22.04 as dev
ARG TARGETARCH ARG TARGETARCH
ARG RUST_TOOLCHAIN="1.70.0" ARG RUST_TOOLCHAIN="1.67.1"
ARG CLH_SRC_DIR="/cloud-hypervisor" ARG CLH_SRC_DIR="/cloud-hypervisor"
ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build" ARG CLH_BUILD_DIR="$CLH_SRC_DIR/build"
ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry" ARG CARGO_REGISTRY_DIR="$CLH_BUILD_DIR/cargo_registry"

View File

@@ -434,7 +434,6 @@ cmd_tests() {
--env BUILD_TARGET="$target" \ --env BUILD_TARGET="$target" \
--env RUSTFLAGS="$rustflags" \ --env RUSTFLAGS="$rustflags" \
--env TARGET_CC="$target_cc" \ --env TARGET_CC="$target_cc" \
--env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \
"$CTR_IMAGE" \ "$CTR_IMAGE" \
dbus-run-session ./scripts/run_integration_tests_"$(uname -m)".sh "$@" || fix_dir_perms $? || exit $? dbus-run-session ./scripts/run_integration_tests_"$(uname -m)".sh "$@" || fix_dir_perms $? || exit $?
fi fi
@@ -456,7 +455,6 @@ cmd_tests() {
--env BUILD_TARGET="$target" \ --env BUILD_TARGET="$target" \
--env RUSTFLAGS="$rustflags" \ --env RUSTFLAGS="$rustflags" \
--env TARGET_CC="$target_cc" \ --env TARGET_CC="$target_cc" \
--env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \
"$CTR_IMAGE" \ "$CTR_IMAGE" \
./scripts/run_integration_tests_sgx.sh "$@" || fix_dir_perms $? || exit $? ./scripts/run_integration_tests_sgx.sh "$@" || fix_dir_perms $? || exit $?
fi fi
@@ -478,7 +476,6 @@ cmd_tests() {
--env BUILD_TARGET="$target" \ --env BUILD_TARGET="$target" \
--env RUSTFLAGS="$rustflags" \ --env RUSTFLAGS="$rustflags" \
--env TARGET_CC="$target_cc" \ --env TARGET_CC="$target_cc" \
--env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \
"$CTR_IMAGE" \ "$CTR_IMAGE" \
./scripts/run_integration_tests_vfio.sh "$@" || fix_dir_perms $? || exit $? ./scripts/run_integration_tests_vfio.sh "$@" || fix_dir_perms $? || exit $?
fi fi
@@ -500,7 +497,6 @@ cmd_tests() {
--env BUILD_TARGET="$target" \ --env BUILD_TARGET="$target" \
--env RUSTFLAGS="$rustflags" \ --env RUSTFLAGS="$rustflags" \
--env TARGET_CC="$target_cc" \ --env TARGET_CC="$target_cc" \
--env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \
"$CTR_IMAGE" \ "$CTR_IMAGE" \
./scripts/run_integration_tests_windows_"$(uname -m)".sh "$@" || fix_dir_perms $? || exit $? ./scripts/run_integration_tests_windows_"$(uname -m)".sh "$@" || fix_dir_perms $? || exit $?
fi fi
@@ -522,7 +518,6 @@ cmd_tests() {
--env BUILD_TARGET="$target" \ --env BUILD_TARGET="$target" \
--env RUSTFLAGS="$rustflags" \ --env RUSTFLAGS="$rustflags" \
--env TARGET_CC="$target_cc" \ --env TARGET_CC="$target_cc" \
--env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \
"$CTR_IMAGE" \ "$CTR_IMAGE" \
./scripts/run_integration_tests_live_migration.sh "$@" || fix_dir_perms $? || exit $? ./scripts/run_integration_tests_live_migration.sh "$@" || fix_dir_perms $? || exit $?
fi fi
@@ -544,7 +539,6 @@ cmd_tests() {
--env BUILD_TARGET="$target" \ --env BUILD_TARGET="$target" \
--env RUSTFLAGS="$rustflags" \ --env RUSTFLAGS="$rustflags" \
--env TARGET_CC="$target_cc" \ --env TARGET_CC="$target_cc" \
--env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \
"$CTR_IMAGE" \ "$CTR_IMAGE" \
./scripts/run_integration_tests_rate_limiter.sh "$@" || fix_dir_perms $? || exit $? ./scripts/run_integration_tests_rate_limiter.sh "$@" || fix_dir_perms $? || exit $?
fi fi
@@ -567,7 +561,6 @@ cmd_tests() {
--env RUSTFLAGS="$rustflags" \ --env RUSTFLAGS="$rustflags" \
--env TARGET_CC="$target_cc" \ --env TARGET_CC="$target_cc" \
--env RUST_BACKTRACE="${RUST_BACKTRACE}" \ --env RUST_BACKTRACE="${RUST_BACKTRACE}" \
--env AUTH_DOWNLOAD_TOKEN="$AUTH_DOWNLOAD_TOKEN" \
"$CTR_IMAGE" \ "$CTR_IMAGE" \
./scripts/run_metrics.sh "$@" || fix_dir_perms $? || exit $? ./scripts/run_metrics.sh "$@" || fix_dir_perms $? || exit $?
fi fi

View File

@@ -1,91 +0,0 @@
from gitlint.rules import LineRule, RuleViolation, CommitMessageTitle
import re
class TitleStartsWithComponent(LineRule):
"""A rule to enforce valid commit message title
Valid title format:
component1[, component2, componentN]: submodule: summary
Title should have at least one component
Components are separated by comma+space: ", "
Components are validated to be in valid_components
Components list is ended by a colon
Submodules are not validated
"""
# A rule MUST have a human friendly name
name = "title-has-valid-component"
# A rule MUST have a *unique* id.
# We recommend starting with UL (for User-defined Line-rule)
id = "UL1"
# A line-rule MUST have a target (not required for CommitRules).
target = CommitMessageTitle
def validate(self, line, _commit):
valid_components = (
'api_client',
'arch',
'block',
'build',
'ch-remote',
'ci',
'devices',
'docs',
'event_monitor',
'fuzz',
'github',
'gitignore',
'gitlint',
'hypervisor',
'main',
'misc',
'net_gen',
'net_util',
'option_parser',
'pci',
'performance-metrics',
'rate_limiter',
'README',
'resources',
'scripts',
'serial_buffer',
'test_data',
'test_infra',
'tests',
'tpm',
'tracer',
'vhost_user_block',
'vhost_user_net',
'virtio-devices',
'vm-allocator',
'vm-device',
'vmm',
'vm-migration',
'vm-virtio')
ptrn_title = re.compile(r'^(.+?):\s(.+)$')
match = ptrn_title.match(line)
if not match:
self.log.debug("Invalid commit title {}", line)
return [RuleViolation(self.id, "Commit title does not comply with "
"rule: 'component: change summary'")]
components = match.group(1)
summary = match.group(2)
self.log.debug(f"\nComponents: {components}\nSummary: {summary}")
ptrn_components = re.compile(r',\s')
components_list = re.split(ptrn_components, components)
self.log.debug("components list: %s" % components_list)
for component in components_list:
if component not in valid_components:
return [RuleViolation(self.id,
f"Invalid component: {component}, "
"\nValid components are: {}".format(
" ".join(valid_components)))]

View File

@@ -53,8 +53,35 @@ build_virtiofsd() {
update_workloads() { update_workloads() {
cp scripts/sha1sums-aarch64 $WORKLOADS_DIR cp scripts/sha1sums-aarch64 $WORKLOADS_DIR
BIONIC_OS_IMAGE_DOWNLOAD_NAME="bionic-server-cloudimg-arm64.img"
BIONIC_OS_IMAGE_DOWNLOAD_URL="https://cloud-hypervisor.azureedge.net/$BIONIC_OS_IMAGE_DOWNLOAD_NAME"
BIONIC_OS_DOWNLOAD_IMAGE="$WORKLOADS_DIR/$BIONIC_OS_IMAGE_DOWNLOAD_NAME"
if [ ! -f "$BIONIC_OS_DOWNLOAD_IMAGE" ]; then
pushd $WORKLOADS_DIR
time wget --quiet $BIONIC_OS_IMAGE_DOWNLOAD_URL || exit 1
popd
fi
BIONIC_OS_RAW_IMAGE_NAME="bionic-server-cloudimg-arm64.raw"
BIONIC_OS_RAW_IMAGE="$WORKLOADS_DIR/$BIONIC_OS_RAW_IMAGE_NAME"
if [ ! -f "$BIONIC_OS_RAW_IMAGE" ]; then
pushd $WORKLOADS_DIR
time qemu-img convert -p -f qcow2 -O raw $BIONIC_OS_IMAGE_DOWNLOAD_NAME $BIONIC_OS_RAW_IMAGE_NAME || exit 1
popd
fi
# Convert the raw image to qcow2 image to remove compressed blocks from the disk. Therefore letting the
# qcow2 format image can be directly used in the integration test.
BIONIC_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME="bionic-server-cloudimg-arm64.qcow2"
BIONIC_OS_QCOW2_UNCOMPRESSED_IMAGE="$WORKLOADS_DIR/$BIONIC_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME"
if [ ! -f "$BIONIC_OS_QCOW2_UNCOMPRESSED_IMAGE" ]; then
pushd $WORKLOADS_DIR
time qemu-img convert -p -f raw -O qcow2 $BIONIC_OS_RAW_IMAGE_NAME $BIONIC_OS_QCOW2_UNCOMPRESSED_IMAGE || exit 1
popd
fi
FOCAL_OS_RAW_IMAGE_NAME="focal-server-cloudimg-arm64-custom-20210929-0.raw" FOCAL_OS_RAW_IMAGE_NAME="focal-server-cloudimg-arm64-custom-20210929-0.raw"
FOCAL_OS_RAW_IMAGE_DOWNLOAD_URL="https://ch-images.azureedge.net/$FOCAL_OS_RAW_IMAGE_NAME" FOCAL_OS_RAW_IMAGE_DOWNLOAD_URL="https://cloud-hypervisor.azureedge.net/$FOCAL_OS_RAW_IMAGE_NAME"
FOCAL_OS_RAW_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_NAME" FOCAL_OS_RAW_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_RAW_IMAGE_NAME"
if [ ! -f "$FOCAL_OS_RAW_IMAGE" ]; then if [ ! -f "$FOCAL_OS_RAW_IMAGE" ]; then
pushd $WORKLOADS_DIR pushd $WORKLOADS_DIR
@@ -63,7 +90,7 @@ update_workloads() {
fi fi
FOCAL_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME="focal-server-cloudimg-arm64-custom-20210929-0.qcow2" FOCAL_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME="focal-server-cloudimg-arm64-custom-20210929-0.qcow2"
FOCAL_OS_QCOW2_IMAGE_UNCOMPRESSED_DOWNLOAD_URL="https://ch-images.azureedge.net/$FOCAL_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME" FOCAL_OS_QCOW2_IMAGE_UNCOMPRESSED_DOWNLOAD_URL="https://cloud-hypervisor.azureedge.net/$FOCAL_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME"
FOCAL_OS_QCOW2_UNCOMPRESSED_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME" FOCAL_OS_QCOW2_UNCOMPRESSED_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME"
if [ ! -f "$FOCAL_OS_QCOW2_UNCOMPRESSED_IMAGE" ]; then if [ ! -f "$FOCAL_OS_QCOW2_UNCOMPRESSED_IMAGE" ]; then
pushd $WORKLOADS_DIR pushd $WORKLOADS_DIR
@@ -80,7 +107,7 @@ update_workloads() {
fi fi
JAMMY_OS_RAW_IMAGE_NAME="jammy-server-cloudimg-arm64-custom-20220329-0.raw" JAMMY_OS_RAW_IMAGE_NAME="jammy-server-cloudimg-arm64-custom-20220329-0.raw"
JAMMY_OS_RAW_IMAGE_DOWNLOAD_URL="https://ch-images.azureedge.net/$JAMMY_OS_RAW_IMAGE_NAME" JAMMY_OS_RAW_IMAGE_DOWNLOAD_URL="https://cloud-hypervisor.azureedge.net/$JAMMY_OS_RAW_IMAGE_NAME"
JAMMY_OS_RAW_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_RAW_IMAGE_NAME" JAMMY_OS_RAW_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_RAW_IMAGE_NAME"
if [ ! -f "$JAMMY_OS_RAW_IMAGE" ]; then if [ ! -f "$JAMMY_OS_RAW_IMAGE" ]; then
pushd $WORKLOADS_DIR pushd $WORKLOADS_DIR
@@ -89,7 +116,7 @@ update_workloads() {
fi fi
JAMMY_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME="jammy-server-cloudimg-arm64-custom-20220329-0.qcow2" JAMMY_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME="jammy-server-cloudimg-arm64-custom-20220329-0.qcow2"
JAMMY_OS_QCOW2_IMAGE_UNCOMPRESSED_DOWNLOAD_URL="https://ch-images.azureedge.net/$JAMMY_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME" JAMMY_OS_QCOW2_IMAGE_UNCOMPRESSED_DOWNLOAD_URL="https://cloud-hypervisor.azureedge.net/$JAMMY_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME"
JAMMY_OS_QCOW2_UNCOMPRESSED_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME" JAMMY_OS_QCOW2_UNCOMPRESSED_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_QCOW2_IMAGE_UNCOMPRESSED_NAME"
if [ ! -f "$JAMMY_OS_QCOW2_UNCOMPRESSED_IMAGE" ]; then if [ ! -f "$JAMMY_OS_QCOW2_UNCOMPRESSED_IMAGE" ]; then
pushd $WORKLOADS_DIR pushd $WORKLOADS_DIR

View File

@@ -19,7 +19,7 @@ fi
cp scripts/sha1sums-x86_64 $WORKLOADS_DIR cp scripts/sha1sums-x86_64 $WORKLOADS_DIR
FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.qcow2" FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.qcow2"
FOCAL_OS_IMAGE_URL="https://ch-images.azureedge.net/$FOCAL_OS_IMAGE_NAME" FOCAL_OS_IMAGE_URL="https://cloud-hypervisor.azureedge.net/$FOCAL_OS_IMAGE_NAME"
FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME" FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME"
if [ ! -f "$FOCAL_OS_IMAGE" ]; then if [ ! -f "$FOCAL_OS_IMAGE" ]; then
pushd $WORKLOADS_DIR pushd $WORKLOADS_DIR

View File

@@ -19,7 +19,7 @@ fi
cp scripts/sha1sums-x86_64 $WORKLOADS_DIR cp scripts/sha1sums-x86_64 $WORKLOADS_DIR
FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.qcow2" FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.qcow2"
FOCAL_OS_IMAGE_URL="https://ch-images.azureedge.net/$FOCAL_OS_IMAGE_NAME" FOCAL_OS_IMAGE_URL="https://cloud-hypervisor.azureedge.net/$FOCAL_OS_IMAGE_NAME"
FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME" FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME"
if [ ! -f "$FOCAL_OS_IMAGE" ]; then if [ ! -f "$FOCAL_OS_IMAGE" ]; then
pushd $WORKLOADS_DIR pushd $WORKLOADS_DIR

View File

@@ -14,10 +14,15 @@ fi
WORKLOADS_DIR="$HOME/workloads" WORKLOADS_DIR="$HOME/workloads"
mkdir -p "$WORKLOADS_DIR" mkdir -p "$WORKLOADS_DIR"
download_hypervisor_fw FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/rust-hypervisor-firmware/releases/latest | grep "browser_download_url" | grep -o 'https://.*[^ "]')
FW="$WORKLOADS_DIR/hypervisor-fw"
pushd $WORKLOADS_DIR
rm -f $FW
time wget --quiet $FW_URL || exit 1
popd
JAMMY_OS_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20230119-0.qcow2" JAMMY_OS_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20230119-0.qcow2"
JAMMY_OS_IMAGE_URL="https://ch-images.azureedge.net/$JAMMY_OS_IMAGE_NAME" JAMMY_OS_IMAGE_URL="https://cloud-hypervisor.azureedge.net/$JAMMY_OS_IMAGE_NAME"
JAMMY_OS_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_IMAGE_NAME" JAMMY_OS_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_IMAGE_NAME"
if [ ! -f "$JAMMY_OS_IMAGE" ]; then if [ ! -f "$JAMMY_OS_IMAGE" ]; then
pushd $WORKLOADS_DIR pushd $WORKLOADS_DIR

View File

@@ -14,7 +14,11 @@ process_common_args "$@"
WORKLOADS_DIR="$HOME/workloads" WORKLOADS_DIR="$HOME/workloads"
download_hypervisor_fw # Always download the latest "hypervisor-fw"
FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/rust-hypervisor-firmware/releases/latest | grep "browser_download_url" | grep -o 'https://.*[^ "]')
pushd $WORKLOADS_DIR
time wget --quiet $FW_URL -O hypervisor-fw || exit 1
popd
CFLAGS="" CFLAGS=""
if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then if [[ "${BUILD_TARGET}" == "x86_64-unknown-linux-musl" ]]; then

View File

@@ -18,7 +18,13 @@ fi
cp scripts/sha1sums-x86_64 $WORKLOADS_DIR cp scripts/sha1sums-x86_64 $WORKLOADS_DIR
download_hypervisor_fw FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/rust-hypervisor-firmware/releases/latest | grep "browser_download_url" | grep -o 'https://.*[^ "]')
FW="$WORKLOADS_DIR/hypervisor-fw"
if [ ! -f "$FW" ]; then
pushd $WORKLOADS_DIR
time wget --quiet $FW_URL || exit 1
popd
fi
OVMF_FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/edk2/releases/latest | grep "browser_download_url" | grep -o 'https://.*[^ "]') OVMF_FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/edk2/releases/latest | grep "browser_download_url" | grep -o 'https://.*[^ "]')
OVMF_FW="$WORKLOADS_DIR/CLOUDHV.fd" OVMF_FW="$WORKLOADS_DIR/CLOUDHV.fd"
@@ -29,7 +35,7 @@ if [ ! -f "$OVMF_FW" ]; then
fi fi
FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.qcow2" FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.qcow2"
FOCAL_OS_IMAGE_URL="https://ch-images.azureedge.net/$FOCAL_OS_IMAGE_NAME" FOCAL_OS_IMAGE_URL="https://cloud-hypervisor.azureedge.net/$FOCAL_OS_IMAGE_NAME"
FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME" FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME"
if [ ! -f "$FOCAL_OS_IMAGE" ]; then if [ ! -f "$FOCAL_OS_IMAGE" ]; then
pushd $WORKLOADS_DIR pushd $WORKLOADS_DIR
@@ -54,7 +60,7 @@ if [ ! -f "$FOCAL_OS_QCOW_BACKING_FILE_IMAGE" ]; then
fi fi
JAMMY_OS_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20230119-0.qcow2" JAMMY_OS_IMAGE_NAME="jammy-server-cloudimg-amd64-custom-20230119-0.qcow2"
JAMMY_OS_IMAGE_URL="https://ch-images.azureedge.net/$JAMMY_OS_IMAGE_NAME" JAMMY_OS_IMAGE_URL="https://cloud-hypervisor.azureedge.net/$JAMMY_OS_IMAGE_NAME"
JAMMY_OS_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_IMAGE_NAME" JAMMY_OS_IMAGE="$WORKLOADS_DIR/$JAMMY_OS_IMAGE_NAME"
if [ ! -f "$JAMMY_OS_IMAGE" ]; then if [ ! -f "$JAMMY_OS_IMAGE" ]; then
pushd $WORKLOADS_DIR pushd $WORKLOADS_DIR

View File

@@ -34,7 +34,7 @@ else
FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.qcow2" FOCAL_OS_IMAGE_NAME="focal-server-cloudimg-amd64-custom-20210609-0.qcow2"
fi fi
FOCAL_OS_IMAGE_URL="https://ch-images.azureedge.net/$FOCAL_OS_IMAGE_NAME" FOCAL_OS_IMAGE_URL="https://cloud-hypervisor.azureedge.net/$FOCAL_OS_IMAGE_NAME"
FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME" FOCAL_OS_IMAGE="$WORKLOADS_DIR/$FOCAL_OS_IMAGE_NAME"
if [ ! -f "$FOCAL_OS_IMAGE" ]; then if [ ! -f "$FOCAL_OS_IMAGE" ]; then
pushd $WORKLOADS_DIR pushd $WORKLOADS_DIR

View File

@@ -1,3 +1,6 @@
6fee67adbfed8db7a225be23ee9d90b5bd7f19e6 bionic-server-cloudimg-arm64.img
786fe1c33588334e92b35c65e414da068df180bc bionic-server-cloudimg-arm64.raw
6e66f9f4b01adc72c884c1c1111e60afadc9c871 bionic-server-cloudimg-arm64.qcow2
e4addb6e212a298144f9eb0eb6e36019d013f0e7 alpine-minirootfs-aarch64.tar.gz e4addb6e212a298144f9eb0eb6e36019d013f0e7 alpine-minirootfs-aarch64.tar.gz
25b4f9ac308898d63b73d7db0e0e2d4768853723 focal-server-cloudimg-arm64-custom-20210929-0.qcow2 25b4f9ac308898d63b73d7db0e0e2d4768853723 focal-server-cloudimg-arm64-custom-20210929-0.qcow2
9953b31bb1923cdd8d91b1b7cc9ad3a9be1e0a59 focal-server-cloudimg-arm64-custom-20210929-0.raw 9953b31bb1923cdd8d91b1b7cc9ad3a9be1e0a59 focal-server-cloudimg-arm64-custom-20210929-0.raw

View File

@@ -107,20 +107,3 @@ process_common_args() {
test_binary_args=($@) test_binary_args=($@)
} }
download_hypervisor_fw() {
if [ -n "$AUTH_DOWNLOAD_TOKEN" ]; then
echo "Using authenticated download from GitHub"
FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/rust-hypervisor-firmware/releases/latest \
--header "Authorization: Token $AUTH_DOWNLOAD_TOKEN" \
--header "X-GitHub-Api-Version: 2022-11-28" | grep "browser_download_url" | grep -o 'https://.*[^ "]')
else
echo "Using anonymous download from GitHub"
FW_URL=$(curl --silent https://api.github.com/repos/cloud-hypervisor/rust-hypervisor-firmware/releases/latest | grep "browser_download_url" | grep -o 'https://.*[^ "]')
fi
FW="$WORKLOADS_DIR/hypervisor-fw"
pushd $WORKLOADS_DIR
rm -f $FW
time wget --quiet $FW_URL || exit 1
popd
}

View File

@@ -443,14 +443,7 @@ fn create_app(default_vcpus: String, default_memory: String, default_rng: String
.num_args(0) .num_args(0)
.group("vmm-config"), .group("vmm-config"),
); );
#[cfg(feature = "igvm")]
let app = app.arg(
Arg::new("igvm")
.long("igvm")
.help("Path to IGVM file to load.")
.num_args(1)
.group("vm-config"),
);
app.arg( app.arg(
Arg::new("version") Arg::new("version")
.short('V') .short('V')
@@ -605,7 +598,6 @@ fn start_vmm(cmd_arguments: ArgMatches) -> Result<Option<String>, Error> {
std::fs::OpenOptions::new() std::fs::OpenOptions::new()
.write(true) .write(true)
.create(true) .create(true)
.truncate(true)
.open(parser.get("path").unwrap()) .open(parser.get("path").unwrap())
.map_err(Error::EventMonitorIo)?, .map_err(Error::EventMonitorIo)?,
)) ))

View File

@@ -12,5 +12,5 @@ once_cell = "1.18.0"
serde = { version = "1.0.168", features = ["rc", "derive"] } serde = { version = "1.0.168", features = ["rc", "derive"] }
serde_json = "1.0.107" serde_json = "1.0.107"
ssh2 = { version = "0.9.4", features = ["vendored-openssl"] } ssh2 = { version = "0.9.4", features = ["vendored-openssl"] }
vmm-sys-util = "0.12.1" vmm-sys-util = "0.11.0"
wait-timeout = "0.2.0" wait-timeout = "0.2.0"

View File

@@ -149,13 +149,13 @@ impl GuestNetworkConfig {
Err(e) => { Err(e) => {
let duration = start.elapsed(); let duration = start.elapsed();
eprintln!( eprintln!(
"\n\n==== Start 'wait_vm_boot' (FAILED) ==== \ "\n\n==== Start 'wait_vm_boot' (FAILED) ====\n\n\
\n\nduration =\"{duration:?}, timeout = {timeout}s\" \ duration =\"{duration:?}, timeout = {timeout}s\"\n\
\nlisten_addr=\"{listen_addr}\" \ listen_addr=\"{listen_addr}\"\n\
\nexpected_guest_addr=\"{expected_guest_addr}\" \ expected_guest_addr=\"{expected_guest_addr}\"\n\
\nmessage=\"{s}\" \ message=\"{s}\"\n\
\nerror=\"{e:?}\" \ error=\"{e:?}\"\n\
\n\n==== End 'wait_vm_boot' outout ====\n\n" \n==== End 'wait_vm_boot' outout ====\n\n"
); );
Err(e) Err(e)
@@ -724,77 +724,18 @@ pub fn ssh_command_ip(
) )
} }
pub fn exec_host_command_with_retries(command: &str, retries: u32, interval: Duration) -> bool {
for _ in 0..retries {
let s = exec_host_command_output(command).status;
if !s.success() {
eprintln!("\n\n==== retrying in {:?} ===\n\n", interval);
thread::sleep(interval);
} else {
return true;
}
}
false
}
pub fn exec_host_command_status(command: &str) -> ExitStatus { pub fn exec_host_command_status(command: &str) -> ExitStatus {
exec_host_command_output(command).status std::process::Command::new("bash")
.args(["-c", command])
.status()
.unwrap_or_else(|_| panic!("Expected '{command}' to run"))
} }
pub fn exec_host_command_output(command: &str) -> Output { pub fn exec_host_command_output(command: &str) -> Output {
let output = std::process::Command::new("bash") std::process::Command::new("bash")
.args(["-c", command]) .args(["-c", command])
.output() .output()
.unwrap_or_else(|e| panic!("Expected '{command}' to run. Error: {:?}", e)); .unwrap_or_else(|_| panic!("Expected '{command}' to run"))
if !output.status.success() {
let stdout = String::from_utf8_lossy(&output.stdout);
let stderr = String::from_utf8_lossy(&output.stderr);
eprintln!(
"\n\n==== Start 'exec_host_command' failed ==== \
\n\n---stdout---\n{stdout}\n---stderr---{stderr} \
\n\n==== End 'exec_host_command' failed ====",
);
}
output
}
pub fn check_lines_count(input: &str, line_count: usize) -> bool {
if input.lines().count() == line_count {
true
} else {
eprintln!(
"\n\n==== Start 'check_lines_count' failed ==== \
\n\ninput = {input}\nline_count = {line_count} \
\n\n==== End 'check_lines_count' failed ====",
);
false
}
}
pub fn check_matched_lines_count(input: &str, keywords: Vec<&str>, line_count: usize) -> bool {
let mut matches = String::new();
for line in input.lines() {
if keywords.iter().all(|k| line.contains(k)) {
matches += line;
}
}
if matches.lines().count() == line_count {
true
} else {
eprintln!(
"\n\n==== Start 'check_matched_lines_count' failed ==== \
\nkeywords = {keywords:?}, line_count = {line_count} \
\n\ninput = {input} matches = {matches} \
\n\n==== End 'check_matched_lines_count' failed ====",
);
false
}
} }
pub const PIPE_SIZE: i32 = 32 << 20; pub const PIPE_SIZE: i32 = 32 << 20;
@@ -1402,7 +1343,7 @@ pub fn parse_iperf3_output(output: &[u8], sender: bool, bandwidth: bool) -> Resu
}) })
.map_err(|_| { .map_err(|_| {
eprintln!( eprintln!(
"==== Start iperf3 output ===\n\n{}\n\n=== End iperf3 output ===\n\n", "=============== iperf3 output ===============\n\n{}\n\n===========end============\n\n",
String::from_utf8_lossy(output) String::from_utf8_lossy(output)
); );
Error::Iperf3Parse Error::Iperf3Parse
@@ -1480,7 +1421,9 @@ pub fn parse_fio_output(output: &str, fio_ops: &FioOps, num_jobs: u32) -> Result
total_bps total_bps
}) })
.map_err(|_| { .map_err(|_| {
eprintln!("=== Start Fio output ===\n\n{output}\n\n=== End Fio output ===\n\n"); eprintln!(
"=============== Fio output ===============\n\n{output}\n\n===========end============\n\n"
);
Error::FioOutputParse Error::FioOutputParse
}) })
} }
@@ -1533,7 +1476,9 @@ pub fn parse_fio_output_iops(output: &str, fio_ops: &FioOps, num_jobs: u32) -> R
total_iops total_iops
}) })
.map_err(|_| { .map_err(|_| {
eprintln!("=== Start Fio output ===\n\n{output}\n\n=== End Fio output ===\n\n"); eprintln!(
"=============== Fio output ===============\n\n{output}\n\n===========end============\n\n"
);
Error::FioOutputParse Error::FioOutputParse
}) })
} }
@@ -1666,7 +1611,7 @@ pub fn parse_ethr_latency_output(output: &[u8]) -> Result<Vec<f64>, Error> {
}) })
.map_err(|_| { .map_err(|_| {
eprintln!( eprintln!(
"=== Start ethr output ===\n\n{}\n\n=== End ethr output ===\n\n", "=============== ethr output ===============\n\n{}\n\n===========end============\n\n",
String::from_utf8_lossy(output) String::from_utf8_lossy(output)
); );
Error::EthrLogParse Error::EthrLogParse

View File

@@ -53,6 +53,7 @@ use x86_64::*;
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
mod aarch64 { mod aarch64 {
pub const BIONIC_IMAGE_NAME: &str = "bionic-server-cloudimg-arm64.raw";
pub const FOCAL_IMAGE_NAME: &str = "focal-server-cloudimg-arm64-custom-20210929-0.raw"; pub const FOCAL_IMAGE_NAME: &str = "focal-server-cloudimg-arm64-custom-20210929-0.raw";
pub const FOCAL_IMAGE_UPDATE_KERNEL_NAME: &str = pub const FOCAL_IMAGE_UPDATE_KERNEL_NAME: &str =
"focal-server-cloudimg-arm64-custom-20210929-0-update-kernel.raw"; "focal-server-cloudimg-arm64-custom-20210929-0-update-kernel.raw";
@@ -686,8 +687,6 @@ fn resize_command(
device_id: None, device_id: None,
}, },
]; ];
// See: #5938
thread::sleep(std::time::Duration::new(1, 0));
assert!(check_latest_events_exact(&latest_events, event_path)); assert!(check_latest_events_exact(&latest_events, event_path));
} }
@@ -859,7 +858,6 @@ fn fw_path(_fw_type: FwType) -> String {
fw_path.to_str().unwrap().to_string() fw_path.to_str().unwrap().to_string()
} }
#[derive(Debug)]
struct MetaEvent { struct MetaEvent {
event: String, event: String,
device_id: Option<String>, device_id: Option<String>,
@@ -912,18 +910,7 @@ fn check_sequential_events(expected_events: &[&MetaEvent], event_file: &str) ->
} }
} }
let ret = idx == len; idx == len
if !ret {
eprintln!(
"\n\n==== Start 'check_sequential_events' failed ==== \
\n\nexpected_events={:?}\nactual_events={:?} \
\n\n==== End 'check_sequential_events' failed ====",
expected_events, json_events,
);
}
ret
} }
// Return true if all events from the input 'expected_events' are matched exactly // Return true if all events from the input 'expected_events' are matched exactly
@@ -935,13 +922,6 @@ fn check_sequential_events_exact(expected_events: &[&MetaEvent], event_file: &st
for (idx, e) in json_events.iter().enumerate() { for (idx, e) in json_events.iter().enumerate() {
if !expected_events[idx].match_with_json_event(e) { if !expected_events[idx].match_with_json_event(e) {
eprintln!(
"\n\n==== Start 'check_sequential_events_exact' failed ==== \
\n\nexpected_events={:?}\nactual_events={:?} \
\n\n==== End 'check_sequential_events_exact' failed ====",
expected_events, json_events,
);
return false; return false;
} }
} }
@@ -958,13 +938,6 @@ fn check_latest_events_exact(latest_events: &[&MetaEvent], event_file: &str) ->
for (idx, e) in json_events.iter().enumerate() { for (idx, e) in json_events.iter().enumerate() {
if !latest_events[idx].match_with_json_event(e) { if !latest_events[idx].match_with_json_event(e) {
eprintln!(
"\n\n==== Start 'check_latest_events_exact' failed ==== \
\n\nexpected_events={:?}\nactual_events={:?} \
\n\n==== End 'check_latest_events_exact' failed ====",
latest_events, json_events,
);
return false; return false;
} }
} }
@@ -1034,40 +1007,6 @@ fn test_cpu_topology(threads_per_core: u8, cores_per_package: u8, packages: u8,
.unwrap_or(0), .unwrap_or(0),
packages packages
); );
#[cfg(target_arch = "x86_64")]
{
let mut cpu_id = 0;
for package_id in 0..packages {
for core_id in 0..cores_per_package {
for _ in 0..threads_per_core {
assert_eq!(
guest
.ssh_command(&format!("cat /sys/devices/system/cpu/cpu{cpu_id}/topology/physical_package_id"))
.unwrap()
.trim()
.parse::<u8>()
.unwrap_or(0),
package_id
);
assert_eq!(
guest
.ssh_command(&format!(
"cat /sys/devices/system/cpu/cpu{cpu_id}/topology/core_id"
))
.unwrap()
.trim()
.parse::<u8>()
.unwrap_or(0),
core_id
);
cpu_id += 1;
}
}
}
}
}); });
let _ = child.kill(); let _ = child.kill();
@@ -2118,7 +2057,7 @@ fn pty_read(mut pty: std::fs::File) -> Receiver<String> {
thread::sleep(std::time::Duration::new(1, 0)); thread::sleep(std::time::Duration::new(1, 0));
let mut buf = [0; 512]; let mut buf = [0; 512];
match pty.read(&mut buf) { match pty.read(&mut buf) {
Ok(_bytes) => { Ok(_) => {
let output = std::str::from_utf8(&buf).unwrap().to_string(); let output = std::str::from_utf8(&buf).unwrap().to_string();
match tx.send(output) { match tx.send(output) {
Ok(_) => (), Ok(_) => (),
@@ -4161,12 +4100,7 @@ mod common_parallel {
let r = std::panic::catch_unwind(|| { let r = std::panic::catch_unwind(|| {
// Check that the cloud-hypervisor binary actually terminated // Check that the cloud-hypervisor binary actually terminated
if !output.status.success() { assert!(output.status.success())
panic!(
"Cloud Hypervisor process failed to terminate gracefully: {:?}",
output.status
);
}
}); });
handle_child_output(r, &output); handle_child_output(r, &output);
} }
@@ -4387,35 +4321,49 @@ mod common_parallel {
// Let's ssh into it and verify that it's there. If it is it means // Let's ssh into it and verify that it's there. If it is it means
// we're in the right guest (The L2 one) because the QEMU L1 guest // we're in the right guest (The L2 one) because the QEMU L1 guest
// does not have this command line tag. // does not have this command line tag.
assert!(check_matched_lines_count( assert_eq!(
guest.ssh_command_l2_1("cat /proc/cmdline").unwrap().trim(), guest
vec!["VFIOTAG"], .ssh_command_l2_1("grep -c VFIOTAG /proc/cmdline")
.unwrap()
.trim()
.parse::<u32>()
.unwrap_or_default(),
1 1
)); );
// Let's also verify from the second virtio-net device passed to // Let's also verify from the second virtio-net device passed to
// the L2 VM. // the L2 VM.
assert!(check_matched_lines_count( assert_eq!(
guest.ssh_command_l2_2("cat /proc/cmdline").unwrap().trim(), guest
vec!["VFIOTAG"], .ssh_command_l2_2("grep -c VFIOTAG /proc/cmdline")
.unwrap()
.trim()
.parse::<u32>()
.unwrap_or_default(),
1 1
)); );
// Check the amount of PCI devices appearing in L2 VM. // Check the amount of PCI devices appearing in L2 VM.
assert!(check_lines_count( assert_eq!(
guest guest
.ssh_command_l2_1("ls /sys/bus/pci/devices") .ssh_command_l2_1("ls /sys/bus/pci/devices | wc -l")
.unwrap() .unwrap()
.trim(), .trim()
8 .parse::<u32>()
)); .unwrap_or_default(),
8,
);
// Check both if /dev/vdc exists and if the block size is 16M in L2 VM // Check both if /dev/vdc exists and if the block size is 16M in L2 VM
assert!(check_matched_lines_count( assert_eq!(
guest.ssh_command_l2_1("lsblk").unwrap().trim(), guest
vec!["vdc", "16M"], .ssh_command_l2_1("lsblk | grep vdc | grep -c 16M")
.unwrap()
.trim()
.parse::<u32>()
.unwrap_or_default(),
1 1
)); );
// Hotplug an extra virtio-net device through L2 VM. // Hotplug an extra virtio-net device through L2 VM.
guest guest
@@ -4433,33 +4381,35 @@ mod common_parallel {
add-device path=/sys/bus/pci/devices/0000:00:09.0,id=vfio123", add-device path=/sys/bus/pci/devices/0000:00:09.0,id=vfio123",
) )
.unwrap(); .unwrap();
assert!(check_matched_lines_count( assert!(vfio_hotplug_output.contains("{\"id\":\"vfio123\",\"bdf\":\"0000:00:08.0\"}"));
vfio_hotplug_output.trim(),
vec!["{\"id\":\"vfio123\",\"bdf\":\"0000:00:08.0\"}"],
1
));
thread::sleep(std::time::Duration::new(10, 0)); thread::sleep(std::time::Duration::new(10, 0));
// Let's also verify from the third virtio-net device passed to // Let's also verify from the third virtio-net device passed to
// the L2 VM. This third device has been hotplugged through the L2 // the L2 VM. This third device has been hotplugged through the L2
// VM, so this is our way to validate hotplug works for VFIO PCI. // VM, so this is our way to validate hotplug works for VFIO PCI.
assert!(check_matched_lines_count( assert_eq!(
guest.ssh_command_l2_3("cat /proc/cmdline").unwrap().trim(), guest
vec!["VFIOTAG"], .ssh_command_l2_3("grep -c VFIOTAG /proc/cmdline")
.unwrap()
.trim()
.parse::<u32>()
.unwrap_or_default(),
1 1
)); );
// Check the amount of PCI devices appearing in L2 VM. // Check the amount of PCI devices appearing in L2 VM.
// There should be one more device than before, raising the count // There should be one more device than before, raising the count
// up to 9 PCI devices. // up to 9 PCI devices.
assert!(check_lines_count( assert_eq!(
guest guest
.ssh_command_l2_1("ls /sys/bus/pci/devices") .ssh_command_l2_1("ls /sys/bus/pci/devices | wc -l")
.unwrap() .unwrap()
.trim(), .trim()
9 .parse::<u32>()
)); .unwrap_or_default(),
9,
);
// Let's now verify that we can correctly remove the virtio-net // Let's now verify that we can correctly remove the virtio-net
// device through the "remove-device" command responsible for // device through the "remove-device" command responsible for
@@ -4475,13 +4425,15 @@ mod common_parallel {
// Check the amount of PCI devices appearing in L2 VM is back down // Check the amount of PCI devices appearing in L2 VM is back down
// to 8 devices. // to 8 devices.
assert!(check_lines_count( assert_eq!(
guest guest
.ssh_command_l2_1("ls /sys/bus/pci/devices") .ssh_command_l2_1("ls /sys/bus/pci/devices | wc -l")
.unwrap() .unwrap()
.trim(), .trim()
8 .parse::<u32>()
)); .unwrap_or_default(),
8,
);
// Perform memory hotplug in L2 and validate the memory is showing // Perform memory hotplug in L2 and validate the memory is showing
// up as expected. In order to check, we will use the virtio-net // up as expected. In order to check, we will use the virtio-net
@@ -5841,7 +5793,7 @@ mod common_parallel {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
let mut kernels = vec![direct_kernel_boot_path()]; let mut kernels = vec![direct_kernel_boot_path()];
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
let kernels = [direct_kernel_boot_path()]; let kernels = vec![direct_kernel_boot_path()];
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
{ {
@@ -6000,8 +5952,6 @@ mod common_parallel {
event: "device-removed".to_string(), event: "device-removed".to_string(),
device_id: Some(net_id.to_string()), device_id: Some(net_id.to_string()),
}]; }];
// See: #5938
thread::sleep(std::time::Duration::new(1, 0));
assert!(check_latest_events_exact(&latest_events, &event_path)); assert!(check_latest_events_exact(&latest_events, &event_path));
// Plug the virtio-net device again // Plug the virtio-net device again
@@ -6025,8 +5975,6 @@ mod common_parallel {
device_id: None, device_id: None,
}, },
]; ];
// See: #5938
thread::sleep(std::time::Duration::new(1, 0));
assert!(check_latest_events_exact(&latest_events, &event_path)); assert!(check_latest_events_exact(&latest_events, &event_path));
// Take a snapshot from the VM // Take a snapshot from the VM
@@ -6049,8 +5997,6 @@ mod common_parallel {
device_id: None, device_id: None,
}, },
]; ];
// See: #5938
thread::sleep(std::time::Duration::new(1, 0));
assert!(check_latest_events_exact(&latest_events, &event_path)); assert!(check_latest_events_exact(&latest_events, &event_path));
}); });
@@ -6091,7 +6037,7 @@ mod common_parallel {
.unwrap(); .unwrap();
// Wait for the VM to be restored // Wait for the VM to be restored
thread::sleep(std::time::Duration::new(20, 0)); thread::sleep(std::time::Duration::new(10, 0));
let expected_events = [ let expected_events = [
&MetaEvent { &MetaEvent {
event: "starting".to_string(), event: "starting".to_string(),
@@ -6126,12 +6072,6 @@ mod common_parallel {
let r = std::panic::catch_unwind(|| { let r = std::panic::catch_unwind(|| {
// Resume the VM // Resume the VM
assert!(remote_command(&api_socket_restored, "resume", None)); assert!(remote_command(&api_socket_restored, "resume", None));
// There is no way that we can ensure the 'write()' to the
// event file is completed when the 'resume' request is
// returned successfully, because the 'write()' was done
// asynchronously from a different thread of Cloud
// Hypervisor (e.g. the event-monitor thread).
thread::sleep(std::time::Duration::new(1, 0));
let latest_events = [ let latest_events = [
&MetaEvent { &MetaEvent {
event: "resuming".to_string(), event: "resuming".to_string(),
@@ -6311,7 +6251,6 @@ mod common_parallel {
let api_socket = temp_api_path(&guest.tmp_dir); let api_socket = temp_api_path(&guest.tmp_dir);
let kernel_path = direct_kernel_boot_path(); let kernel_path = direct_kernel_boot_path();
let event_path = temp_event_monitor_path(&guest.tmp_dir);
let mut cmd = GuestCommand::new(&guest); let mut cmd = GuestCommand::new(&guest);
cmd.args(["--cpus", "boot=1"]) cmd.args(["--cpus", "boot=1"])
@@ -6322,7 +6261,6 @@ mod common_parallel {
.args(["--net", guest.default_net_string().as_str()]) .args(["--net", guest.default_net_string().as_str()])
.args(["--watchdog"]) .args(["--watchdog"])
.args(["--api-socket", &api_socket]) .args(["--api-socket", &api_socket])
.args(["--event-monitor", format!("path={event_path}").as_str()])
.capture_output(); .capture_output();
let mut child = cmd.spawn().unwrap(); let mut child = cmd.spawn().unwrap();
@@ -6367,17 +6305,7 @@ mod common_parallel {
{ {
// Now pause the VM and remain offline for 30s // Now pause the VM and remain offline for 30s
assert!(remote_command(&api_socket, "pause", None)); assert!(remote_command(&api_socket, "pause", None));
let latest_events = [ thread::sleep(std::time::Duration::new(30, 0));
&MetaEvent {
event: "pausing".to_string(),
device_id: None,
},
&MetaEvent {
event: "paused".to_string(),
device_id: None,
},
];
assert!(check_latest_events_exact(&latest_events, &event_path));
assert!(remote_command(&api_socket, "resume", None)); assert!(remote_command(&api_socket, "resume", None));
// Check no reboot // Check no reboot
@@ -6809,11 +6737,10 @@ mod common_parallel {
.unwrap(); .unwrap();
thread::sleep(std::time::Duration::new(2, 0)); thread::sleep(std::time::Duration::new(2, 0));
assert!(exec_host_command_with_retries( assert!(exec_host_command_status(
"/usr/local/bin/spdk-nvme/rpc.py nvmf_create_transport -t VFIOUSER", "/usr/local/bin/spdk-nvme/rpc.py nvmf_create_transport -t VFIOUSER"
3, )
std::time::Duration::new(5, 0), .success());
));
assert!(exec_host_command_status(&format!( assert!(exec_host_command_status(&format!(
"/usr/local/bin/spdk-nvme/rpc.py bdev_aio_create {} test 512", "/usr/local/bin/spdk-nvme/rpc.py bdev_aio_create {} test 512",
nvme_dir.join("test-disk.raw").to_str().unwrap() nvme_dir.join("test-disk.raw").to_str().unwrap()
@@ -6928,7 +6855,9 @@ mod common_parallel {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
fn test_vdpa_block() { fn test_vdpa_block() {
// Before trying to run the test, verify the vdpa_sim_blk module is correctly loaded. // Before trying to run the test, verify the vdpa_sim_blk module is correctly loaded.
assert!(exec_host_command_status("lsmod | grep vdpa_sim_blk").success()); if !exec_host_command_status("lsmod | grep vdpa_sim_blk").success() {
return;
}
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string()); let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(focal)); let guest = Guest::new(Box::new(focal));
@@ -7167,58 +7096,6 @@ mod common_parallel {
handle_child_output(r, &output); handle_child_output(r, &output);
} }
#[test]
#[cfg(target_arch = "x86_64")]
fn test_double_tty() {
let focal = UbuntuDiskConfig::new(FOCAL_IMAGE_NAME.to_string());
let guest = Guest::new(Box::new(focal));
let mut cmd = GuestCommand::new(&guest);
let api_socket = temp_api_path(&guest.tmp_dir);
let tty_str: &str = "console=hvc0 earlyprintk=ttyS0 ";
// linux printk module enable console log.
let con_dis_str: &str = "console [hvc0] enabled";
// linux printk module disable console log.
let con_enb_str: &str = "bootconsole [earlyser0] disabled";
let kernel_path = direct_kernel_boot_path();
cmd.args(["--cpus", "boot=1"])
.args(["--memory", "size=512M"])
.args(["--kernel", kernel_path.to_str().unwrap()])
.args([
"--cmdline",
DIRECT_KERNEL_BOOT_CMDLINE
.replace("console=hvc0 ", tty_str)
.as_str(),
])
.capture_output()
.default_disks()
.default_net()
.args(["--serial", "tty"])
.args(["--console", "tty"])
.args(["--api-socket", &api_socket]);
let mut child = cmd.spawn().unwrap();
let mut r = std::panic::catch_unwind(|| {
guest.wait_vm_boot(None).unwrap();
});
let _ = child.kill();
let output = child.wait_with_output().unwrap();
if r.is_ok() {
r = std::panic::catch_unwind(|| {
let s = String::from_utf8_lossy(&output.stdout);
assert!(s.contains(tty_str));
assert!(s.contains(con_dis_str));
assert!(s.contains(con_enb_str));
});
}
handle_child_output(r, &output);
}
} }
mod dbus_api { mod dbus_api {
@@ -8575,13 +8452,8 @@ mod live_migration {
if !send_success { if !send_success {
let _ = send_migration.kill(); let _ = send_migration.kill();
let output = send_migration.wait_with_output().unwrap(); let output = send_migration.wait_with_output().unwrap();
eprintln!( eprintln!("\n\n==== Start 'send_migration' output ====\n\n---stdout---\n{}\n\n---stderr---\n{}\n\n==== End 'send_migration' output ====\n\n",
"\n\n==== Start 'send_migration' output ==== \ String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr));
\n\n---stdout---\n{}\n\n---stderr---\n{} \
\n\n==== End 'send_migration' output ====\n\n",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
} }
// The 'receive-migration' command should be executed successfully within the given timeout // The 'receive-migration' command should be executed successfully within the given timeout
@@ -8597,13 +8469,8 @@ mod live_migration {
if !receive_success { if !receive_success {
let _ = receive_migration.kill(); let _ = receive_migration.kill();
let output = receive_migration.wait_with_output().unwrap(); let output = receive_migration.wait_with_output().unwrap();
eprintln!( eprintln!("\n\n==== Start 'receive_migration' output ====\n\n---stdout---\n{}\n\n---stderr---\n{}\n\n==== End 'receive_migration' output ====\n\n",
"\n\n==== Start 'receive_migration' output ==== \ String::from_utf8_lossy(&output.stdout), String::from_utf8_lossy(&output.stderr));
\n\n---stdout---\n{}\n\n---stderr---\n{} \
\n\n==== End 'receive_migration' output ====\n\n",
String::from_utf8_lossy(&output.stdout),
String::from_utf8_lossy(&output.stderr)
);
} }
send_success && receive_success send_success && receive_success
@@ -9606,7 +9473,6 @@ mod live_migration {
} }
#[test] #[test]
#[cfg(target_arch = "aarch64")] // see: #6272
#[cfg(not(feature = "mshv"))] #[cfg(not(feature = "mshv"))]
fn test_live_upgrade_numa() { fn test_live_upgrade_numa() {
_test_live_migration_numa(true, false) _test_live_migration_numa(true, false)
@@ -9669,7 +9535,6 @@ mod live_migration {
} }
#[test] #[test]
#[ignore = "See #5532"]
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
#[cfg(not(feature = "mshv"))] #[cfg(not(feature = "mshv"))]
fn test_live_upgrade_ovs_dpdk_local() { fn test_live_upgrade_ovs_dpdk_local() {
@@ -9760,9 +9625,7 @@ mod rate_limiter {
} }
eprintln!( eprintln!(
"\n\n==== Start 'check_rate_limit' failed ==== \ "\n\n==== check_rate_limit failed! ====\n\nmeasured={measured}, , lower_limit={lower_limit}, upper_limit={upper_limit}\n\n"
\n\nmeasured={measured}, , lower_limit={lower_limit}, upper_limit={upper_limit} \
\n\n==== End 'check_rate_limit' failed ====\n\n"
); );
false false

View File

@@ -12,4 +12,4 @@ libc = "0.2.138"
log = "0.4.17" log = "0.4.17"
net_gen = { path = "../net_gen" } net_gen = { path = "../net_gen" }
thiserror = "1.0.37" thiserror = "1.0.37"
vmm-sys-util = "0.12.1" vmm-sys-util = "0.11.0"

View File

@@ -6,7 +6,7 @@ edition = "2021"
[dependencies] [dependencies]
libc = "0.2.147" libc = "0.2.147"
log = "0.4.20" log = "0.4.17"
once_cell = "1.18.0" once_cell = "1.18.0"
serde = { version = "1.0.168", features = ["rc", "derive"] } serde = { version = "1.0.168", features = ["rc", "derive"] }
serde_json = "1.0.107" serde_json = "1.0.107"

View File

@@ -6,16 +6,17 @@ edition = "2021"
build = "../build.rs" build = "../build.rs"
[dependencies] [dependencies]
clap = { version = "4.4.7", features = ["wrap_help","cargo"] } clap = { version = "4.3.11", features = ["wrap_help","cargo"] }
block = { path = "../block" } block = { path = "../block" }
env_logger = "0.10.0" env_logger = "0.10.0"
epoll = "4.3.3" epoll = "4.3.3"
libc = "0.2.147" libc = "0.2.147"
log = "0.4.20" log = "0.4.17"
option_parser = { path = "../option_parser" } option_parser = { path = "../option_parser" }
vhost = { version = "0.10.0", features = ["vhost-user-backend"] } vhost = { version = "0.8.1", features = ["vhost-user-slave"] }
vhost-user-backend = "0.13.1" vhost-user-backend = "0.10.1"
virtio-bindings = "0.2.0" virtio-bindings = "0.2.0"
virtio-queue = "0.11.0" virtio-queue = "0.9.0"
vm-memory = "0.14.0" vm-memory = "0.12.2"
vmm-sys-util = "0.12.1" vmm-sys-util = "0.11.0"

View File

@@ -58,7 +58,6 @@ impl<D: Read + Seek + Write + Send> DiskFile for D {}
type Result<T> = std::result::Result<T, Error>; type Result<T> = std::result::Result<T, Error>;
type VhostUserBackendResult<T> = std::result::Result<T, std::io::Error>; type VhostUserBackendResult<T> = std::result::Result<T, std::io::Error>;
#[allow(dead_code)]
#[derive(Debug)] #[derive(Debug)]
enum Error { enum Error {
/// Failed to create kill eventfd /// Failed to create kill eventfd
@@ -300,10 +299,9 @@ impl VhostUserBlkBackend {
} }
} }
impl VhostUserBackendMut for VhostUserBlkBackend { impl VhostUserBackendMut<VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>, AtomicBitmap>
type Bitmap = AtomicBitmap; for VhostUserBlkBackend
type Vring = VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>; {
fn num_queues(&self) -> usize { fn num_queues(&self) -> usize {
self.config.num_queues as usize self.config.num_queues as usize
} }
@@ -352,7 +350,7 @@ impl VhostUserBackendMut for VhostUserBlkBackend {
evset: EventSet, evset: EventSet,
vrings: &[VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>], vrings: &[VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>],
thread_id: usize, thread_id: usize,
) -> VhostUserBackendResult<()> { ) -> VhostUserBackendResult<bool> {
if evset != EventSet::IN { if evset != EventSet::IN {
return Err(Error::HandleEventNotEpollIn.into()); return Err(Error::HandleEventNotEpollIn.into());
} }
@@ -396,7 +394,7 @@ impl VhostUserBackendMut for VhostUserBlkBackend {
thread.process_queue(&mut vring); thread.process_queue(&mut vring);
} }
Ok(()) Ok(false)
} }
_ => Err(Error::HandleEventUnknownEvent.into()), _ => Err(Error::HandleEventUnknownEvent.into()),
} }

View File

@@ -6,15 +6,16 @@ edition = "2021"
build = "../build.rs" build = "../build.rs"
[dependencies] [dependencies]
clap = { version = "4.4.7", features = ["wrap_help","cargo"] } clap = { version = "4.3.11", features = ["wrap_help","cargo"] }
env_logger = "0.10.0" env_logger = "0.10.0"
epoll = "4.3.3" epoll = "4.3.3"
libc = "0.2.147" libc = "0.2.147"
log = "0.4.20" log = "0.4.17"
net_util = { path = "../net_util" } net_util = { path = "../net_util" }
option_parser = { path = "../option_parser" } option_parser = { path = "../option_parser" }
vhost = { version = "0.10.0", features = ["vhost-user-backend"] } vhost = { version = "0.8.1", features = ["vhost-user-slave"] }
vhost-user-backend = "0.13.1" vhost-user-backend = "0.10.1"
virtio-bindings = "0.2.0" virtio-bindings = "0.2.0"
vm-memory = "0.14.0" vm-memory = "0.12.2"
vmm-sys-util = "0.12.1" vmm-sys-util = "0.11.0"

View File

@@ -158,10 +158,9 @@ impl VhostUserNetBackend {
} }
} }
impl VhostUserBackendMut for VhostUserNetBackend { impl VhostUserBackendMut<VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>, AtomicBitmap>
type Bitmap = AtomicBitmap; for VhostUserNetBackend
type Vring = VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>; {
fn num_queues(&self) -> usize { fn num_queues(&self) -> usize {
self.num_queues self.num_queues
} }
@@ -204,7 +203,7 @@ impl VhostUserBackendMut for VhostUserNetBackend {
_evset: EventSet, _evset: EventSet,
vrings: &[VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>], vrings: &[VringRwLock<GuestMemoryAtomic<GuestMemoryMmap>>],
thread_id: usize, thread_id: usize,
) -> VhostUserBackendResult<()> { ) -> VhostUserBackendResult<bool> {
let mut thread = self.threads[thread_id].lock().unwrap(); let mut thread = self.threads[thread_id].lock().unwrap();
match device_event { match device_event {
0 => { 0 => {
@@ -246,7 +245,7 @@ impl VhostUserBackendMut for VhostUserNetBackend {
_ => return Err(Error::HandleEventUnknownEvent.into()), _ => return Err(Error::HandleEventUnknownEvent.into()),
} }
Ok(()) Ok(false)
} }
fn exit_event(&self, thread_index: usize) -> Option<EventFd> { fn exit_event(&self, thread_index: usize) -> Option<EventFd> {

View File

@@ -15,7 +15,7 @@ byteorder = "1.4.3"
epoll = "4.3.3" epoll = "4.3.3"
event_monitor = { path = "../event_monitor" } event_monitor = { path = "../event_monitor" }
libc = "0.2.147" libc = "0.2.147"
log = "0.4.20" log = "0.4.17"
net_gen = { path = "../net_gen" } net_gen = { path = "../net_gen" }
net_util = { path = "../net_util" } net_util = { path = "../net_util" }
pci = { path = "../pci" } pci = { path = "../pci" }
@@ -24,15 +24,15 @@ seccompiler = "0.4.0"
serde = { version = "1.0.168", features = ["derive"] } serde = { version = "1.0.168", features = ["derive"] }
serde_json = "1.0.107" serde_json = "1.0.107"
serial_buffer = { path = "../serial_buffer" } serial_buffer = { path = "../serial_buffer" }
thiserror = "1.0.52" thiserror = "1.0.40"
versionize = "0.2.0" versionize = "0.1.10"
versionize_derive = "0.1.6" versionize_derive = "0.1.4"
vhost = { version = "0.10.0", features = ["vhost-user-frontend", "vhost-user-backend", "vhost-kern", "vhost-vdpa"] } vhost = { version = "0.8.1", features = ["vhost-user-master", "vhost-user-slave", "vhost-kern", "vhost-vdpa"] }
virtio-bindings = { version = "0.2.0", features = ["virtio-v5_0_0"] } virtio-bindings = { version = "0.2.0", features = ["virtio-v5_0_0"] }
virtio-queue = "0.11.0" virtio-queue = "0.9.0"
vm-allocator = { path = "../vm-allocator" } vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" } vm-device = { path = "../vm-device" }
vm-memory = { version = "0.14.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] } vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-migration = { path = "../vm-migration" } vm-migration = { path = "../vm-migration" }
vm-virtio = { path = "../vm-virtio" } vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = "0.12.1" vmm-sys-util = "0.11.0"

View File

@@ -28,7 +28,7 @@ use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult}; use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize; use versionize_derive::Versionize;
use virtio_queue::{Queue, QueueT}; use virtio_queue::{Queue, QueueT};
use vm_memory::{ByteValued, Bytes, GuestAddressSpace, GuestMemory, GuestMemoryAtomic}; use vm_memory::{ByteValued, Bytes, GuestAddressSpace, GuestMemoryAtomic};
use vm_migration::VersionMapped; use vm_migration::VersionMapped;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable}; use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_virtio::{AccessPlatform, Translatable}; use vm_virtio::{AccessPlatform, Translatable};
@@ -59,8 +59,6 @@ enum Error {
GuestMemoryRead(vm_memory::guest_memory::Error), GuestMemoryRead(vm_memory::guest_memory::Error),
#[error("Failed to write to guest memory: {0}")] #[error("Failed to write to guest memory: {0}")]
GuestMemoryWrite(vm_memory::guest_memory::Error), GuestMemoryWrite(vm_memory::guest_memory::Error),
#[error("Failed to write_all output: {0}")]
OutputWriteAll(io::Error),
#[error("Failed to flush output: {0}")] #[error("Failed to flush output: {0}")]
OutputFlush(io::Error), OutputFlush(io::Error),
#[error("Failed to add used index: {0}")] #[error("Failed to add used index: {0}")]
@@ -266,18 +264,15 @@ impl ConsoleEpollHandler {
while let Some(mut desc_chain) = trans_queue.pop_descriptor_chain(self.mem.memory()) { while let Some(mut desc_chain) = trans_queue.pop_descriptor_chain(self.mem.memory()) {
let desc = desc_chain.next().ok_or(Error::DescriptorChainTooShort)?; let desc = desc_chain.next().ok_or(Error::DescriptorChainTooShort)?;
if let Some(out) = &mut self.out { if let Some(out) = &mut self.out {
let mut buf: Vec<u8> = Vec::new();
desc_chain desc_chain
.memory() .memory()
.write_volatile_to( .write_to(
desc.addr() desc.addr()
.translate_gva(self.access_platform.as_ref(), desc.len() as usize), .translate_gva(self.access_platform.as_ref(), desc.len() as usize),
&mut buf, out,
desc.len() as usize, desc.len() as usize,
) )
.map_err(Error::GuestMemoryRead)?; .map_err(Error::GuestMemoryRead)?;
out.write_all(&buf).map_err(Error::OutputWriteAll)?;
out.flush().map_err(Error::OutputFlush)?; out.flush().map_err(Error::OutputFlush)?;
} }
trans_queue trans_queue

View File

@@ -24,7 +24,7 @@ use thiserror::Error;
use versionize::{VersionMap, Versionize, VersionizeResult}; use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize; use versionize_derive::Versionize;
use virtio_queue::{Queue, QueueT}; use virtio_queue::{Queue, QueueT};
use vm_memory::{GuestAddressSpace, GuestMemory, GuestMemoryAtomic}; use vm_memory::{Bytes, GuestAddressSpace, GuestMemoryAtomic};
use vm_migration::VersionMapped; use vm_migration::VersionMapped;
use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable}; use vm_migration::{Migratable, MigratableError, Pausable, Snapshot, Snapshottable, Transportable};
use vm_virtio::{AccessPlatform, Translatable}; use vm_virtio::{AccessPlatform, Translatable};
@@ -75,7 +75,7 @@ impl RngEpollHandler {
// Fill the read with data from the random device on the host. // Fill the read with data from the random device on the host.
let len = desc_chain let len = desc_chain
.memory() .memory()
.read_volatile_from( .read_from(
desc.addr() desc.addr()
.translate_gva(self.access_platform.as_ref(), desc.len() as usize), .translate_gva(self.access_platform.as_ref(), desc.len() as usize),
&mut self.random_file, &mut self.random_file,

View File

@@ -955,9 +955,8 @@ impl PciDevice for VirtioPciDevice {
fn allocate_bars( fn allocate_bars(
&mut self, &mut self,
_allocator: &Arc<Mutex<SystemAllocator>>, allocator: &Arc<Mutex<SystemAllocator>>,
mmio32_allocator: &mut AddressAllocator, mmio_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
resources: Option<Vec<Resource>>, resources: Option<Vec<Resource>>,
) -> std::result::Result<Vec<PciBarConfiguration>, PciDeviceError> { ) -> std::result::Result<Vec<PciBarConfiguration>, PciDeviceError> {
let mut bars = Vec::new(); let mut bars = Vec::new();
@@ -996,7 +995,7 @@ impl PciDevice for VirtioPciDevice {
// See http://docs.oasis-open.org/virtio/virtio/v1.0/cs04/virtio-v1.0-cs04.html#x1-740004 // See http://docs.oasis-open.org/virtio/virtio/v1.0/cs04/virtio-v1.0-cs04.html#x1-740004
let (virtio_pci_bar_addr, region_type) = if use_64bit_bar { let (virtio_pci_bar_addr, region_type) = if use_64bit_bar {
let region_type = PciBarRegionType::Memory64BitRegion; let region_type = PciBarRegionType::Memory64BitRegion;
let addr = mmio64_allocator let addr = mmio_allocator
.allocate( .allocate(
settings_bar_addr, settings_bar_addr,
CAPABILITY_BAR_SIZE, CAPABILITY_BAR_SIZE,
@@ -1006,8 +1005,10 @@ impl PciDevice for VirtioPciDevice {
(addr, region_type) (addr, region_type)
} else { } else {
let region_type = PciBarRegionType::Memory32BitRegion; let region_type = PciBarRegionType::Memory32BitRegion;
let addr = mmio32_allocator let addr = allocator
.allocate( .lock()
.unwrap()
.allocate_mmio_hole_addresses(
settings_bar_addr, settings_bar_addr,
CAPABILITY_BAR_SIZE, CAPABILITY_BAR_SIZE,
Some(CAPABILITY_BAR_SIZE), Some(CAPABILITY_BAR_SIZE),
@@ -1077,17 +1078,16 @@ impl PciDevice for VirtioPciDevice {
fn free_bars( fn free_bars(
&mut self, &mut self,
_allocator: &mut SystemAllocator, allocator: &mut SystemAllocator,
mmio32_allocator: &mut AddressAllocator, mmio_allocator: &mut AddressAllocator,
mmio64_allocator: &mut AddressAllocator,
) -> std::result::Result<(), PciDeviceError> { ) -> std::result::Result<(), PciDeviceError> {
for bar in self.bar_regions.drain(..) { for bar in self.bar_regions.drain(..) {
match bar.region_type() { match bar.region_type() {
PciBarRegionType::Memory32BitRegion => { PciBarRegionType::Memory32BitRegion => {
mmio32_allocator.free(GuestAddress(bar.addr()), bar.size()); allocator.free_mmio_hole_addresses(GuestAddress(bar.addr()), bar.size());
} }
PciBarRegionType::Memory64BitRegion => { PciBarRegionType::Memory64BitRegion => {
mmio64_allocator.free(GuestAddress(bar.addr()), bar.size()); mmio_allocator.free(GuestAddress(bar.addr()), bar.size());
} }
_ => error!("Unexpected PCI bar type"), _ => error!("Unexpected PCI bar type"),
} }

View File

@@ -23,7 +23,7 @@ use vhost::vhost_user::message::{
VhostUserConfigFlags, VhostUserProtocolFeatures, VhostUserVirtioFeatures, VhostUserConfigFlags, VhostUserProtocolFeatures, VhostUserVirtioFeatures,
VHOST_USER_CONFIG_OFFSET, VHOST_USER_CONFIG_OFFSET,
}; };
use vhost::vhost_user::{FrontendReqHandler, VhostUserFrontend, VhostUserFrontendReqHandler}; use vhost::vhost_user::{MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler};
use virtio_bindings::virtio_blk::{ use virtio_bindings::virtio_blk::{
VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_CONFIG_WCE, VIRTIO_BLK_F_DISCARD, VIRTIO_BLK_F_FLUSH, VIRTIO_BLK_F_BLK_SIZE, VIRTIO_BLK_F_CONFIG_WCE, VIRTIO_BLK_F_DISCARD, VIRTIO_BLK_F_FLUSH,
VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_MQ, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_GEOMETRY, VIRTIO_BLK_F_MQ, VIRTIO_BLK_F_RO, VIRTIO_BLK_F_SEG_MAX,
@@ -50,8 +50,8 @@ pub struct State {
impl VersionMapped for State {} impl VersionMapped for State {}
struct BackendReqHandler {} struct SlaveReqHandler {}
impl VhostUserFrontendReqHandler for BackendReqHandler {} impl VhostUserMasterReqHandler for SlaveReqHandler {}
pub struct Blk { pub struct Blk {
common: VirtioCommon, common: VirtioCommon,
@@ -294,7 +294,7 @@ impl VirtioDevice for Blk {
self.common.activate(&queues, &interrupt_cb)?; self.common.activate(&queues, &interrupt_cb)?;
self.guest_memory = Some(mem.clone()); self.guest_memory = Some(mem.clone());
let backend_req_handler: Option<FrontendReqHandler<BackendReqHandler>> = None; let slave_req_handler: Option<MasterReqHandler<SlaveReqHandler>> = None;
// Run a dedicated thread for handling potential reconnections with // Run a dedicated thread for handling potential reconnections with
// the backend. // the backend.
@@ -305,7 +305,7 @@ impl VirtioDevice for Blk {
queues, queues,
interrupt_cb, interrupt_cb,
self.common.acked_features, self.common.acked_features,
backend_req_handler, slave_req_handler,
kill_evt, kill_evt,
pause_evt, pause_evt,
)?; )?;

View File

@@ -22,11 +22,11 @@ use std::thread;
use versionize::{VersionMap, Versionize, VersionizeResult}; use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize; use versionize_derive::Versionize;
use vhost::vhost_user::message::{ use vhost::vhost_user::message::{
VhostUserFSBackendMsg, VhostUserFSBackendMsgFlags, VhostUserProtocolFeatures, VhostUserFSSlaveMsg, VhostUserFSSlaveMsgFlags, VhostUserProtocolFeatures,
VhostUserVirtioFeatures, VHOST_USER_FS_BACKEND_ENTRIES, VhostUserVirtioFeatures, VHOST_USER_FS_SLAVE_ENTRIES,
}; };
use vhost::vhost_user::{ use vhost::vhost_user::{
FrontendReqHandler, HandlerResult, VhostUserFrontend, VhostUserFrontendReqHandler, HandlerResult, MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler,
}; };
use virtio_queue::Queue; use virtio_queue::Queue;
use vm_memory::{ use vm_memory::{
@@ -48,19 +48,19 @@ pub struct State {
pub config: VirtioFsConfig, pub config: VirtioFsConfig,
pub acked_protocol_features: u64, pub acked_protocol_features: u64,
pub vu_num_queues: usize, pub vu_num_queues: usize,
pub backend_req_support: bool, pub slave_req_support: bool,
} }
impl VersionMapped for State {} impl VersionMapped for State {}
struct BackendReqHandler { struct SlaveReqHandler {
cache_offset: GuestAddress, cache_offset: GuestAddress,
cache_size: u64, cache_size: u64,
mmap_cache_addr: u64, mmap_cache_addr: u64,
mem: GuestMemoryAtomic<GuestMemoryMmap>, mem: GuestMemoryAtomic<GuestMemoryMmap>,
} }
impl BackendReqHandler { impl SlaveReqHandler {
// Make sure request is within cache range // Make sure request is within cache range
fn is_req_valid(&self, offset: u64, len: u64) -> bool { fn is_req_valid(&self, offset: u64, len: u64) -> bool {
let end = match offset.checked_add(len) { let end = match offset.checked_add(len) {
@@ -72,16 +72,16 @@ impl BackendReqHandler {
} }
} }
impl VhostUserFrontendReqHandler for BackendReqHandler { impl VhostUserMasterReqHandler for SlaveReqHandler {
fn handle_config_change(&self) -> HandlerResult<u64> { fn handle_config_change(&self) -> HandlerResult<u64> {
debug!("handle_config_change"); debug!("handle_config_change");
Ok(0) Ok(0)
} }
fn fs_backend_map(&self, fs: &VhostUserFSBackendMsg, fd: &dyn AsRawFd) -> HandlerResult<u64> { fn fs_slave_map(&self, fs: &VhostUserFSSlaveMsg, fd: &dyn AsRawFd) -> HandlerResult<u64> {
debug!("fs_backend_map"); debug!("fs_slave_map");
for i in 0..VHOST_USER_FS_BACKEND_ENTRIES { for i in 0..VHOST_USER_FS_SLAVE_ENTRIES {
let offset = fs.cache_offset[i]; let offset = fs.cache_offset[i];
let len = fs.len[i]; let len = fs.len[i];
@@ -115,10 +115,10 @@ impl VhostUserFrontendReqHandler for BackendReqHandler {
Ok(0) Ok(0)
} }
fn fs_backend_unmap(&self, fs: &VhostUserFSBackendMsg) -> HandlerResult<u64> { fn fs_slave_unmap(&self, fs: &VhostUserFSSlaveMsg) -> HandlerResult<u64> {
debug!("fs_backend_unmap"); debug!("fs_slave_unmap");
for i in 0..VHOST_USER_FS_BACKEND_ENTRIES { for i in 0..VHOST_USER_FS_SLAVE_ENTRIES {
let mut len = fs.len[i]; let mut len = fs.len[i];
// Ignore if the length is 0. // Ignore if the length is 0.
@@ -126,7 +126,7 @@ impl VhostUserFrontendReqHandler for BackendReqHandler {
continue; continue;
} }
// Need to handle a special case where the backend ask for the unmapping // Need to handle a special case where the slave ask for the unmapping
// of the entire mapping. // of the entire mapping.
let offset = if len == 0xffff_ffff_ffff_ffff { let offset = if len == 0xffff_ffff_ffff_ffff {
len = self.cache_size; len = self.cache_size;
@@ -159,10 +159,10 @@ impl VhostUserFrontendReqHandler for BackendReqHandler {
Ok(0) Ok(0)
} }
fn fs_backend_sync(&self, fs: &VhostUserFSBackendMsg) -> HandlerResult<u64> { fn fs_slave_sync(&self, fs: &VhostUserFSSlaveMsg) -> HandlerResult<u64> {
debug!("fs_backend_sync"); debug!("fs_slave_sync");
for i in 0..VHOST_USER_FS_BACKEND_ENTRIES { for i in 0..VHOST_USER_FS_SLAVE_ENTRIES {
let offset = fs.cache_offset[i]; let offset = fs.cache_offset[i];
let len = fs.len[i]; let len = fs.len[i];
@@ -187,11 +187,11 @@ impl VhostUserFrontendReqHandler for BackendReqHandler {
Ok(0) Ok(0)
} }
fn fs_backend_io(&self, fs: &VhostUserFSBackendMsg, fd: &dyn AsRawFd) -> HandlerResult<u64> { fn fs_slave_io(&self, fs: &VhostUserFSSlaveMsg, fd: &dyn AsRawFd) -> HandlerResult<u64> {
debug!("fs_backend_io"); debug!("fs_slave_io");
let mut done: u64 = 0; let mut done: u64 = 0;
for i in 0..VHOST_USER_FS_BACKEND_ENTRIES { for i in 0..VHOST_USER_FS_SLAVE_ENTRIES {
// Ignore if the length is 0. // Ignore if the length is 0.
if fs.len[i] == 0 { if fs.len[i] == 0 {
continue; continue;
@@ -230,8 +230,8 @@ impl VhostUserFrontendReqHandler for BackendReqHandler {
}; };
while len > 0 { while len > 0 {
let ret = if (fs.flags[i] & VhostUserFSBackendMsgFlags::MAP_W) let ret = if (fs.flags[i] & VhostUserFSSlaveMsgFlags::MAP_W)
== VhostUserFSBackendMsgFlags::MAP_W == VhostUserFSSlaveMsgFlags::MAP_W
{ {
debug!("write: foffset={}, len={}", foffset, len); debug!("write: foffset={}, len={}", foffset, len);
// SAFETY: FFI call with valid arguments // SAFETY: FFI call with valid arguments
@@ -298,7 +298,7 @@ pub struct Fs {
// Hold ownership of the memory that is allocated for the device // Hold ownership of the memory that is allocated for the device
// which will be automatically dropped when the device is dropped // which will be automatically dropped when the device is dropped
cache: Option<(VirtioSharedMemoryList, MmapRegion)>, cache: Option<(VirtioSharedMemoryList, MmapRegion)>,
backend_req_support: bool, slave_req_support: bool,
seccomp_action: SeccompAction, seccomp_action: SeccompAction,
guest_memory: Option<GuestMemoryAtomic<GuestMemoryMmap>>, guest_memory: Option<GuestMemoryAtomic<GuestMemoryMmap>>,
epoll_thread: Option<thread::JoinHandle<()>>, epoll_thread: Option<thread::JoinHandle<()>>,
@@ -321,7 +321,7 @@ impl Fs {
iommu: bool, iommu: bool,
state: Option<State>, state: Option<State>,
) -> Result<Fs> { ) -> Result<Fs> {
let mut backend_req_support = false; let mut slave_req_support = false;
// Calculate the actual number of queues needed. // Calculate the actual number of queues needed.
let num_queues = NUM_QUEUE_OFFSET + req_num_queues; let num_queues = NUM_QUEUE_OFFSET + req_num_queues;
@@ -335,7 +335,7 @@ impl Fs {
acked_protocol_features, acked_protocol_features,
vu_num_queues, vu_num_queues,
config, config,
backend_req_support, slave_req_support,
paused, paused,
) = if let Some(state) = state { ) = if let Some(state) = state {
info!("Restoring vhost-user-fs {}", id); info!("Restoring vhost-user-fs {}", id);
@@ -351,7 +351,7 @@ impl Fs {
state.acked_protocol_features, state.acked_protocol_features,
state.vu_num_queues, state.vu_num_queues,
state.config, state.config,
state.backend_req_support, state.slave_req_support,
true, true,
) )
} else { } else {
@@ -363,10 +363,10 @@ impl Fs {
| VhostUserProtocolFeatures::REPLY_ACK | VhostUserProtocolFeatures::REPLY_ACK
| VhostUserProtocolFeatures::INFLIGHT_SHMFD | VhostUserProtocolFeatures::INFLIGHT_SHMFD
| VhostUserProtocolFeatures::LOG_SHMFD; | VhostUserProtocolFeatures::LOG_SHMFD;
let backend_protocol_features = let slave_protocol_features =
VhostUserProtocolFeatures::BACKEND_REQ | VhostUserProtocolFeatures::BACKEND_SEND_FD; VhostUserProtocolFeatures::SLAVE_REQ | VhostUserProtocolFeatures::SLAVE_SEND_FD;
if cache.is_some() { if cache.is_some() {
avail_protocol_features |= backend_protocol_features; avail_protocol_features |= slave_protocol_features;
} }
let (acked_features, acked_protocol_features) = let (acked_features, acked_protocol_features) =
@@ -389,10 +389,10 @@ impl Fs {
return Err(Error::BadQueueNum); return Err(Error::BadQueueNum);
} }
if acked_protocol_features & backend_protocol_features.bits() if acked_protocol_features & slave_protocol_features.bits()
== backend_protocol_features.bits() == slave_protocol_features.bits()
{ {
backend_req_support = true; slave_req_support = true;
} }
// Create virtio-fs device configuration. // Create virtio-fs device configuration.
@@ -411,7 +411,7 @@ impl Fs {
acked_protocol_features, acked_protocol_features,
num_queues, num_queues,
config, config,
backend_req_support, slave_req_support,
false, false,
) )
}; };
@@ -437,7 +437,7 @@ impl Fs {
id, id,
config, config,
cache, cache,
backend_req_support, slave_req_support,
seccomp_action, seccomp_action,
guest_memory: None, guest_memory: None,
epoll_thread: None, epoll_thread: None,
@@ -453,7 +453,7 @@ impl Fs {
config: self.config, config: self.config,
acked_protocol_features: self.vu_common.acked_protocol_features, acked_protocol_features: self.vu_common.acked_protocol_features,
vu_num_queues: self.vu_common.vu_num_queues, vu_num_queues: self.vu_common.vu_num_queues,
backend_req_support: self.backend_req_support, slave_req_support: self.slave_req_support,
} }
} }
} }
@@ -507,10 +507,10 @@ impl VirtioDevice for Fs {
self.common.activate(&queues, &interrupt_cb)?; self.common.activate(&queues, &interrupt_cb)?;
self.guest_memory = Some(mem.clone()); self.guest_memory = Some(mem.clone());
// Initialize backend communication. // Initialize slave communication.
let backend_req_handler = if self.backend_req_support { let slave_req_handler = if self.slave_req_support {
if let Some(cache) = self.cache.as_ref() { if let Some(cache) = self.cache.as_ref() {
let vu_frontend_req_handler = Arc::new(BackendReqHandler { let vu_master_req_handler = Arc::new(SlaveReqHandler {
cache_offset: cache.0.addr, cache_offset: cache.0.addr,
cache_size: cache.0.len, cache_size: cache.0.len,
mmap_cache_addr: cache.0.host_addr, mmap_cache_addr: cache.0.host_addr,
@@ -518,8 +518,8 @@ impl VirtioDevice for Fs {
}); });
let mut req_handler = let mut req_handler =
FrontendReqHandler::new(vu_frontend_req_handler).map_err(|e| { MasterReqHandler::new(vu_master_req_handler).map_err(|e| {
ActivateError::VhostUserFsSetup(Error::FrontendReqHandlerCreation(e)) ActivateError::VhostUserFsSetup(Error::MasterReqHandlerCreation(e))
})?; })?;
if self.vu_common.acked_protocol_features if self.vu_common.acked_protocol_features
@@ -546,7 +546,7 @@ impl VirtioDevice for Fs {
queues, queues,
interrupt_cb, interrupt_cb,
self.common.acked_features, self.common.acked_features,
backend_req_handler, slave_req_handler,
kill_evt, kill_evt,
pause_evt, pause_evt,
)?; )?;

View File

@@ -17,7 +17,7 @@ use versionize::Versionize;
use vhost::vhost_user::message::{ use vhost::vhost_user::message::{
VhostUserInflight, VhostUserProtocolFeatures, VhostUserVirtioFeatures, VhostUserInflight, VhostUserProtocolFeatures, VhostUserVirtioFeatures,
}; };
use vhost::vhost_user::{FrontendReqHandler, VhostUserFrontendReqHandler}; use vhost::vhost_user::{MasterReqHandler, VhostUserMasterReqHandler};
use vhost::Error as VhostError; use vhost::Error as VhostError;
use virtio_queue::Error as QueueError; use virtio_queue::Error as QueueError;
use virtio_queue::Queue; use virtio_queue::Queue;
@@ -61,8 +61,8 @@ pub enum Error {
MemoryRegions(MmapError), MemoryRegions(MmapError),
#[error("Failed removing socket path: {0}")] #[error("Failed removing socket path: {0}")]
RemoveSocketPath(io::Error), RemoveSocketPath(io::Error),
#[error("Failed to create frontend: {0}")] #[error("Failed to create master: {0}")]
VhostUserCreateFrontend(VhostError), VhostUserCreateMaster(VhostError),
#[error("Failed to open vhost device: {0}")] #[error("Failed to open vhost device: {0}")]
VhostUserOpen(VhostError), VhostUserOpen(VhostError),
#[error("Connection to socket failed")] #[error("Connection to socket failed")]
@@ -105,10 +105,10 @@ pub enum Error {
VhostIrqRead(io::Error), VhostIrqRead(io::Error),
#[error("Failed to read vhost eventfd: {0}")] #[error("Failed to read vhost eventfd: {0}")]
VhostUserMemoryRegion(MmapError), VhostUserMemoryRegion(MmapError),
#[error("Failed to create the frontend request handler from backend: {0}")] #[error("Failed to create the master request handler from slave: {0}")]
FrontendReqHandlerCreation(vhost::vhost_user::Error), MasterReqHandlerCreation(vhost::vhost_user::Error),
#[error("Set backend request fd failed: {0}")] #[error("Set slave request fd failed: {0}")]
VhostUserSetBackendRequestFd(vhost::Error), VhostUserSetSlaveRequestFd(vhost::Error),
#[error("Add memory region failed: {0}")] #[error("Add memory region failed: {0}")]
VhostUserAddMemReg(VhostError), VhostUserAddMemReg(VhostError),
#[error("Failed getting the configuration: {0}")] #[error("Failed getting the configuration: {0}")]
@@ -155,7 +155,7 @@ pub const DEFAULT_VIRTIO_FEATURES: u64 = 1 << VIRTIO_F_RING_INDIRECT_DESC
| VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits(); | VhostUserVirtioFeatures::PROTOCOL_FEATURES.bits();
const HUP_CONNECTION_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 1; const HUP_CONNECTION_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 1;
const BACKEND_REQ_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 2; const SLAVE_REQ_EVENT: u16 = EPOLL_HELPER_EVENT_LAST + 2;
#[derive(Default)] #[derive(Default)]
pub struct Inflight { pub struct Inflight {
@@ -163,7 +163,7 @@ pub struct Inflight {
pub fd: Option<std::fs::File>, pub fd: Option<std::fs::File>,
} }
pub struct VhostUserEpollHandler<S: VhostUserFrontendReqHandler> { pub struct VhostUserEpollHandler<S: VhostUserMasterReqHandler> {
pub vu: Arc<Mutex<VhostUserHandle>>, pub vu: Arc<Mutex<VhostUserHandle>>,
pub mem: GuestMemoryAtomic<GuestMemoryMmap>, pub mem: GuestMemoryAtomic<GuestMemoryMmap>,
pub kill_evt: EventFd, pub kill_evt: EventFd,
@@ -174,11 +174,11 @@ pub struct VhostUserEpollHandler<S: VhostUserFrontendReqHandler> {
pub acked_protocol_features: u64, pub acked_protocol_features: u64,
pub socket_path: String, pub socket_path: String,
pub server: bool, pub server: bool,
pub backend_req_handler: Option<FrontendReqHandler<S>>, pub slave_req_handler: Option<MasterReqHandler<S>>,
pub inflight: Option<Inflight>, pub inflight: Option<Inflight>,
} }
impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> { impl<S: VhostUserMasterReqHandler> VhostUserEpollHandler<S> {
pub fn run( pub fn run(
&mut self, &mut self,
paused: Arc<AtomicBool>, paused: Arc<AtomicBool>,
@@ -191,8 +191,8 @@ impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
epoll::Events::EPOLLHUP, epoll::Events::EPOLLHUP,
)?; )?;
if let Some(backend_req_handler) = &self.backend_req_handler { if let Some(slave_req_handler) = &self.slave_req_handler {
helper.add_event(backend_req_handler.as_raw_fd(), BACKEND_REQ_EVENT)?; helper.add_event(slave_req_handler.as_raw_fd(), SLAVE_REQ_EVENT)?;
} }
helper.run(paused, paused_sync, self)?; helper.run(paused, paused_sync, self)?;
@@ -231,7 +231,7 @@ impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
&self.virtio_interrupt, &self.virtio_interrupt,
self.acked_features, self.acked_features,
self.acked_protocol_features, self.acked_protocol_features,
&self.backend_req_handler, &self.slave_req_handler,
self.inflight.as_mut(), self.inflight.as_mut(),
) )
.map_err(|e| { .map_err(|e| {
@@ -255,7 +255,7 @@ impl<S: VhostUserFrontendReqHandler> VhostUserEpollHandler<S> {
} }
} }
impl<S: VhostUserFrontendReqHandler> EpollHelperHandler for VhostUserEpollHandler<S> { impl<S: VhostUserMasterReqHandler> EpollHelperHandler for VhostUserEpollHandler<S> {
fn handle_event( fn handle_event(
&mut self, &mut self,
helper: &mut EpollHelper, helper: &mut EpollHelper,
@@ -271,9 +271,9 @@ impl<S: VhostUserFrontendReqHandler> EpollHelperHandler for VhostUserEpollHandle
)) ))
})?; })?;
} }
BACKEND_REQ_EVENT => { SLAVE_REQ_EVENT => {
if let Some(backend_req_handler) = self.backend_req_handler.as_mut() { if let Some(slave_req_handler) = self.slave_req_handler.as_mut() {
backend_req_handler.handle_request().map_err(|e| { slave_req_handler.handle_request().map_err(|e| {
EpollHelperError::HandleEvent(anyhow!( EpollHelperError::HandleEvent(anyhow!(
"Failed to handle request from vhost-user backend: {:?}", "Failed to handle request from vhost-user backend: {:?}",
e e
@@ -304,13 +304,13 @@ pub struct VhostUserCommon {
impl VhostUserCommon { impl VhostUserCommon {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn activate<T: VhostUserFrontendReqHandler>( pub fn activate<T: VhostUserMasterReqHandler>(
&mut self, &mut self,
mem: GuestMemoryAtomic<GuestMemoryMmap>, mem: GuestMemoryAtomic<GuestMemoryMmap>,
queues: Vec<(usize, Queue, EventFd)>, queues: Vec<(usize, Queue, EventFd)>,
interrupt_cb: Arc<dyn VirtioInterrupt>, interrupt_cb: Arc<dyn VirtioInterrupt>,
acked_features: u64, acked_features: u64,
backend_req_handler: Option<FrontendReqHandler<T>>, slave_req_handler: Option<MasterReqHandler<T>>,
kill_evt: EventFd, kill_evt: EventFd,
pause_evt: EventFd, pause_evt: EventFd,
) -> std::result::Result<VhostUserEpollHandler<T>, ActivateError> { ) -> std::result::Result<VhostUserEpollHandler<T>, ActivateError> {
@@ -337,7 +337,7 @@ impl VhostUserCommon {
.collect(), .collect(),
&interrupt_cb, &interrupt_cb,
acked_features, acked_features,
&backend_req_handler, &slave_req_handler,
inflight.as_mut(), inflight.as_mut(),
) )
.map_err(ActivateError::VhostUserSetup)?; .map_err(ActivateError::VhostUserSetup)?;
@@ -353,7 +353,7 @@ impl VhostUserCommon {
acked_protocol_features: self.acked_protocol_features, acked_protocol_features: self.acked_protocol_features,
socket_path: self.socket_path.clone(), socket_path: self.socket_path.clone(),
server: self.server, server: self.server,
backend_req_handler, slave_req_handler,
inflight, inflight,
}) })
} }

View File

@@ -20,7 +20,7 @@ use std::vec::Vec;
use versionize::{VersionMap, Versionize, VersionizeResult}; use versionize::{VersionMap, Versionize, VersionizeResult};
use versionize_derive::Versionize; use versionize_derive::Versionize;
use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures}; use vhost::vhost_user::message::{VhostUserProtocolFeatures, VhostUserVirtioFeatures};
use vhost::vhost_user::{FrontendReqHandler, VhostUserFrontend, VhostUserFrontendReqHandler}; use vhost::vhost_user::{MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler};
use virtio_bindings::virtio_net::{ use virtio_bindings::virtio_net::{
VIRTIO_NET_F_CSUM, VIRTIO_NET_F_CTRL_VQ, VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GUEST_ECN, VIRTIO_NET_F_CSUM, VIRTIO_NET_F_CTRL_VQ, VIRTIO_NET_F_GUEST_CSUM, VIRTIO_NET_F_GUEST_ECN,
VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_UFO, VIRTIO_NET_F_GUEST_TSO4, VIRTIO_NET_F_GUEST_TSO6, VIRTIO_NET_F_GUEST_UFO,
@@ -49,8 +49,8 @@ pub struct State {
impl VersionMapped for State {} impl VersionMapped for State {}
struct BackendReqHandler {} struct SlaveReqHandler {}
impl VhostUserFrontendReqHandler for BackendReqHandler {} impl VhostUserMasterReqHandler for SlaveReqHandler {}
pub struct Net { pub struct Net {
common: VirtioCommon, common: VirtioCommon,
@@ -342,7 +342,7 @@ impl VirtioDevice for Net {
self.ctrl_queue_epoll_thread = Some(epoll_threads.remove(0)); self.ctrl_queue_epoll_thread = Some(epoll_threads.remove(0));
} }
let backend_req_handler: Option<FrontendReqHandler<BackendReqHandler>> = None; let slave_req_handler: Option<MasterReqHandler<SlaveReqHandler>> = None;
// The backend acknowledged features must not contain VIRTIO_NET_F_MAC // The backend acknowledged features must not contain VIRTIO_NET_F_MAC
// since we don't expect the backend to handle it. // since we don't expect the backend to handle it.
@@ -357,7 +357,7 @@ impl VirtioDevice for Net {
queues, queues,
interrupt_cb, interrupt_cb,
backend_acked_features, backend_acked_features,
backend_req_handler, slave_req_handler,
kill_evt, kill_evt,
pause_evt, pause_evt,
)?; )?;

View File

@@ -20,9 +20,7 @@ use vhost::vhost_kern::vhost_binding::{VHOST_F_LOG_ALL, VHOST_VRING_F_LOG};
use vhost::vhost_user::message::{ use vhost::vhost_user::message::{
VhostUserHeaderFlag, VhostUserInflight, VhostUserProtocolFeatures, VhostUserVirtioFeatures, VhostUserHeaderFlag, VhostUserInflight, VhostUserProtocolFeatures, VhostUserVirtioFeatures,
}; };
use vhost::vhost_user::{ use vhost::vhost_user::{Master, MasterReqHandler, VhostUserMaster, VhostUserMasterReqHandler};
Frontend, FrontendReqHandler, VhostUserFrontend, VhostUserFrontendReqHandler,
};
use vhost::{VhostBackend, VhostUserDirtyLogRegion, VhostUserMemoryRegionInfo, VringConfigData}; use vhost::{VhostBackend, VhostUserDirtyLogRegion, VhostUserMemoryRegionInfo, VringConfigData};
use virtio_queue::{Descriptor, Queue, QueueT}; use virtio_queue::{Descriptor, Queue, QueueT};
use vm_memory::{ use vm_memory::{
@@ -49,7 +47,7 @@ struct VringInfo {
#[derive(Clone)] #[derive(Clone)]
pub struct VhostUserHandle { pub struct VhostUserHandle {
vu: Frontend, vu: Master,
ready: bool, ready: bool,
supports_migration: bool, supports_migration: bool,
shm_log: Option<Arc<MmapRegion>>, shm_log: Option<Arc<MmapRegion>>,
@@ -150,13 +148,13 @@ impl VhostUserHandle {
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn setup_vhost_user<S: VhostUserFrontendReqHandler>( pub fn setup_vhost_user<S: VhostUserMasterReqHandler>(
&mut self, &mut self,
mem: &GuestMemoryMmap, mem: &GuestMemoryMmap,
queues: Vec<(usize, Queue, EventFd)>, queues: Vec<(usize, Queue, EventFd)>,
virtio_interrupt: &Arc<dyn VirtioInterrupt>, virtio_interrupt: &Arc<dyn VirtioInterrupt>,
acked_features: u64, acked_features: u64,
backend_req_handler: &Option<FrontendReqHandler<S>>, slave_req_handler: &Option<MasterReqHandler<S>>,
inflight: Option<&mut Inflight>, inflight: Option<&mut Inflight>,
) -> Result<()> { ) -> Result<()> {
self.vu self.vu
@@ -268,10 +266,10 @@ impl VhostUserHandle {
self.enable_vhost_user_vrings(self.queue_indexes.clone(), true)?; self.enable_vhost_user_vrings(self.queue_indexes.clone(), true)?;
if let Some(backend_req_handler) = backend_req_handler { if let Some(slave_req_handler) = slave_req_handler {
self.vu self.vu
.set_backend_request_fd(&backend_req_handler.get_tx_raw_fd()) .set_slave_request_fd(&slave_req_handler.get_tx_raw_fd())
.map_err(Error::VhostUserSetBackendRequestFd)?; .map_err(Error::VhostUserSetSlaveRequestFd)?;
} }
self.vrings_info = Some(vrings_info); self.vrings_info = Some(vrings_info);
@@ -335,14 +333,14 @@ impl VhostUserHandle {
} }
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn reinitialize_vhost_user<S: VhostUserFrontendReqHandler>( pub fn reinitialize_vhost_user<S: VhostUserMasterReqHandler>(
&mut self, &mut self,
mem: &GuestMemoryMmap, mem: &GuestMemoryMmap,
queues: Vec<(usize, Queue, EventFd)>, queues: Vec<(usize, Queue, EventFd)>,
virtio_interrupt: &Arc<dyn VirtioInterrupt>, virtio_interrupt: &Arc<dyn VirtioInterrupt>,
acked_features: u64, acked_features: u64,
acked_protocol_features: u64, acked_protocol_features: u64,
backend_req_handler: &Option<FrontendReqHandler<S>>, slave_req_handler: &Option<MasterReqHandler<S>>,
inflight: Option<&mut Inflight>, inflight: Option<&mut Inflight>,
) -> Result<()> { ) -> Result<()> {
self.set_protocol_features_vhost_user(acked_features, acked_protocol_features)?; self.set_protocol_features_vhost_user(acked_features, acked_protocol_features)?;
@@ -352,7 +350,7 @@ impl VhostUserHandle {
queues, queues,
virtio_interrupt, virtio_interrupt,
acked_features, acked_features,
backend_req_handler, slave_req_handler,
inflight, inflight,
) )
} }
@@ -374,7 +372,7 @@ impl VhostUserHandle {
let (stream, _) = listener.accept().map_err(Error::AcceptConnection)?; let (stream, _) = listener.accept().map_err(Error::AcceptConnection)?;
Ok(VhostUserHandle { Ok(VhostUserHandle {
vu: Frontend::from_stream(stream, num_queues), vu: Master::from_stream(stream, num_queues),
ready: false, ready: false,
supports_migration: false, supports_migration: false,
shm_log: None, shm_log: None,
@@ -387,7 +385,7 @@ impl VhostUserHandle {
// Retry connecting for a full minute // Retry connecting for a full minute
let err = loop { let err = loop {
let err = match Frontend::connect(socket_path, num_queues) { let err = match Master::connect(socket_path, num_queues) {
Ok(m) => { Ok(m) => {
return Ok(VhostUserHandle { return Ok(VhostUserHandle {
vu: m, vu: m,
@@ -416,7 +414,7 @@ impl VhostUserHandle {
} }
} }
pub fn socket_handle(&mut self) -> &mut Frontend { pub fn socket_handle(&mut self) -> &mut Master {
&mut self.vu &mut self.vu
} }

View File

@@ -340,7 +340,7 @@ where
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
pub fn new( pub fn new(
id: String, id: String,
cid: u32, cid: u64,
path: PathBuf, path: PathBuf,
backend: B, backend: B,
iommu: bool, iommu: bool,
@@ -372,7 +372,7 @@ where
..Default::default() ..Default::default()
}, },
id, id,
cid: cid.into(), cid,
backend: Arc::new(RwLock::new(backend)), backend: Arc::new(RwLock::new(backend)),
path, path,
seccomp_action, seccomp_action,

View File

@@ -17,7 +17,7 @@ pub use self::device::Vsock;
pub use self::unix::VsockUnixBackend; pub use self::unix::VsockUnixBackend;
pub use self::unix::VsockUnixError; pub use self::unix::VsockUnixError;
use packet::VsockPacket; pub use packet::VsockPacket;
use std::os::unix::io::RawFd; use std::os::unix::io::RawFd;
mod defs { mod defs {
@@ -262,10 +262,10 @@ mod tests {
impl TestContext { impl TestContext {
pub fn new() -> Self { pub fn new() -> Self {
const CID: u32 = 52; const CID: u64 = 52;
const MEM_SIZE: usize = 1024 * 1024 * 128; const MEM_SIZE: usize = 1024 * 1024 * 128;
Self { Self {
cid: CID as u64, cid: CID,
mem: GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap(), mem: GuestMemoryMmap::from_ranges(&[(GuestAddress(0), MEM_SIZE)]).unwrap(),
mem_size: MEM_SIZE, mem_size: MEM_SIZE,
device: Vsock::new( device: Vsock::new(

View File

@@ -40,7 +40,7 @@
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::fs::File; use std::fs::File;
use std::io::{self, ErrorKind, Read}; use std::io::{self, Read};
use std::os::unix::io::{AsRawFd, FromRawFd, RawFd}; use std::os::unix::io::{AsRawFd, FromRawFd, RawFd};
use std::os::unix::net::{UnixListener, UnixStream}; use std::os::unix::net::{UnixListener, UnixStream};
@@ -92,15 +92,6 @@ enum EpollListener {
LocalStream(UnixStream), LocalStream(UnixStream),
} }
/// A partially read "CONNECT" command.
#[derive(Default)]
struct PartiallyReadCommand {
/// The bytes of the command that have been read so far.
buf: [u8; 32],
/// How much of `buf` has been used.
len: usize,
}
/// The vsock connection multiplexer. /// The vsock connection multiplexer.
/// ///
pub struct VsockMuxer { pub struct VsockMuxer {
@@ -110,8 +101,6 @@ pub struct VsockMuxer {
conn_map: HashMap<ConnMapKey, MuxerConnection>, conn_map: HashMap<ConnMapKey, MuxerConnection>,
/// A hash map used to store epoll event listeners / handlers. /// A hash map used to store epoll event listeners / handlers.
listener_map: HashMap<RawFd, EpollListener>, listener_map: HashMap<RawFd, EpollListener>,
/// A hash map used to store partially read "connect" commands.
partial_command_map: HashMap<RawFd, PartiallyReadCommand>,
/// The RX queue. Items in this queue are consumed by `VsockMuxer::recv_pkt()`, and /// The RX queue. Items in this queue are consumed by `VsockMuxer::recv_pkt()`, and
/// produced /// produced
/// - by `VsockMuxer::send_pkt()` (e.g. RST in response to a connection request packet); /// - by `VsockMuxer::send_pkt()` (e.g. RST in response to a connection request packet);
@@ -347,7 +336,7 @@ impl VsockBackend for VsockMuxer {}
impl VsockMuxer { impl VsockMuxer {
/// Muxer constructor. /// Muxer constructor.
/// ///
pub fn new(cid: u32, host_sock_path: String) -> Result<Self> { pub fn new(cid: u64, host_sock_path: String) -> Result<Self> {
// Create the nested epoll FD. This FD will be added to the VMM `EpollContext`, at // Create the nested epoll FD. This FD will be added to the VMM `EpollContext`, at
// device activation time. // device activation time.
let epoll_fd = epoll::create(true).map_err(Error::EpollFdCreate)?; let epoll_fd = epoll::create(true).map_err(Error::EpollFdCreate)?;
@@ -362,14 +351,13 @@ impl VsockMuxer {
.map_err(Error::UnixBind)?; .map_err(Error::UnixBind)?;
let mut muxer = Self { let mut muxer = Self {
cid: cid.into(), cid,
host_sock, host_sock,
host_sock_path, host_sock_path,
epoll_file, epoll_file,
rxq: MuxerRxQ::new(), rxq: MuxerRxQ::new(),
conn_map: HashMap::with_capacity(defs::MAX_CONNECTIONS), conn_map: HashMap::with_capacity(defs::MAX_CONNECTIONS),
listener_map: HashMap::with_capacity(defs::MAX_CONNECTIONS + 1), listener_map: HashMap::with_capacity(defs::MAX_CONNECTIONS + 1),
partial_command_map: Default::default(),
killq: MuxerKillQ::new(), killq: MuxerKillQ::new(),
local_port_last: (1u32 << 30) - 1, local_port_last: (1u32 << 30) - 1,
local_port_set: HashSet::with_capacity(defs::MAX_CONNECTIONS), local_port_set: HashSet::with_capacity(defs::MAX_CONNECTIONS),
@@ -436,40 +424,27 @@ impl VsockMuxer {
// Data is ready to be read from a host-initiated connection. That would be the // Data is ready to be read from a host-initiated connection. That would be the
// "connect" command that we're expecting. // "connect" command that we're expecting.
Some(EpollListener::LocalStream(_)) => { Some(EpollListener::LocalStream(_)) => {
if let Some(EpollListener::LocalStream(stream)) = self.listener_map.get_mut(&fd) { if let Some(EpollListener::LocalStream(mut stream)) = self.remove_listener(fd) {
let port = Self::read_local_stream_port(&mut self.partial_command_map, stream); Self::read_local_stream_port(&mut stream)
.map(|peer_port| (self.allocate_local_port(), peer_port))
if let Err(Error::UnixRead(ref e)) = port { .and_then(|(local_port, peer_port)| {
if e.kind() == ErrorKind::WouldBlock { self.add_connection(
return; ConnMapKey {
} local_port,
} peer_port,
},
let stream = match self.remove_listener(fd) { MuxerConnection::new_local_init(
Some(EpollListener::LocalStream(s)) => s, stream,
_ => unreachable!(), uapi::VSOCK_HOST_CID,
}; self.cid,
local_port,
port.and_then(|peer_port| { peer_port,
let local_port = self.allocate_local_port(); ),
)
self.add_connection( })
ConnMapKey { .unwrap_or_else(|err| {
local_port, info!("vsock: error adding local-init connection: {:?}", err);
peer_port, })
},
MuxerConnection::new_local_init(
stream,
uapi::VSOCK_HOST_CID,
self.cid,
local_port,
peer_port,
),
)
})
.unwrap_or_else(|err| {
info!("vsock: error adding local-init connection: {:?}", err);
})
} }
} }
@@ -484,36 +459,30 @@ impl VsockMuxer {
/// Parse a host "connect" command, and extract the destination vsock port. /// Parse a host "connect" command, and extract the destination vsock port.
/// ///
fn read_local_stream_port( fn read_local_stream_port(stream: &mut UnixStream) -> Result<u32> {
partial_command_map: &mut HashMap<RawFd, PartiallyReadCommand>, let mut buf = [0u8; 32];
stream: &mut UnixStream,
) -> Result<u32> {
let command = partial_command_map.entry(stream.as_raw_fd()).or_default();
// This is the minimum number of bytes that we should be able to read, when parsing a // This is the minimum number of bytes that we should be able to read, when parsing a
// valid connection request. I.e. `b"connect 0\n".len()`. // valid connection request. I.e. `b"connect 0\n".len()`.
const MIN_COMMAND_LEN: usize = 10; const MIN_READ_LEN: usize = 10;
// Bring in the minimum number of bytes that we should be able to read. // Bring in the minimum number of bytes that we should be able to read.
if command.len < MIN_COMMAND_LEN { stream
command.len += stream .read_exact(&mut buf[..MIN_READ_LEN])
.read(&mut command.buf[command.len..MIN_COMMAND_LEN]) .map_err(Error::UnixRead)?;
.map_err(Error::UnixRead)?;
}
// Now, finish reading the destination port number, by bringing in one byte at a time, // Now, finish reading the destination port number, by bringing in one byte at a time,
// until we reach an EOL terminator (or our buffer space runs out). Yeah, not // until we reach an EOL terminator (or our buffer space runs out). Yeah, not
// particularly proud of this approach, but it will have to do for now. // particularly proud of this approach, but it will have to do for now.
while command.buf[command.len - 1] != b'\n' && command.len < command.buf.len() { let mut blen = MIN_READ_LEN;
command.len += stream while buf[blen - 1] != b'\n' && blen < buf.len() {
.read(&mut command.buf[command.len..=command.len]) stream
.read_exact(&mut buf[blen..=blen])
.map_err(Error::UnixRead)?; .map_err(Error::UnixRead)?;
blen += 1;
} }
let _ = command; let mut word_iter = std::str::from_utf8(&buf[..blen])
let command = partial_command_map.remove(&stream.as_raw_fd()).unwrap();
let mut word_iter = std::str::from_utf8(&command.buf[..command.len])
.map_err(Error::ConvertFromUtf8)? .map_err(Error::ConvertFromUtf8)?
.split_whitespace(); .split_whitespace();
@@ -862,7 +831,7 @@ mod tests {
use super::super::super::tests::TestContext as VsockTestContext; use super::super::super::tests::TestContext as VsockTestContext;
use super::*; use super::*;
const PEER_CID: u32 = 3; const PEER_CID: u64 = 3;
const PEER_BUF_ALLOC: u32 = 64 * 1024; const PEER_BUF_ALLOC: u32 = 64 * 1024;
struct MuxerTestContext { struct MuxerTestContext {
@@ -906,7 +875,7 @@ mod tests {
} }
self.pkt self.pkt
.set_type(uapi::VSOCK_TYPE_STREAM) .set_type(uapi::VSOCK_TYPE_STREAM)
.set_src_cid(PEER_CID.into()) .set_src_cid(PEER_CID)
.set_dst_cid(uapi::VSOCK_HOST_CID) .set_dst_cid(uapi::VSOCK_HOST_CID)
.set_src_port(peer_port) .set_src_port(peer_port)
.set_dst_port(local_port) .set_dst_port(local_port)
@@ -1060,7 +1029,7 @@ mod tests {
ctx.recv(); ctx.recv();
assert_eq!(ctx.pkt.op(), uapi::VSOCK_OP_RST); assert_eq!(ctx.pkt.op(), uapi::VSOCK_OP_RST);
assert_eq!(ctx.pkt.src_cid(), uapi::VSOCK_HOST_CID); assert_eq!(ctx.pkt.src_cid(), uapi::VSOCK_HOST_CID);
assert_eq!(ctx.pkt.dst_cid(), PEER_CID as u64); assert_eq!(ctx.pkt.dst_cid(), PEER_CID);
assert_eq!(ctx.pkt.src_port(), LOCAL_PORT); assert_eq!(ctx.pkt.src_port(), LOCAL_PORT);
assert_eq!(ctx.pkt.dst_port(), PEER_PORT); assert_eq!(ctx.pkt.dst_port(), PEER_PORT);
@@ -1105,7 +1074,7 @@ mod tests {
assert_eq!(ctx.pkt.op(), uapi::VSOCK_OP_RST); assert_eq!(ctx.pkt.op(), uapi::VSOCK_OP_RST);
assert_eq!(ctx.pkt.len(), 0); assert_eq!(ctx.pkt.len(), 0);
assert_eq!(ctx.pkt.src_cid(), uapi::VSOCK_HOST_CID); assert_eq!(ctx.pkt.src_cid(), uapi::VSOCK_HOST_CID);
assert_eq!(ctx.pkt.dst_cid(), PEER_CID as u64); assert_eq!(ctx.pkt.dst_cid(), PEER_CID);
assert_eq!(ctx.pkt.src_port(), LOCAL_PORT); assert_eq!(ctx.pkt.src_port(), LOCAL_PORT);
assert_eq!(ctx.pkt.dst_port(), PEER_PORT); assert_eq!(ctx.pkt.dst_port(), PEER_PORT);
@@ -1119,7 +1088,7 @@ mod tests {
assert_eq!(ctx.pkt.op(), uapi::VSOCK_OP_RESPONSE); assert_eq!(ctx.pkt.op(), uapi::VSOCK_OP_RESPONSE);
assert_eq!(ctx.pkt.len(), 0); assert_eq!(ctx.pkt.len(), 0);
assert_eq!(ctx.pkt.src_cid(), uapi::VSOCK_HOST_CID); assert_eq!(ctx.pkt.src_cid(), uapi::VSOCK_HOST_CID);
assert_eq!(ctx.pkt.dst_cid(), PEER_CID as u64); assert_eq!(ctx.pkt.dst_cid(), PEER_CID);
assert_eq!(ctx.pkt.src_port(), LOCAL_PORT); assert_eq!(ctx.pkt.src_port(), LOCAL_PORT);
assert_eq!(ctx.pkt.dst_port(), PEER_PORT); assert_eq!(ctx.pkt.dst_port(), PEER_PORT);
let key = ConnMapKey { let key = ConnMapKey {

View File

@@ -6,7 +6,7 @@ edition = "2021"
[dependencies] [dependencies]
libc = "0.2.147" libc = "0.2.147"
vm-memory = "0.14.0" vm-memory = "0.12.2"
[target.'cfg(target_arch = "aarch64")'.dependencies] [target.'cfg(target_arch = "aarch64")'.dependencies]
arch = { path = "../arch" } arch = { path = "../arch" }

View File

@@ -30,6 +30,7 @@ use crate::page_size::get_page_size;
/// #[cfg(target_arch = "x86_64")] GuestAddress(0x1000), /// #[cfg(target_arch = "x86_64")] GuestAddress(0x1000),
/// #[cfg(target_arch = "x86_64")] 0x10000, /// #[cfg(target_arch = "x86_64")] 0x10000,
/// GuestAddress(0x10000000), 0x10000000, /// GuestAddress(0x10000000), 0x10000000,
/// GuestAddress(0x20000000), 0x100000,
/// #[cfg(target_arch = "x86_64")] vec![GsiApic::new(5, 19)]).unwrap(); /// #[cfg(target_arch = "x86_64")] vec![GsiApic::new(5, 19)]).unwrap();
/// #[cfg(target_arch = "x86_64")] /// #[cfg(target_arch = "x86_64")]
/// assert_eq!(allocator.allocate_irq(), Some(5)); /// assert_eq!(allocator.allocate_irq(), Some(5));
@@ -46,6 +47,7 @@ pub struct SystemAllocator {
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
io_address_space: AddressAllocator, io_address_space: AddressAllocator,
platform_mmio_address_space: AddressAllocator, platform_mmio_address_space: AddressAllocator,
mmio_hole_address_space: AddressAllocator,
gsi_allocator: GsiAllocator, gsi_allocator: GsiAllocator,
} }
@@ -57,6 +59,8 @@ impl SystemAllocator {
/// * `io_size` - (X86) The size of IO memory. /// * `io_size` - (X86) The size of IO memory.
/// * `platform_mmio_base` - The starting address of platform MMIO memory. /// * `platform_mmio_base` - The starting address of platform MMIO memory.
/// * `platform_mmio_size` - The size of platform MMIO memory. /// * `platform_mmio_size` - The size of platform MMIO memory.
/// * `mmio_hole_base` - The starting address of MMIO memory in 32-bit address space.
/// * `mmio_hole_size` - The size of MMIO memory in 32-bit address space.
/// * `apics` - (X86) Vector of APIC's. /// * `apics` - (X86) Vector of APIC's.
/// ///
pub fn new( pub fn new(
@@ -64,6 +68,8 @@ impl SystemAllocator {
#[cfg(target_arch = "x86_64")] io_size: GuestUsize, #[cfg(target_arch = "x86_64")] io_size: GuestUsize,
platform_mmio_base: GuestAddress, platform_mmio_base: GuestAddress,
platform_mmio_size: GuestUsize, platform_mmio_size: GuestUsize,
mmio_hole_base: GuestAddress,
mmio_hole_size: GuestUsize,
#[cfg(target_arch = "x86_64")] apics: Vec<GsiApic>, #[cfg(target_arch = "x86_64")] apics: Vec<GsiApic>,
) -> Option<Self> { ) -> Option<Self> {
Some(SystemAllocator { Some(SystemAllocator {
@@ -73,6 +79,7 @@ impl SystemAllocator {
platform_mmio_base, platform_mmio_base,
platform_mmio_size, platform_mmio_size,
)?, )?,
mmio_hole_address_space: AddressAllocator::new(mmio_hole_base, mmio_hole_size)?,
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
gsi_allocator: GsiAllocator::new(apics), gsi_allocator: GsiAllocator::new(apics),
#[cfg(target_arch = "aarch64")] #[cfg(target_arch = "aarch64")]
@@ -116,6 +123,20 @@ impl SystemAllocator {
) )
} }
/// Reserves a section of `size` bytes of MMIO address space.
pub fn allocate_mmio_hole_addresses(
&mut self,
address: Option<GuestAddress>,
size: GuestUsize,
align_size: Option<GuestUsize>,
) -> Option<GuestAddress> {
self.mmio_hole_address_space.allocate(
address,
size,
Some(align_size.unwrap_or_else(get_page_size)),
)
}
#[cfg(target_arch = "x86_64")] #[cfg(target_arch = "x86_64")]
/// Free an IO address range. /// Free an IO address range.
/// We can only free a range if it matches exactly an already allocated range. /// We can only free a range if it matches exactly an already allocated range.
@@ -128,4 +149,10 @@ impl SystemAllocator {
pub fn free_platform_mmio_addresses(&mut self, address: GuestAddress, size: GuestUsize) { pub fn free_platform_mmio_addresses(&mut self, address: GuestAddress, size: GuestUsize) {
self.platform_mmio_address_space.free(address, size) self.platform_mmio_address_space.free(address, size)
} }
/// Free an MMIO address range from the 32 bits hole.
/// We can only free a range if it matches exactly an already allocated range.
pub fn free_mmio_hole_addresses(&mut self, address: GuestAddress, size: GuestUsize) {
self.mmio_hole_address_space.free(address, size)
}
} }

View File

@@ -15,5 +15,6 @@ hypervisor = { path = "../hypervisor" }
thiserror = "1.0.40" thiserror = "1.0.40"
serde = { version = "1.0.168", features = ["rc", "derive"] } serde = { version = "1.0.168", features = ["rc", "derive"] }
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false } vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false }
vm-memory = { version = "0.14.0", features = ["backend-mmap"] } vm-memory = { version = "0.12.2", features = ["backend-mmap"] }
vmm-sys-util = "0.12.1" vmm-sys-util = "0.11.0"

View File

@@ -8,7 +8,7 @@ edition = "2021"
anyhow = "1.0.75" anyhow = "1.0.75"
thiserror = "1.0.40" thiserror = "1.0.40"
serde = { version = "1.0.168", features = ["rc", "derive"] } serde = { version = "1.0.168", features = ["rc", "derive"] }
serde_json = "1.0.109" serde_json = "1.0.107"
versionize = "0.2.0" versionize = "0.1.10"
versionize_derive = "0.1.6" versionize_derive = "0.1.4"
vm-memory = { version = "0.14.0", features = ["backend-mmap", "backend-atomic"] } vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic"] }

View File

@@ -12,7 +12,7 @@ use versionize::{VersionMap, Versionize};
pub mod protocol; pub mod protocol;
/// Global VMM version for versioning /// Global VMM version for versioning
const MAJOR_VERSION: u16 = 37; const MAJOR_VERSION: u16 = 36;
const MINOR_VERSION: u16 = 1; const MINOR_VERSION: u16 = 1;
const VMM_VERSION: u16 = MAJOR_VERSION << 12 | MINOR_VERSION & 0b1111; const VMM_VERSION: u16 = MAJOR_VERSION << 12 | MINOR_VERSION & 0b1111;

View File

@@ -8,6 +8,6 @@ edition = "2021"
default = [] default = []
[dependencies] [dependencies]
log = "0.4.20" log = "0.4.17"
virtio-queue = "0.11.0" virtio-queue = "0.9.0"
vm-memory = { version = "0.14.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] } vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }

View File

@@ -8,7 +8,6 @@ edition = "2021"
default = [] default = []
dbus_api = ["blocking", "futures", "zbus"] dbus_api = ["blocking", "futures", "zbus"]
guest_debug = ["kvm", "gdbstub", "gdbstub_arch"] guest_debug = ["kvm", "gdbstub", "gdbstub_arch"]
igvm = ["hex", "igvm_parser", "igvm_defs", "mshv-bindings", "range_map_vec"]
io_uring = ["block/io_uring"] io_uring = ["block/io_uring"]
kvm = ["hypervisor/kvm", "vfio-ioctls/kvm", "vm-device/kvm", "pci/kvm"] kvm = ["hypervisor/kvm", "vfio-ioctls/kvm", "vm-device/kvm", "pci/kvm"]
mshv = ["hypervisor/mshv", "vfio-ioctls/mshv", "vm-device/mshv", "pci/mshv"] mshv = ["hypervisor/mshv", "vfio-ioctls/mshv", "vm-device/mshv", "pci/mshv"]
@@ -25,28 +24,23 @@ bitflags = "2.4.1"
block = { path = "../block" } block = { path = "../block" }
blocking = { version = "1.3.0", optional = true } blocking = { version = "1.3.0", optional = true }
cfg-if = "1.0.0" cfg-if = "1.0.0"
clap = "4.4.7" clap = "4.3.11"
devices = { path = "../devices" } devices = { path = "../devices" }
epoll = "4.3.3" epoll = "4.3.3"
event_monitor = { path = "../event_monitor" } event_monitor = { path = "../event_monitor" }
flume = "0.10.14" flume = "0.10.14"
futures = { version = "0.3.27", optional = true } futures = { version = "0.3.27", optional = true }
gdbstub = { version = "0.7.0", optional = true } gdbstub = { version = "0.6.4", optional = true }
gdbstub_arch = { version = "0.3.0", optional = true } gdbstub_arch = { version = "0.2.4", optional = true }
hex = { version = "0.4.3", optional = true }
hypervisor = { path = "../hypervisor" } hypervisor = { path = "../hypervisor" }
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.147" libc = "0.2.147"
linux-loader = { version = "0.11.0", features = ["elf", "bzimage", "pe"] } linux-loader = { version = "0.9.1", features = ["elf", "bzimage", "pe"] }
log = "0.4.20" log = "0.4.17"
micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" } micro_http = { git = "https://github.com/firecracker-microvm/micro-http", branch = "main" }
mshv-bindings = { git = "https://github.com/rust-vmm/mshv", branch = "main", features = ["with-serde", "fam-wrappers"], optional = true }
net_util = { path = "../net_util" } net_util = { path = "../net_util" }
once_cell = "1.18.0" once_cell = "1.18.0"
option_parser = { path = "../option_parser" } option_parser = { path = "../option_parser" }
pci = { path = "../pci" } pci = { path = "../pci" }
range_map_vec = { version = "0.1.0", optional = true }
seccompiler = "0.4.0" seccompiler = "0.4.0"
serde = { version = "1.0.168", features = ["rc", "derive"] } serde = { version = "1.0.168", features = ["rc", "derive"] }
serde_json = "1.0.107" serde_json = "1.0.107"
@@ -55,17 +49,17 @@ signal-hook = "0.3.17"
thiserror = "1.0.40" thiserror = "1.0.40"
tracer = { path = "../tracer" } tracer = { path = "../tracer" }
uuid = "1.3.4" uuid = "1.3.4"
versionize = "0.2.0" versionize = "0.1.10"
versionize_derive = "0.1.6" versionize_derive = "0.1.4"
vfio-ioctls = { git = "https://github.com/rust-vmm/vfio", branch = "main", default-features = false } 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" } vfio_user = { git = "https://github.com/rust-vmm/vfio-user", branch = "main" }
virtio-devices = { path = "../virtio-devices" } virtio-devices = { path = "../virtio-devices" }
virtio-queue = "0.11.0" virtio-queue = "0.9.0"
vm-allocator = { path = "../vm-allocator" } vm-allocator = { path = "../vm-allocator" }
vm-device = { path = "../vm-device" } vm-device = { path = "../vm-device" }
vm-memory = { version = "0.14.0", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] } vm-memory = { version = "0.12.2", features = ["backend-mmap", "backend-atomic", "backend-bitmap"] }
vm-migration = { path = "../vm-migration" } vm-migration = { path = "../vm-migration" }
vm-virtio = { path = "../vm-virtio" } vm-virtio = { path = "../vm-virtio" }
vmm-sys-util = { version = "0.12.1", features = ["with-serde"] } vmm-sys-util = { version = "0.11.0", features = ["with-serde"] }
zbus = { version = "3.11.1", optional = true } zbus = { version = "3.11.1", optional = true }
zerocopy = { version = "0.7.21", features = ["alloc","derive"] } zerocopy = { version = "0.7.21", features = ["derive"] }

View File

@@ -277,10 +277,7 @@ fn create_tpm2_table() -> Sdt {
tpm tpm
} }
fn create_srat_table( fn create_srat_table(numa_nodes: &NumaNodes) -> Sdt {
numa_nodes: &NumaNodes,
#[cfg(target_arch = "x86_64")] topology: Option<(u8, u8, u8)>,
) -> Sdt {
let mut srat = Sdt::new(*b"SRAT", 36, 3, *b"CLOUDH", *b"CHSRAT ", 1); let mut srat = Sdt::new(*b"SRAT", 36, 3, *b"CLOUDH", *b"CHSRAT ", 1);
// SRAT reserved 12 bytes // SRAT reserved 12 bytes
srat.append_slice(&[0u8; 12]); srat.append_slice(&[0u8; 12]);
@@ -319,9 +316,6 @@ fn create_srat_table(
} }
for cpu in &node.cpus { for cpu in &node.cpus {
#[cfg(target_arch = "x86_64")]
let x2apic_id = arch::x86_64::get_x2apic_id(*cpu as u32, topology);
#[cfg(target_arch = "aarch64")]
let x2apic_id = *cpu as u32; let x2apic_id = *cpu as u32;
// Flags // Flags
@@ -758,14 +752,8 @@ pub fn create_acpi_tables(
// SRAT and SLIT // SRAT and SLIT
// Only created if the NUMA nodes list is not empty. // Only created if the NUMA nodes list is not empty.
if !numa_nodes.is_empty() { if !numa_nodes.is_empty() {
#[cfg(target_arch = "x86_64")]
let topology = cpu_manager.lock().unwrap().get_vcpu_topology();
// SRAT // SRAT
let srat = create_srat_table( let srat = create_srat_table(numa_nodes);
numa_nodes,
#[cfg(target_arch = "x86_64")]
topology,
);
let srat_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap(); let srat_offset = prev_tbl_off.checked_add(prev_tbl_len).unwrap();
guest_mem guest_mem
.write_slice(srat.as_slice(), srat_offset) .write_slice(srat.as_slice(), srat_offset)
@@ -863,15 +851,8 @@ pub fn create_acpi_tables_tdx(
// SRAT and SLIT // SRAT and SLIT
// Only created if the NUMA nodes list is not empty. // Only created if the NUMA nodes list is not empty.
if !numa_nodes.is_empty() { if !numa_nodes.is_empty() {
#[cfg(target_arch = "x86_64")]
let topology = cpu_manager.lock().unwrap().get_vcpu_topology();
// SRAT // SRAT
tables.push(create_srat_table( tables.push(create_srat_table(numa_nodes));
numa_nodes,
#[cfg(target_arch = "x86_64")]
topology,
));
// SLIT // SLIT
tables.push(create_slit_table(numa_nodes)); tables.push(create_slit_table(numa_nodes));

Some files were not shown because too many files have changed in this diff Show More