Skip to content

Commit 7f60738

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 5e83c07 commit 7f60738

File tree

5 files changed

+80
-1
lines changed

5 files changed

+80
-1
lines changed

vhost-device-gpu/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
### Changed
77

8+
- [[#903]] (https://github.com/rust-vmm/vhost-device/pull/903) vhost-device-gpu: Add support for GPU device path
89
- [[#852]] (https://github.com/rust-vmm/vhost-device/pull/890) vhost-device-gpu: Refactor vhost-device-gpu
910

1011
### Fixed

vhost-device-gpu/README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ 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+
Specifies which GPU device to use for rendering. Only applicable
63+
when using the virglrenderer backend.
64+
5965
-h, --help
6066
Print help (see a summary with '-h')
6167
@@ -134,6 +140,12 @@ First start the daemon on the host machine using one of the available gpu modes:
134140
host# vhost-device-gpu --socket-path /tmp/gpu.socket --gpu-mode virglrenderer
135141
```
136142

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

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

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
use std::{
88
collections::BTreeMap,
9+
fs::File,
910
io::IoSliceMut,
1011
os::fd::{AsFd, FromRawFd, IntoRawFd, RawFd},
1112
sync::{Arc, Mutex},
@@ -159,7 +160,16 @@ impl VirglRendererAdapter {
159160
fence_state.clone(),
160161
));
161162

162-
let renderer = VirglRenderer::init(virglrenderer_flags, fence_handler, None)
163+
// Open the GPU device if a path was specified
164+
let render_server_fd = config.flags().gpu_path.as_ref().map(|path| {
165+
File::open(path)
166+
.unwrap_or_else(|e| {
167+
panic!("Failed to open GPU device at {}: {}", path.display(), e)
168+
})
169+
.into()
170+
});
171+
172+
let renderer = VirglRenderer::init(virglrenderer_flags, fence_handler, render_server_fd)
163173
.expect("Failed to initialize virglrenderer");
164174
Self {
165175
renderer,
@@ -638,6 +648,8 @@ impl Renderer for VirglRendererAdapter {
638648
mod virgl_cov_tests {
639649
use std::{
640650
os::unix::net::UnixStream,
651+
panic,
652+
path::PathBuf,
641653
sync::{Arc, Mutex},
642654
};
643655

@@ -925,4 +937,41 @@ mod virgl_cov_tests {
925937
);
926938
}
927939
}
940+
941+
#[test]
942+
fn test_gpu_path_invalid_file_panics() {
943+
// Create a config with an invalid gpu_path
944+
let cfg = GpuConfig::new(
945+
GpuMode::VirglRenderer,
946+
Some(GpuCapset::VIRGL),
947+
GpuFlags {
948+
gpu_path: Some(PathBuf::from("/nonexistent/gpu/device")),
949+
..GpuFlags::default()
950+
},
951+
)
952+
.expect("GpuConfig");
953+
954+
let mem = GuestMemoryAtomic::new(
955+
GuestMemoryMmap::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap(),
956+
);
957+
let (vring, _outs, _call_evt) = create_vring(
958+
&mem,
959+
&[] as &[TestingDescChainArgs],
960+
GuestAddress(0x100),
961+
GuestAddress(0x200),
962+
16,
963+
);
964+
965+
let backend = dummy_gpu_backend();
966+
967+
// This should panic when trying to open the nonexistent GPU device
968+
let result = panic::catch_unwind(panic::AssertUnwindSafe(|| {
969+
let _gpu = VirglRendererAdapter::new(&vring, &cfg, backend);
970+
}));
971+
972+
assert!(
973+
result.is_err(),
974+
"Expected panic when opening invalid GPU device path"
975+
);
976+
}
928977
}

vhost-device-gpu/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ pub struct GpuFlags {
131131
pub use_glx: bool,
132132
pub use_gles: bool,
133133
pub use_surfaceless: bool,
134+
pub gpu_path: Option<std::path::PathBuf>,
134135
}
135136

136137
impl GpuFlags {
@@ -141,6 +142,7 @@ impl GpuFlags {
141142
use_glx: false,
142143
use_gles: true,
143144
use_surfaceless: true,
145+
gpu_path: None,
144146
}
145147
}
146148
}
@@ -157,6 +159,8 @@ pub enum GpuConfigError {
157159
CapsetUnsupportedByMode(GpuMode, GpuCapset),
158160
#[error("Requested gfxstream-gles capset, but gles is disabled")]
159161
GlesRequiredByGfxstream,
162+
#[error("GPU path can only be specified when using virglrenderer mode")]
163+
GpuPathNotSupportedByMode,
160164
}
161165

162166
impl GpuConfig {
@@ -208,6 +212,12 @@ impl GpuConfig {
208212
return Err(GpuConfigError::GlesRequiredByGfxstream);
209213
}
210214

215+
// Validate that gpu_path is only used with virglrenderer
216+
#[cfg(feature = "backend-virgl")]
217+
if flags.gpu_path.is_some() && !matches!(gpu_mode, GpuMode::VirglRenderer) {
218+
return Err(GpuConfigError::GpuPathNotSupportedByMode);
219+
}
220+
211221
Ok(Self {
212222
gpu_mode,
213223
capset,

vhost-device-gpu/src/main.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,10 @@ 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+
pub gpu_path: Option<PathBuf>,
117121
}
118122

119123
impl From<GpuFlagsArgs> for GpuFlags {
@@ -123,6 +127,7 @@ impl From<GpuFlagsArgs> for GpuFlags {
123127
use_glx: args.use_glx,
124128
use_gles: args.use_gles,
125129
use_surfaceless: args.use_surfaceless,
130+
gpu_path: args.gpu_path,
126131
}
127132
}
128133
}
@@ -200,6 +205,7 @@ mod tests {
200205
use_glx: true,
201206
use_gles: false,
202207
use_surfaceless: false,
208+
gpu_path: None,
203209
},
204210
};
205211

@@ -213,6 +219,7 @@ mod tests {
213219
use_glx: true,
214220
use_gles: false,
215221
use_surfaceless: false,
222+
gpu_path: None,
216223
}
217224
);
218225
assert_eq!(config.gpu_mode(), GpuMode::VirglRenderer);

0 commit comments

Comments
 (0)