From fbe3f46963debc35a23d22a4a19705643cec3c86 Mon Sep 17 00:00:00 2001 From: Ryan Neph Date: Fri, 19 Apr 2024 11:59:33 -0700 Subject: [PATCH] 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 Reviewed-by: Gurchetan Singh Commit-Queue: Ryan Neph --- devices/src/virtio/gpu/virtio_gpu.rs | 25 +++++++++++++++++------ rutabaga_gfx/src/rutabaga_core.rs | 30 ++++++++++++++++++---------- 2 files changed, 38 insertions(+), 17 deletions(-) diff --git a/devices/src/virtio/gpu/virtio_gpu.rs b/devices/src/virtio/gpu/virtio_gpu.rs index cb95969bb1..ae87e3ea7a 100644 --- a/devices/src/virtio/gpu/virtio_gpu.rs +++ b/devices/src/virtio/gpu/virtio_gpu.rs @@ -859,12 +859,25 @@ impl VirtioGpu { /// Gets rutabaga's capset information associated with `index`. pub fn get_capset_info(&self, index: u32) -> VirtioGpuResult { - let (capset_id, version, size) = self.rutabaga.get_capset_info(index)?; - Ok(OkCapsetInfo { - capset_id, - version, - size, - }) + if let Ok((capset_id, version, size)) = self.rutabaga.get_capset_info(index) { + Ok(OkCapsetInfo { + capset_id, + version, + 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. diff --git a/rutabaga_gfx/src/rutabaga_core.rs b/rutabaga_gfx/src/rutabaga_core.rs index ab89e7e872..d487449209 100644 --- a/rutabaga_gfx/src/rutabaga_core.rs +++ b/rutabaga_gfx/src/rutabaga_core.rs @@ -1177,23 +1177,26 @@ impl RutabagaBuilder { )); } - if self.default_component == RutabagaComponentType::Rutabaga2D { - let rutabaga_2d = Rutabaga2D::init(fence_handler.clone())?; - rutabaga_components.insert(RutabagaComponentType::Rutabaga2D, rutabaga_2d); - } else { + #[allow(unused_mut)] + let mut fallback_2d = false; + if self.default_component != RutabagaComponentType::Rutabaga2D { #[cfg(feature = "virgl_renderer")] if self.default_component == RutabagaComponentType::VirglRenderer { - let virgl = VirglRenderer::init( + if let Ok(virgl) = VirglRenderer::init( self.virglrenderer_flags, fence_handler.clone(), rutabaga_server_descriptor, - )?; - rutabaga_components.insert(RutabagaComponentType::VirglRenderer, virgl); + ) { + rutabaga_components.insert(RutabagaComponentType::VirglRenderer, virgl); - push_capset(RUTABAGA_CAPSET_VIRGL); - push_capset(RUTABAGA_CAPSET_VIRGL2); - push_capset(RUTABAGA_CAPSET_VENUS); - push_capset(RUTABAGA_CAPSET_DRM); + push_capset(RUTABAGA_CAPSET_VIRGL); + push_capset(RUTABAGA_CAPSET_VIRGL2); + push_capset(RUTABAGA_CAPSET_VENUS); + push_capset(RUTABAGA_CAPSET_DRM); + } else { + log::warn!("error initializing gpu backend=virglrenderer, falling back to 2d."); + fallback_2d = true; + }; } #[cfg(feature = "gfxstream")] @@ -1220,6 +1223,11 @@ impl RutabagaBuilder { 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 { resources: Default::default(), contexts: Default::default(),