devices: gpu: fallback to 2D backend on failed virgl backend init

If virglrenderer as the default GPU backend failed initialization, fall
back to 2D mode to prevent crashing the VM. This configuration is still
able to support software-rendered workflows with ChromeOS' usual
virtio-wl supported windowing.

BUG=b:329522487
TEST=Crostini software rendered glxgears still works with failing
virglrenderer init.

Change-Id: I931b0a8c5662ce9726a85aaaa05565b901b727cf
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/5468982
Reviewed-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-by: Gurchetan Singh <gurchetansingh@chromium.org>
Commit-Queue: Ryan Neph <ryanneph@google.com>
This commit is contained in:
Ryan Neph 2024-04-19 11:59:33 -07:00 committed by crosvm LUCI
parent 02c05d6c84
commit fbe3f46963
2 changed files with 38 additions and 17 deletions

View file

@ -859,12 +859,25 @@ impl VirtioGpu {
/// Gets rutabaga's capset information associated with `index`. /// Gets rutabaga's capset information associated with `index`.
pub fn get_capset_info(&self, index: u32) -> VirtioGpuResult { pub fn get_capset_info(&self, index: u32) -> VirtioGpuResult {
let (capset_id, version, size) = self.rutabaga.get_capset_info(index)?; if let Ok((capset_id, version, size)) = self.rutabaga.get_capset_info(index) {
Ok(OkCapsetInfo { Ok(OkCapsetInfo {
capset_id, capset_id,
version, version,
size, size,
}) })
} else {
// Any capset_id > 63 is invalid according to the virtio-gpu spec, so we can
// intentionally poison the capset without stalling the guest kernel driver.
base::warn!(
"virtio-gpu get_capset_info(index={}) failed. intentionally poisoning response",
index
);
Ok(OkCapsetInfo {
capset_id: u32::max_value(),
version: 0,
size: 0,
})
}
} }
/// Gets a capset from rutabaga. /// Gets a capset from rutabaga.

View file

@ -1177,23 +1177,26 @@ impl RutabagaBuilder {
)); ));
} }
if self.default_component == RutabagaComponentType::Rutabaga2D { #[allow(unused_mut)]
let rutabaga_2d = Rutabaga2D::init(fence_handler.clone())?; let mut fallback_2d = false;
rutabaga_components.insert(RutabagaComponentType::Rutabaga2D, rutabaga_2d); if self.default_component != RutabagaComponentType::Rutabaga2D {
} else {
#[cfg(feature = "virgl_renderer")] #[cfg(feature = "virgl_renderer")]
if self.default_component == RutabagaComponentType::VirglRenderer { if self.default_component == RutabagaComponentType::VirglRenderer {
let virgl = VirglRenderer::init( if let Ok(virgl) = VirglRenderer::init(
self.virglrenderer_flags, self.virglrenderer_flags,
fence_handler.clone(), fence_handler.clone(),
rutabaga_server_descriptor, rutabaga_server_descriptor,
)?; ) {
rutabaga_components.insert(RutabagaComponentType::VirglRenderer, virgl); rutabaga_components.insert(RutabagaComponentType::VirglRenderer, virgl);
push_capset(RUTABAGA_CAPSET_VIRGL); push_capset(RUTABAGA_CAPSET_VIRGL);
push_capset(RUTABAGA_CAPSET_VIRGL2); push_capset(RUTABAGA_CAPSET_VIRGL2);
push_capset(RUTABAGA_CAPSET_VENUS); push_capset(RUTABAGA_CAPSET_VENUS);
push_capset(RUTABAGA_CAPSET_DRM); push_capset(RUTABAGA_CAPSET_DRM);
} else {
log::warn!("error initializing gpu backend=virglrenderer, falling back to 2d.");
fallback_2d = true;
};
} }
#[cfg(feature = "gfxstream")] #[cfg(feature = "gfxstream")]
@ -1220,6 +1223,11 @@ impl RutabagaBuilder {
push_capset(RUTABAGA_CAPSET_CROSS_DOMAIN); push_capset(RUTABAGA_CAPSET_CROSS_DOMAIN);
} }
if self.default_component == RutabagaComponentType::Rutabaga2D || fallback_2d {
let rutabaga_2d = Rutabaga2D::init(fence_handler.clone())?;
rutabaga_components.insert(RutabagaComponentType::Rutabaga2D, rutabaga_2d);
}
Ok(Rutabaga { Ok(Rutabaga {
resources: Default::default(), resources: Default::default(),
contexts: Default::default(), contexts: Default::default(),