mirror of
https://github.com/rust-vmm/vhost-device.git
synced 2026-01-03 15:58:37 +00:00
vhost-device-gpu: Add Initial Implementation
This program is a vhost-user backend daemon that provides VIRTIO GPU device emulation as specified in the VIRTIO Spec v.1.2 https://docs.oasis-open.org/virtio/virtio/v1.2/csd01/virtio-v1.2-csd01.html This crate utilizes the rutabaga crate from crosvm with some minor modification to rutabaga crate to fix compilation. This crate depends on this PR[rust-vmm/vhost#239] that implements support for QEMU's vhost-user-gpu protocol. This device uses the rutabaga_gfx crate to offer two rendering backends: 1. Virglrenderer: - Rutabaga translates OpenGL API and Vulkan calls to an intermediate representation and allows for OpenGL acceleration on the host. 2. Gfxstream: - GLES and Vulkan calls are forwarded to the host. These backends can be used by simply changing the `--gpu-mode` command line option. This crate also includes some modifications from libkrun virtio-gpu device https://github.com/containers/libkrun/tree/main/src/devices/src/virtio/gpu Fixes: rust-vmm#598 Co-authored-by: Dorinda Bassey <dbassey@redhat.com> Co-authored-by: Matej Hrica <mhrica@redhat.com> Signed-off-by: Dorinda Bassey <dbassey@redhat.com> Signed-off-by: Matej Hrica <mhrica@redhat.com>
This commit is contained in:
parent
b7321b7997
commit
391e32b82f
190
staging/Cargo.lock
generated
190
staging/Cargo.lock
generated
@ -108,6 +108,12 @@ version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "cfg_aliases"
|
||||
version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
|
||||
|
||||
[[package]]
|
||||
name = "clap"
|
||||
version = "4.5.21"
|
||||
@ -154,6 +160,12 @@ version = "1.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990"
|
||||
|
||||
[[package]]
|
||||
name = "downcast"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1435fa1053d8b2fbbe9be7e97eca7f33d37b28409959813daefc1446a14247f1"
|
||||
|
||||
[[package]]
|
||||
name = "enumn"
|
||||
version = "0.1.14"
|
||||
@ -220,6 +232,18 @@ version = "2.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "486f806e73c5707928240ddc295403b1b93c96a02038563881c4a2fd84b81ac4"
|
||||
|
||||
[[package]]
|
||||
name = "fnv"
|
||||
version = "1.0.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
|
||||
|
||||
[[package]]
|
||||
name = "fragile"
|
||||
version = "2.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c2141d6d6c8512188a7891b4b01590a45f6dac67afb4f255c4124dbb86d4eaa"
|
||||
|
||||
[[package]]
|
||||
name = "futures"
|
||||
version = "0.3.31"
|
||||
@ -397,6 +421,41 @@ version = "2.7.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3"
|
||||
|
||||
[[package]]
|
||||
name = "memoffset"
|
||||
version = "0.9.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mockall"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39a6bfcc6c8c7eed5ee98b9c3e33adc726054389233e201c95dab2d41a3839d2"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"downcast",
|
||||
"fragile",
|
||||
"mockall_derive",
|
||||
"predicates",
|
||||
"predicates-tree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mockall_derive"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "25ca3004c2efe9011bd4e461bd8256445052b9615405b4f7ea43fc8ca5c20898"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.27.1"
|
||||
@ -408,6 +467,19 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "nix"
|
||||
version = "0.28.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
|
||||
dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"cfg-if",
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
"memoffset",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num_cpus"
|
||||
version = "1.16.0"
|
||||
@ -457,6 +529,12 @@ version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184"
|
||||
|
||||
[[package]]
|
||||
name = "pkg-config"
|
||||
version = "0.3.31"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "953ec861398dccce10c670dfeaf3ec4911ca479e9c02154b3a215178c5f566f2"
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.20"
|
||||
@ -466,6 +544,32 @@ dependencies = [
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "predicates"
|
||||
version = "3.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7e9086cc7640c29a356d1a29fd134380bee9d8f79a17410aa76e7ad295f42c97"
|
||||
dependencies = [
|
||||
"anstyle",
|
||||
"predicates-core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "predicates-core"
|
||||
version = "1.0.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ae8177bee8e75d6846599c6b9ff679ed51e882816914eec639944d7c9aa11931"
|
||||
|
||||
[[package]]
|
||||
name = "predicates-tree"
|
||||
version = "1.0.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41b740d195ed3166cd147c8047ec98db0e22ec019eb8eeb76d343b795304fb13"
|
||||
dependencies = [
|
||||
"predicates-core",
|
||||
"termtree",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-crate"
|
||||
version = "3.2.0"
|
||||
@ -484,6 +588,12 @@ dependencies = [
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "quick-error"
|
||||
version = "1.2.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0"
|
||||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.37"
|
||||
@ -558,6 +668,17 @@ version = "1.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba39f3699c378cd8970968dcbff9c43159ea4cfbd88d43c00b22f2ef10a435d2"
|
||||
|
||||
[[package]]
|
||||
name = "remain"
|
||||
version = "0.2.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "46aef80f842736de545ada6ec65b81ee91504efd6853f4b96de7414c42ae7443"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rstest"
|
||||
version = "0.23.0"
|
||||
@ -610,6 +731,36 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rusty-fork"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb3dcc6e454c328bb824492db107ab7c0ae8fcffe4ad210136ef014458c1bc4f"
|
||||
dependencies = [
|
||||
"fnv",
|
||||
"quick-error",
|
||||
"tempfile",
|
||||
"wait-timeout",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rutabaga_gfx"
|
||||
version = "0.1.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6628c6391bc654170f64fe8bfb7e5da3bf97f7ed3174c52c7a7349c012adec9c"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"log",
|
||||
"nix 0.28.0",
|
||||
"pkg-config",
|
||||
"remain",
|
||||
"thiserror 1.0.69",
|
||||
"winapi",
|
||||
"zerocopy",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "semver"
|
||||
version = "1.0.23"
|
||||
@ -655,6 +806,12 @@ dependencies = [
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "termtree"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3369f5ac52d5eb6ab48c6b4ffdc8efbcad6b89c765749064ba298f2c68a16a76"
|
||||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.69"
|
||||
@ -755,7 +912,7 @@ dependencies = [
|
||||
"bitflags 2.6.0",
|
||||
"enumn",
|
||||
"log",
|
||||
"nix",
|
||||
"nix 0.27.1",
|
||||
"thiserror 1.0.69",
|
||||
]
|
||||
|
||||
@ -772,6 +929,28 @@ dependencies = [
|
||||
"vmm-sys-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vhost-device-gpu"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"assert_matches",
|
||||
"clap",
|
||||
"env_logger",
|
||||
"libc",
|
||||
"log",
|
||||
"mockall",
|
||||
"rusty-fork",
|
||||
"rutabaga_gfx",
|
||||
"tempfile",
|
||||
"thiserror 2.0.3",
|
||||
"vhost",
|
||||
"vhost-user-backend",
|
||||
"virtio-bindings",
|
||||
"virtio-queue",
|
||||
"vm-memory",
|
||||
"vmm-sys-util",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "vhost-device-video"
|
||||
version = "0.1.0"
|
||||
@ -854,6 +1033,15 @@ dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wait-timeout"
|
||||
version = "0.2.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
[workspace]
|
||||
resolver = "2"
|
||||
members = [
|
||||
"vhost-device-gpu",
|
||||
"vhost-device-video",
|
||||
]
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
{
|
||||
"coverage_score": 74.82,
|
||||
"coverage_score": 79.80,
|
||||
"exclude_path": "",
|
||||
"crate_features": ""
|
||||
}
|
||||
|
||||
10
staging/vhost-device-gpu/CHANGELOG.md
Normal file
10
staging/vhost-device-gpu/CHANGELOG.md
Normal file
@ -0,0 +1,10 @@
|
||||
# Changelog
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
### Changed
|
||||
|
||||
### Fixed
|
||||
|
||||
### Deprecated
|
||||
39
staging/vhost-device-gpu/Cargo.toml
Normal file
39
staging/vhost-device-gpu/Cargo.toml
Normal file
@ -0,0 +1,39 @@
|
||||
[package]
|
||||
name = "vhost-device-gpu"
|
||||
version = "0.1.0"
|
||||
authors = ["Dorinda Bassey <dbassey@redhat.com>", "Matej Hrica <mhrica@redhat.com>"]
|
||||
description = "A virtio-gpu device using the vhost-user protocol."
|
||||
repository = "https://github.com/rust-vmm/vhost-device"
|
||||
readme = "README.md"
|
||||
keywords = ["gpu", "vhost", "vhost-user", "virtio"]
|
||||
categories = ["multimedia::video", "virtualization"]
|
||||
license = "Apache-2.0 OR BSD-3-Clause"
|
||||
edition = "2021"
|
||||
publish = false
|
||||
|
||||
[features]
|
||||
xen = ["vm-memory/xen", "vhost/xen", "vhost-user-backend/xen"]
|
||||
|
||||
[dependencies]
|
||||
clap = { version = "4.4", features = ["derive"] }
|
||||
env_logger = "0.11.5"
|
||||
libc = "0.2"
|
||||
log = "0.4"
|
||||
|
||||
[target.'cfg(not(target_env = "musl"))'.dependencies]
|
||||
rutabaga_gfx = { version = "0.1.4", features = ["gfxstream", "virgl_renderer"] }
|
||||
thiserror = "2.0.3"
|
||||
vhost = { version = "0.13.0", features = ["vhost-user-backend"] }
|
||||
vhost-user-backend = "0.17"
|
||||
virtio-bindings = "0.2.2"
|
||||
virtio-queue = "0.14.0"
|
||||
vm-memory = "0.16.1"
|
||||
vmm-sys-util = "0.12.1"
|
||||
|
||||
[dev-dependencies]
|
||||
assert_matches = "1.5"
|
||||
tempfile = "3.13"
|
||||
virtio-queue = { version = "0.14", features = ["test-utils"] }
|
||||
vm-memory = { version = "0.16.1", features = ["backend-mmap", "backend-atomic"] }
|
||||
mockall = "0.13.0"
|
||||
rusty-fork = "0.3.0"
|
||||
1
staging/vhost-device-gpu/LICENSE-APACHE
Normal file
1
staging/vhost-device-gpu/LICENSE-APACHE
Normal file
@ -0,0 +1 @@
|
||||
../../LICENSE-APACHE
|
||||
1
staging/vhost-device-gpu/LICENSE-BSD-3-Clause
Normal file
1
staging/vhost-device-gpu/LICENSE-BSD-3-Clause
Normal file
@ -0,0 +1 @@
|
||||
../../LICENSE-BSD-3-Clause
|
||||
101
staging/vhost-device-gpu/README.md
Normal file
101
staging/vhost-device-gpu/README.md
Normal file
@ -0,0 +1,101 @@
|
||||
# vhost-device-gpu - GPU emulation backend daemon
|
||||
|
||||
## Synopsis
|
||||
```shell
|
||||
vhost-device-gpu --socket-path <SOCKET>
|
||||
```
|
||||
|
||||
## Description
|
||||
A virtio-gpu device using the vhost-user protocol.
|
||||
|
||||
## Options
|
||||
|
||||
```text
|
||||
-s, --socket-path <SOCKET>
|
||||
vhost-user Unix domain socket path
|
||||
|
||||
-h, --help
|
||||
Print help
|
||||
|
||||
-V, --version
|
||||
Print version
|
||||
```
|
||||
|
||||
## Limitations
|
||||
|
||||
We are currently only supporting sharing the display output to QEMU through a
|
||||
socket using the transfer_read operation triggered by
|
||||
VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D to transfer data from and to virtio-gpu 3d
|
||||
resources. It'll be nice to have support for directly sharing display output
|
||||
resource using dmabuf.
|
||||
|
||||
This device does not yet support the VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB,
|
||||
VIRTIO_GPU_CMD_SET_SCANOUT_BLOB and VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID features.
|
||||
|
||||
Currently this crate requires some necessary bits in order to move the crate out of staging:
|
||||
|
||||
- Achieving a minimum of ~87% code coverage in the main vhost-device repository,
|
||||
which requires some additional unit tests to increase code coverage.
|
||||
- Addition of CLI arguments to specify the exact number of capsets and use
|
||||
a default capset configuration when no capset is specified rather than using
|
||||
hard-coded capset value.
|
||||
|
||||
## Features
|
||||
|
||||
The device leverages the [rutabaga_gfx](https://crates.io/crates/rutabaga_gfx) crate
|
||||
to provide virglrenderer and gfxstream rendering. With Virglrenderer, Rutabaga
|
||||
translates OpenGL API and Vulkan calls to an intermediate representation and allows
|
||||
for OpenGL acceleration on the host. With the gfxstream rendering mode, GLES and
|
||||
Vulkan calls are forwarded to the host with minimal modification.
|
||||
|
||||
## Examples
|
||||
|
||||
First start the daemon on the host machine using either of the 2 gpu modes:
|
||||
|
||||
1) virgl-renderer
|
||||
2) gfxstream
|
||||
|
||||
```shell
|
||||
host# vhost-device-gpu --socket-path /tmp/gpu.socket --gpu-mode virgl-renderer
|
||||
```
|
||||
|
||||
With QEMU, there are two device front-ends you can use with this device.
|
||||
You can either use `vhost-user-gpu-pci` or `vhost-user-vga`, which also
|
||||
implements VGA, that allows you to see boot messages before the guest
|
||||
initializes the GPU. You can also use different display outputs (for example
|
||||
`gtk` or `dbus`).
|
||||
By default, QEMU also adds another VGA output, use `-vga none` to make
|
||||
sure it is disabled.
|
||||
|
||||
1) Using `vhost-user-gpu-pci`
|
||||
|
||||
Start QEMU with the following flags:
|
||||
|
||||
```text
|
||||
-chardev socket,id=vgpu,path=/tmp/gpu.socket \
|
||||
-device vhost-user-gpu-pci,chardev=vgpu,id=vgpu \
|
||||
-object memory-backend-memfd,share=on,id=mem0,size=4G, \
|
||||
-machine q35,memory-backend=mem0,accel=kvm \
|
||||
-display gtk,gl=on,show-cursor=on \
|
||||
-vga none
|
||||
```
|
||||
|
||||
2) Using `vhost-user-vga`
|
||||
|
||||
Start QEMU with the following flags:
|
||||
|
||||
```text
|
||||
-chardev socket,id=vgpu,path=/tmp/gpu.socket \
|
||||
-device vhost-user-vga,chardev=vgpu,id=vgpu \
|
||||
-object memory-backend-memfd,share=on,id=mem0,size=4G, \
|
||||
-machine q35,memory-backend=mem0,accel=kvm \
|
||||
-display gtk,gl=on,show-cursor=on \
|
||||
-vga none
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under either of
|
||||
|
||||
- [Apache License](http://www.apache.org/licenses/LICENSE-2.0), Version 2.0
|
||||
- [BSD-3-Clause License](https://opensource.org/licenses/BSD-3-Clause)
|
||||
7
staging/vhost-device-gpu/rustfmt.toml
Normal file
7
staging/vhost-device-gpu/rustfmt.toml
Normal file
@ -0,0 +1,7 @@
|
||||
edition = "2018"
|
||||
format_generated_files = false
|
||||
format_code_in_doc_comments = true
|
||||
format_strings = true
|
||||
imports_granularity = "Crate"
|
||||
group_imports = "StdExternalCrate"
|
||||
wrap_comments = true
|
||||
1630
staging/vhost-device-gpu/src/device.rs
Normal file
1630
staging/vhost-device-gpu/src/device.rs
Normal file
File diff suppressed because it is too large
Load Diff
99
staging/vhost-device-gpu/src/lib.rs
Normal file
99
staging/vhost-device-gpu/src/lib.rs
Normal file
@ -0,0 +1,99 @@
|
||||
// Copyright 2024 Red Hat Inc
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
|
||||
|
||||
#![deny(
|
||||
clippy::undocumented_unsafe_blocks,
|
||||
/* groups */
|
||||
clippy::correctness,
|
||||
clippy::suspicious,
|
||||
clippy::complexity,
|
||||
clippy::perf,
|
||||
clippy::style,
|
||||
clippy::nursery,
|
||||
//* restriction */
|
||||
clippy::dbg_macro,
|
||||
clippy::rc_buffer,
|
||||
clippy::as_underscore,
|
||||
clippy::assertions_on_result_states,
|
||||
//* pedantic */
|
||||
clippy::cast_lossless,
|
||||
clippy::cast_possible_wrap,
|
||||
clippy::ptr_as_ptr,
|
||||
clippy::bool_to_int_with_if,
|
||||
clippy::borrow_as_ptr,
|
||||
clippy::case_sensitive_file_extension_comparisons,
|
||||
clippy::cast_lossless,
|
||||
clippy::cast_ptr_alignment,
|
||||
clippy::naive_bytecount
|
||||
)]
|
||||
#![allow(
|
||||
clippy::missing_errors_doc,
|
||||
clippy::missing_panics_doc,
|
||||
clippy::must_use_candidate,
|
||||
clippy::significant_drop_in_scrutinee,
|
||||
clippy::significant_drop_tightening
|
||||
)]
|
||||
|
||||
#[cfg(target_env = "gnu")]
|
||||
pub mod device;
|
||||
#[cfg(target_env = "gnu")]
|
||||
pub mod protocol;
|
||||
#[cfg(target_env = "gnu")]
|
||||
pub mod virtio_gpu;
|
||||
|
||||
use std::path::{Path, PathBuf};
|
||||
|
||||
use clap::ValueEnum;
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, Eq, ValueEnum)]
|
||||
pub enum GpuMode {
|
||||
VirglRenderer,
|
||||
Gfxstream,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
/// This structure holds the internal configuration for the GPU backend,
|
||||
/// derived from the command-line arguments provided through `GpuArgs`.
|
||||
pub struct GpuConfig {
|
||||
/// vhost-user Unix domain socket
|
||||
socket_path: PathBuf,
|
||||
gpu_mode: GpuMode,
|
||||
}
|
||||
|
||||
impl GpuConfig {
|
||||
/// Create a new instance of the `GpuConfig` struct, containing the
|
||||
/// parameters to be fed into the gpu-backend server.
|
||||
pub const fn new(socket_path: PathBuf, gpu_mode: GpuMode) -> Self {
|
||||
Self {
|
||||
socket_path,
|
||||
gpu_mode,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the path of the unix domain socket which is listening to
|
||||
/// requests from the guest.
|
||||
pub fn socket_path(&self) -> &Path {
|
||||
&self.socket_path
|
||||
}
|
||||
|
||||
pub const fn gpu_mode(&self) -> GpuMode {
|
||||
self.gpu_mode
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use tempfile::tempdir;
|
||||
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn test_gpu_config() {
|
||||
// Test the creation of `GpuConfig` struct
|
||||
let test_dir = tempdir().expect("Could not create a temp test directory.");
|
||||
let socket_path = test_dir.path().join("socket");
|
||||
let gpu_config = GpuConfig::new(socket_path.clone(), GpuMode::VirglRenderer);
|
||||
assert_eq!(gpu_config.socket_path(), socket_path);
|
||||
}
|
||||
}
|
||||
132
staging/vhost-device-gpu/src/main.rs
Normal file
132
staging/vhost-device-gpu/src/main.rs
Normal file
@ -0,0 +1,132 @@
|
||||
// VIRTIO GPU Emulation via vhost-user
|
||||
//
|
||||
// Copyright 2024 Red Hat Inc
|
||||
//
|
||||
// SPDX-License-Identifier: Apache-2.0 or BSD-3-Clause
|
||||
|
||||
// Rust vmm container (https://github.com/rust-vmm/rust-vmm-container) doesn't
|
||||
// have tools to do a musl build at the moment, and adding that support is
|
||||
// tricky as well to the container. Skip musl builds until the time pre-built
|
||||
// rutabaga library is available for musl.
|
||||
#[cfg(target_env = "gnu")]
|
||||
pub mod gnu_main {
|
||||
use std::{path::PathBuf, process::exit};
|
||||
|
||||
use clap::Parser;
|
||||
use log::{error, info};
|
||||
use thiserror::Error as ThisError;
|
||||
use vhost_device_gpu::{
|
||||
device::{self, VhostUserGpuBackend},
|
||||
GpuConfig, GpuMode,
|
||||
};
|
||||
use vhost_user_backend::VhostUserDaemon;
|
||||
use vm_memory::{GuestMemoryAtomic, GuestMemoryMmap};
|
||||
|
||||
type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[derive(Debug, ThisError)]
|
||||
pub enum Error {
|
||||
#[error("Could not create backend: {0}")]
|
||||
CouldNotCreateBackend(device::Error),
|
||||
#[error("Could not create daemon: {0}")]
|
||||
CouldNotCreateDaemon(vhost_user_backend::Error),
|
||||
#[error("Fatal error: {0}")]
|
||||
ServeFailed(vhost_user_backend::Error),
|
||||
}
|
||||
|
||||
#[derive(Parser, Debug)]
|
||||
#[clap(author, version, about, long_about = None)]
|
||||
pub struct GpuArgs {
|
||||
/// vhost-user Unix domain socket.
|
||||
#[clap(short, long, value_name = "SOCKET")]
|
||||
pub socket_path: PathBuf,
|
||||
#[clap(short, long, value_enum)]
|
||||
pub gpu_mode: GpuMode,
|
||||
}
|
||||
|
||||
impl From<GpuArgs> for GpuConfig {
|
||||
fn from(args: GpuArgs) -> Self {
|
||||
let socket_path = args.socket_path;
|
||||
let gpu_mode: GpuMode = args.gpu_mode;
|
||||
|
||||
GpuConfig::new(socket_path, gpu_mode)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn start_backend(config: &GpuConfig) -> Result<()> {
|
||||
info!("Starting backend");
|
||||
let socket = config.socket_path();
|
||||
let backend = VhostUserGpuBackend::new(config).map_err(Error::CouldNotCreateBackend)?;
|
||||
|
||||
let mut daemon = VhostUserDaemon::new(
|
||||
"vhost-device-gpu-backend".to_string(),
|
||||
backend.clone(),
|
||||
GuestMemoryAtomic::new(GuestMemoryMmap::new()),
|
||||
)
|
||||
.map_err(Error::CouldNotCreateDaemon)?;
|
||||
|
||||
backend.set_epoll_handler(&daemon.get_epoll_handlers());
|
||||
|
||||
daemon.serve(socket).map_err(Error::ServeFailed)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn main() {
|
||||
env_logger::init();
|
||||
|
||||
if let Err(e) = start_backend(&GpuConfig::from(GpuArgs::parse())) {
|
||||
error!("{e}");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_env = "gnu")]
|
||||
fn main() {
|
||||
gnu_main::main();
|
||||
}
|
||||
|
||||
#[cfg(target_env = "musl")]
|
||||
fn main() {}
|
||||
|
||||
#[cfg(target_env = "gnu")]
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::path::Path;
|
||||
|
||||
use assert_matches::assert_matches;
|
||||
use tempfile::tempdir;
|
||||
use vhost_device_gpu::{GpuConfig, GpuMode};
|
||||
|
||||
use super::gnu_main::{start_backend, Error, GpuArgs};
|
||||
|
||||
impl GpuArgs {
|
||||
pub(crate) fn from_args(path: &Path) -> Self {
|
||||
Self {
|
||||
socket_path: path.to_path_buf(),
|
||||
gpu_mode: GpuMode::Gfxstream,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_successful() {
|
||||
let test_dir = tempdir().expect("Could not create a temp test directory.");
|
||||
let socket_path = test_dir.path().join("vgpu.sock");
|
||||
|
||||
let cmd_args = GpuArgs::from_args(socket_path.as_path());
|
||||
let config = GpuConfig::from(cmd_args);
|
||||
|
||||
assert_eq!(config.socket_path(), socket_path);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fail_listener() {
|
||||
// This will fail the listeners and thread will panic.
|
||||
let socket_name = Path::new("/proc/-1/nonexistent");
|
||||
let cmd_args = GpuArgs::from_args(socket_name);
|
||||
let config = GpuConfig::from(cmd_args);
|
||||
|
||||
assert_matches!(start_backend(&config).unwrap_err(), Error::ServeFailed(_));
|
||||
}
|
||||
}
|
||||
1395
staging/vhost-device-gpu/src/protocol.rs
Normal file
1395
staging/vhost-device-gpu/src/protocol.rs
Normal file
File diff suppressed because it is too large
Load Diff
1046
staging/vhost-device-gpu/src/virtio_gpu.rs
Normal file
1046
staging/vhost-device-gpu/src/virtio_gpu.rs
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user