Skip to content

Commit 0dd8175

Browse files
author
Dorinda Bassey
committed
vhost-device-gpu: Add support for GPU device path
Add a new --gpu-path CLI argument that allows users to specify which GPU device to use for rendering when using the virglrenderer backend. This is useful for systems with multiple GPUs where a specific device needs to be selected. Signed-off-by: Dorinda Bassey <[email protected]>
1 parent cf95bca commit 0dd8175

File tree

6 files changed

+60
-2
lines changed

6 files changed

+60
-2
lines changed

vhost-device-gpu/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
### Added
55

6+
- [[#903]] (https://github.com/rust-vmm/vhost-device/pull/903) vhost-device-gpu: Add support for GPU device path
7+
68
### Changed
79

810
- [[#852]] (https://github.com/rust-vmm/vhost-device/pull/890) vhost-device-gpu: Refactor vhost-device-gpu

vhost-device-gpu/README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ A virtio-gpu device using the vhost-user protocol.
5656
[default: true]
5757
[possible values: true, false]
5858
59+
--gpu-path <PATH>
60+
GPU device path (e.g., /dev/dri/renderD128)
61+
62+
[Optional] Specifies which GPU device to use for rendering. Only
63+
applicable when using the virglrenderer backend. If not specified,
64+
virglrenderer will automatically select the default GPU device.
65+
5966
-h, --help
6067
Print help (see a summary with '-h')
6168
@@ -134,6 +141,12 @@ First start the daemon on the host machine using one of the available gpu modes:
134141
host# vhost-device-gpu --socket-path /tmp/gpu.socket --gpu-mode virglrenderer
135142
```
136143

144+
To specify a particular GPU device (e.g., when you have multiple GPUs):
145+
146+
```shell
147+
host# vhost-device-gpu --socket-path /tmp/gpu.socket --gpu-mode virglrenderer --gpu-path /dev/dri/renderD128
148+
```
149+
137150
With QEMU, there are two device front-ends you can use with this device.
138151
You can either use `vhost-user-gpu-pci` or `vhost-user-vga`, which also
139152
implements VGA, that allows you to see boot messages before the guest

vhost-device-gpu/src/backend/virgl.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use std::{
88
collections::BTreeMap,
9+
fs::File,
910
io::{self, IoSliceMut},
1011
os::fd::{AsFd, FromRawFd, IntoRawFd, RawFd},
1112
sync::{Arc, Mutex},
@@ -163,8 +164,16 @@ impl VirglRendererAdapter {
163164
fence_state.clone(),
164165
));
165166

166-
let renderer = VirglRenderer::init(virglrenderer_flags, fence_handler, None)
167-
.expect("Failed to initialize virglrenderer");
167+
// Open the GPU device if a path was specified
168+
// Note: The path is validated early in start_backend(), so this should not fail
169+
let render_server_fd = config
170+
.flags()
171+
.gpu_path
172+
.as_ref()
173+
.map(|path| File::open(path).map(|f| f.into()).unwrap());
174+
175+
let renderer = VirglRenderer::init(virglrenderer_flags, fence_handler, render_server_fd)
176+
.map_err(|e| io::Error::other(format!("Failed to initialize virglrenderer: {e:?}")))?;
168177
Ok(Self {
169178
renderer,
170179
gpu_backend,

vhost-device-gpu/src/device.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ pub enum Error {
110110
NotificationFailed(io::Error),
111111
#[error("Failed to create new EventFd")]
112112
EventFdFailed,
113+
#[error("Invalid GPU device path: {0}")]
114+
InvalidGpuDevice(io::Error),
113115
#[error("Failed to create an iterator over a descriptor chain: {0}")]
114116
CreateIteratorDescChain(virtio_queue::Error),
115117
#[error("Failed to create descriptor chain Reader: {0}")]

vhost-device-gpu/src/lib.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,8 @@ pub struct GpuFlags {
131131
pub use_glx: bool,
132132
pub use_gles: bool,
133133
pub use_surfaceless: bool,
134+
#[cfg(feature = "backend-virgl")]
135+
pub gpu_path: Option<std::path::PathBuf>,
134136
}
135137

136138
impl GpuFlags {
@@ -141,6 +143,8 @@ impl GpuFlags {
141143
use_glx: false,
142144
use_gles: true,
143145
use_surfaceless: true,
146+
#[cfg(feature = "backend-virgl")]
147+
gpu_path: None,
144148
}
145149
}
146150
}
@@ -157,6 +161,8 @@ pub enum GpuConfigError {
157161
CapsetUnsupportedByMode(GpuMode, GpuCapset),
158162
#[error("Requested gfxstream-gles capset, but gles is disabled")]
159163
GlesRequiredByGfxstream,
164+
#[error("GPU path can only be specified when using virglrenderer mode")]
165+
GpuPathNotSupportedByMode,
160166
}
161167

162168
impl GpuConfig {
@@ -208,6 +214,12 @@ impl GpuConfig {
208214
return Err(GpuConfigError::GlesRequiredByGfxstream);
209215
}
210216

217+
// Validate that gpu_path is only used with virglrenderer
218+
#[cfg(feature = "backend-virgl")]
219+
if flags.gpu_path.is_some() && !matches!(gpu_mode, GpuMode::VirglRenderer) {
220+
return Err(GpuConfigError::GpuPathNotSupportedByMode);
221+
}
222+
211223
Ok(Self {
212224
gpu_mode,
213225
capset,
@@ -240,6 +252,15 @@ pub enum StartError {
240252

241253
pub fn start_backend(socket_path: &Path, config: GpuConfig) -> Result<(), StartError> {
242254
info!("Starting backend");
255+
256+
// Validate GPU device path early if provided (virgl backend only)
257+
#[cfg(feature = "backend-virgl")]
258+
if let Some(gpu_path) = config.flags().gpu_path.as_ref() {
259+
use std::fs::File;
260+
File::open(gpu_path)
261+
.map_err(|e| StartError::CouldNotCreateBackend(device::Error::InvalidGpuDevice(e)))?;
262+
}
263+
243264
let backend = VhostUserGpuBackend::new(config).map_err(StartError::CouldNotCreateBackend)?;
244265

245266
let mut daemon = VhostUserDaemon::new(

vhost-device-gpu/src/main.rs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,11 @@ pub struct GpuFlagsArgs {
114114
default_value_t = GpuFlags::new_default().use_surfaceless
115115
)]
116116
pub use_surfaceless: bool,
117+
118+
/// GPU device path (e.g., /dev/dri/renderD128)
119+
#[clap(long, value_name = "PATH")]
120+
#[cfg(feature = "backend-virgl")]
121+
pub gpu_path: Option<PathBuf>,
117122
}
118123

119124
impl From<GpuFlagsArgs> for GpuFlags {
@@ -123,6 +128,8 @@ impl From<GpuFlagsArgs> for GpuFlags {
123128
use_glx: args.use_glx,
124129
use_gles: args.use_gles,
125130
use_surfaceless: args.use_surfaceless,
131+
#[cfg(feature = "backend-virgl")]
132+
gpu_path: args.gpu_path,
126133
}
127134
}
128135
}
@@ -200,6 +207,8 @@ mod tests {
200207
use_glx: true,
201208
use_gles: false,
202209
use_surfaceless: false,
210+
#[cfg(feature = "backend-virgl")]
211+
gpu_path: None,
203212
},
204213
};
205214

@@ -213,6 +222,8 @@ mod tests {
213222
use_glx: true,
214223
use_gles: false,
215224
use_surfaceless: false,
225+
#[cfg(feature = "backend-virgl")]
226+
gpu_path: None,
216227
}
217228
);
218229
assert_eq!(config.gpu_mode(), GpuMode::VirglRenderer);

0 commit comments

Comments
 (0)