diff --git a/initfs.toml b/initfs.toml index 53e05f3432..d648d466ad 100644 --- a/initfs.toml +++ b/initfs.toml @@ -23,7 +23,6 @@ subclass = 8 command = ["nvmed"] use_channel = true -# -------------- virtio -------------- # [[drivers]] name = "virtio-blk" class = 1 @@ -33,15 +32,6 @@ device = 4097 command = ["virtio-blkd"] use_channel = true -[[drivers]] -name = "virtio-net" -class = 2 -subclass = 0 -vendor = 6900 -device = 4096 -command = ["virtio-netd"] -use_channel = true - [[drivers]] name = "virtio-gpu" class = 3 diff --git a/virtio-gpud/patches/00-init.patch b/virtio-gpud/patches/00-init.patch deleted file mode 100644 index dc20be1df6..0000000000 --- a/virtio-gpud/patches/00-init.patch +++ /dev/null @@ -1,45 +0,0 @@ -diff --git a/src/main.rs b/src/main.rs -index a99488a..ec97fdd 100644 ---- a/src/main.rs -+++ b/src/main.rs -@@ -78,6 +78,40 @@ pub fn run(file: &Path) -> Result<()> { - println!("init: failed to run: no argument"); - }, - "run.d" => if let Some(new_dir) = args.next() { -+ // On startup, the VESA display driver is started which basically makes use of the framebuffer -+ // provided by the firmware. The GPU device are latter started by `pcid` (such as `virtio-gpu`). -+ let mut devices = vec![]; -+ let schemes = std::fs::read_dir(":").unwrap(); -+ -+ for entry in schemes { -+ let path = entry.unwrap().path(); -+ let path_str = path -+ .into_os_string() -+ .into_string() -+ .expect("init: failed to convert path to string"); -+ -+ if path_str.contains("display") { -+ println!("init: found display scheme {}", path_str); -+ devices.push(path_str); -+ } -+ } -+ -+ let device = devices.iter().filter(|d| !d.contains("vesa")).collect::>(); -+ let device = if device.is_empty() { -+ // No GPU available, fallback to VESA display which *should* always be accessible via `display/vesa:`. -+ "vesa" -+ } else { -+ // Parts: -+ // :/display/virtio-gpu -+ // -+ // 1st: ":" -+ // 2nd: "display" -+ // 3rd: "virtio-gpu" (the one we want!) -+ device[0].split("/").nth(2).unwrap() -+ }; -+ -+ std::env::set_var("DISPLAY", &format!("display/{}:3/activate", device)); -+ - let mut entries = vec![]; - match read_dir(&new_dir) { - Ok(list) => for entry_res in list { diff --git a/virtio-gpud/patches/01-orbital.patch b/virtio-gpud/patches/01-orbital.patch deleted file mode 100644 index 0dc1b7c6dd..0000000000 --- a/virtio-gpud/patches/01-orbital.patch +++ /dev/null @@ -1,58 +0,0 @@ -diff --git a/src/core/mod.rs b/src/core/mod.rs -index 85337dd..a454579 100644 ---- a/src/core/mod.rs -+++ b/src/core/mod.rs -@@ -160,6 +160,9 @@ pub struct Orbital { - pub todo: Vec, - pub displays: Vec, - pub maps: BTreeMap, -+ -+ /// Handle to "input:consumer" to recieve input events. -+ pub input: File, - } - - impl Orbital { -@@ -259,6 +262,7 @@ impl Orbital { - todo: Vec::new(), - displays, - maps: BTreeMap::new(), -+ input: File::open("input:consumer")?, - }) - } - -@@ -294,6 +298,7 @@ impl Orbital { - - let scheme_fd = self.scheme.as_raw_fd(); - let display_fd = self.displays[0].file.as_raw_fd(); -+ let input_fd = self.input.as_raw_fd(); - - handler.handle_startup(&mut self)?; - -@@ -337,12 +342,12 @@ impl Orbital { - Ok(result) - })?; - -- event_queue.add(display_fd, move |_| -> io::Result> { -+ event_queue.add(input_fd, move |_| -> io::Result> { - let mut me = me2.borrow_mut(); - let me = &mut *me; - let mut events = [Event::new(); 16]; - loop { -- match read_to_slice(&mut me.orb.displays[0].file, &mut events)? { -+ match read_to_slice(&mut me.orb.input, &mut events)? { - 0 => break, - count => { - let events = &mut events[..count]; -diff --git a/src/main.rs b/src/main.rs -index 1cdf9cf..3859ac0 100644 ---- a/src/main.rs -+++ b/src/main.rs -@@ -63,7 +63,7 @@ fn orbital(daemon: Daemon) -> Result<(), String> { - .enable(); - - let mut args = env::args().skip(1); -- let display_path = args.next().ok_or("no display argument")?; -+ let display_path = env::var("DISPLAY").unwrap(); - let login_cmd = args.next().ok_or("no login manager argument")?; - - core::fix_env(&display_path).map_err(|_| "error setting env vars")?; diff --git a/virtio-gpud/src/main.rs b/virtio-gpud/src/main.rs index ce3dc49a53..f9671f2485 100644 --- a/virtio-gpud/src/main.rs +++ b/virtio-gpud/src/main.rs @@ -3,6 +3,23 @@ //! XXX: 3D mode will offload rendering ops to the host gpu and therefore requires a GPU with 3D support //! on the host machine. +// Notes for the future: +// +// `virtio-gpu` 2D acceleration is just blitting. 3D acceleration has 2 kinds: +// - virgl - OpenGL +// - venus - Vulkan +// +// The Venus driver requires support for the following from the `virtio-gpu` kernel driver: +// - VIRTGPU_PARAM_3D_FEATURES +// - VIRTGPU_PARAM_CAPSET_QUERY_FIX +// - VIRTGPU_PARAM_RESOURCE_BLOB +// - VIRTGPU_PARAM_HOST_VISIBLE +// - VIRTGPU_PARAM_CROSS_DEVICE +// - VIRTGPU_PARAM_CONTEXT_INIT +// +// cc https://docs.mesa3d.org/drivers/venus.html +// cc https://docs.mesa3d.org/drivers/virgl.html + #![feature(int_roundings)] use std::fs::File; @@ -371,7 +388,6 @@ fn deamon(deamon: redox_daemon::Daemon) -> anyhow::Result<()> { device.transport.run_device(); deamon.ready().unwrap(); - let mut socket_file = File::create(":display/virtio-gpu")?; let mut scheme = scheme::Scheme::new(config, control_queue.clone(), cursor_queue.clone())?; diff --git a/virtio-gpud/src/scheme.rs b/virtio-gpud/src/scheme.rs index 2dd680fd48..89c524a517 100644 --- a/virtio-gpud/src/scheme.rs +++ b/virtio-gpud/src/scheme.rs @@ -1,17 +1,13 @@ -use std::{ - collections::BTreeMap, - sync::{ - atomic::{AtomicUsize, Ordering, AtomicU32}, - Arc, - }, -}; +use std::collections::BTreeMap; + +use std::sync::atomic::{AtomicU32, AtomicUsize, Ordering}; +use std::sync::Arc; use syscall::{Dma, Error as SysError, SchemeMut, EINVAL}; -use virtio_core::{ - spec::{Buffer, ChainBuilder, DescriptorFlags}, - transport::{Error, Queue}, - utils::VolatileCell, -}; + +use virtio_core::spec::{Buffer, ChainBuilder, DescriptorFlags}; +use virtio_core::transport::{Error, Queue}; +use virtio_core::utils::VolatileCell; use crate::*; @@ -31,9 +27,12 @@ pub struct Display<'a> { } impl<'a> Display<'a> { - pub fn new(control_queue: Arc>, cursor_queue: Arc>, display_info: & mut DisplayInfo, id: usize) -> Self { - display_info.enabled.set(1); - + pub fn new( + control_queue: Arc>, + cursor_queue: Arc>, + _display_info: &mut DisplayInfo, + id: usize, + ) -> Self { Self { control_queue, cursor_queue, @@ -44,7 +43,7 @@ impl<'a> Display<'a> { height: 1080, id, - resource_id: RESOURCE_ALLOC.fetch_add(1, Ordering::SeqCst) + resource_id: RESOURCE_ALLOC.fetch_add(1, Ordering::SeqCst), } } @@ -94,8 +93,8 @@ impl<'a> Display<'a> { // lists are supported, so the framebuffer doesn’t need to be contignous in guest // physical memory. let bpp = 32; - let fb_size = - (self.width as usize * self.height as usize * bpp / 8).next_multiple_of(syscall::PAGE_SIZE); + let fb_size = (self.width as usize * self.height as usize * bpp / 8) + .next_multiple_of(syscall::PAGE_SIZE); let address = unsafe { syscall::physalloc(fb_size) }? as u64; let mapped = unsafe { syscall::physmap( @@ -142,7 +141,8 @@ impl<'a> Display<'a> { assert_eq!(header.ty.get(), CommandTy::RespOkNodata); let rect = GpuRect::new(0, 0, self.width, self.height); - self.flush_resource(ResourceFlush::new(self.resource_id, rect)).await?; + self.flush_resource(ResourceFlush::new(self.resource_id, rect)) + .await?; Ok(()) } } @@ -153,36 +153,42 @@ pub struct Scheme<'a> { config: &'a mut GpuConfig, /// File descriptor allocator. next_id: AtomicUsize, - handles: BTreeMap> + handles: BTreeMap>, } impl<'a> Scheme<'a> { - pub fn new(config: &'a mut GpuConfig, control_queue: Arc>, cursor_queue: Arc>) -> Result { - Ok( - Self { - control_queue, - cursor_queue, - config, - next_id: AtomicUsize::new(0), - handles: BTreeMap::new() - } - ) + pub fn new( + config: &'a mut GpuConfig, + control_queue: Arc>, + cursor_queue: Arc>, + ) -> Result { + Ok(Self { + control_queue, + cursor_queue, + config, + next_id: AtomicUsize::new(0), + handles: BTreeMap::new(), + }) } async fn open_display(&self, id: usize) -> Result, Error> { let mut display_info = self.get_display_info().await?; let displays = &mut display_info.display_info[..self.config.num_scanouts() as usize]; - let display = displays.get_mut (id).ok_or(SysError::new(syscall::ENOENT))?; + let display = displays.get_mut(id).ok_or(SysError::new(syscall::ENOENT))?; - log::info!("virtio-gpu: opening display ({}x{}px)", display.rect.width(), display.rect.height()); - let mut d = Display::new(self.control_queue.clone(), self.cursor_queue.clone(), display, id); - - if id != 0 { - d.map_screen(0).await?; - } + log::info!( + "virtio-gpu: opening display ({}x{}px)", + display.rect.width(), + display.rect.height() + ); - Ok( d) + Ok(Display::new( + self.control_queue.clone(), + self.cursor_queue.clone(), + display, + id, + )) } async fn get_display_info(&self) -> Result, Error> { @@ -207,7 +213,7 @@ impl<'a> Scheme<'a> { impl<'a> SchemeMut for Scheme<'a> { fn open(&mut self, path: &str, _flags: usize, _uid: u32, _gid: u32) -> syscall::Result { dbg!(&path); - + let mut parts = path.split('/'); let mut screen = parts.next().unwrap_or("").split('.'); @@ -217,7 +223,8 @@ impl<'a> SchemeMut for Scheme<'a> { dbg!(&vt_index, &id); let fd = self.next_id.fetch_add(1, Ordering::SeqCst); - let display = futures::executor::block_on(self.open_display(id)).map_err(|_| SysError::new(syscall::ENOENT))?; + let display = futures::executor::block_on(self.open_display(id)) + .map_err(|_| SysError::new(syscall::ENOENT))?; self.handles.insert(fd, display); Ok(fd) diff --git a/virtio-netd/config.toml b/virtio-netd/config.toml new file mode 100644 index 0000000000..93949ce905 --- /dev/null +++ b/virtio-netd/config.toml @@ -0,0 +1,7 @@ +[[drivers]] +name = "virtio-net" +class = 2 +vendor = 6900 +device = 4096 +command = ["virtio-netd"] +use_channel = true