From a913b41902332245585445c9bb4306d45edc5924 Mon Sep 17 00:00:00 2001 From: sunhaosheng-kylin Date: Fri, 13 Mar 2026 15:19:44 +0800 Subject: [PATCH 1/3] refactor(virtio): remove gpu/input adapters and restructure blk/vsock drivers --- api/kfeat/Cargo.toml | 2 - drivers/kdriver/Cargo.toml | 2 - drivers/kdriver/build.rs | 20 +++-- drivers/kdriver/src/drivers.rs | 12 --- drivers/kdriver/src/macros.rs | 10 --- drivers/kdriver/src/virtio.rs | 32 -------- drivers/virtio/Cargo.toml | 4 - drivers/virtio/src/blk.rs | 41 +++++++--- drivers/virtio/src/gpu.rs | 74 ------------------ drivers/virtio/src/input.rs | 115 ---------------------------- drivers/virtio/src/lib.rs | 12 --- drivers/virtio/src/socket.rs | 132 ++++++++++++++++++--------------- 12 files changed, 115 insertions(+), 341 deletions(-) delete mode 100644 drivers/virtio/src/gpu.rs delete mode 100644 drivers/virtio/src/input.rs diff --git a/api/kfeat/Cargo.toml b/api/kfeat/Cargo.toml index 924bd5dc..4e9c589b 100644 --- a/api/kfeat/Cargo.toml +++ b/api/kfeat/Cargo.toml @@ -63,7 +63,6 @@ vsock = ["net", "kdriver/virtio-socket", "kruntime/vsock", "knet/vsock"] display = [ "alloc", "paging", - "kdriver/virtio-gpu", "dep:fbdevice", "kruntime/display", ] @@ -72,7 +71,6 @@ display = [ input = [ "alloc", "paging", - "kdriver/virtio-input", "dep:inputdev", "kruntime/input", ] diff --git a/drivers/kdriver/Cargo.toml b/drivers/kdriver/Cargo.toml index ca9c056d..2221d134 100644 --- a/drivers/kdriver/Cargo.toml +++ b/drivers/kdriver/Cargo.toml @@ -27,8 +27,6 @@ virtio = ["dep:virtio", "dep:kalloc", "dep:khal"] virtio-blk = ["block", "virtio", "virtio/block"] virtio-net = ["net", "virtio", "virtio/net"] -virtio-gpu = ["display", "virtio", "virtio/gpu"] -virtio-input = ["input", "virtio", "virtio/input"] virtio-socket = ["vsock", "virtio", "virtio/socket"] ramdisk = ["block", "block/ramdisk"] # bcm2835-sdhci = ["block", "block/bcm2835-sdhci"] diff --git a/drivers/kdriver/build.rs b/drivers/kdriver/build.rs index 6c02877c..07e0f35d 100644 --- a/drivers/kdriver/build.rs +++ b/drivers/kdriver/build.rs @@ -4,8 +4,8 @@ const NET_DEV_FEATURES: &[&str] = &["fxmac", "ixgbe", "virtio-net"]; const BLOCK_DEV_FEATURES: &[&str] = &["ahci", "ramdisk", "sdmmc", "bcm2835-sdhci", "virtio-blk"]; -const DISPLAY_DEV_FEATURES: &[&str] = &["virtio-gpu"]; -const INPUT_DEV_FEATURES: &[&str] = &["virtio-input"]; +const DISPLAY_DEV_FEATURES: &[&str] = &[]; +const INPUT_DEV_FEATURES: &[&str] = &[]; const VSOCK_DEV_FEATURES: &[&str] = &["virtio-socket"]; fn make_cfg_values(str_list: &[&str]) -> String { @@ -16,6 +16,14 @@ fn make_cfg_values(str_list: &[&str]) -> String { .join(", ") } +fn make_cfg_values_with_dummy(str_list: &[&str]) -> String { + if str_list.is_empty() { + "\"dummy\"".to_owned() + } else { + format!("{}, \"dummy\"", make_cfg_values(str_list)) + } +} + fn has_feature(feature: &str) -> bool { std::env::var(format!( "CARGO_FEATURE_{}", @@ -77,12 +85,12 @@ fn main() { make_cfg_values(BLOCK_DEV_FEATURES) ); println!( - "cargo::rustc-check-cfg=cfg(display_dev, values({}, \"dummy\"))", - make_cfg_values(DISPLAY_DEV_FEATURES) + "cargo::rustc-check-cfg=cfg(display_dev, values({}))", + make_cfg_values_with_dummy(DISPLAY_DEV_FEATURES) ); println!( - "cargo::rustc-check-cfg=cfg(input_dev, values({}, \"dummy\"))", - make_cfg_values(INPUT_DEV_FEATURES) + "cargo::rustc-check-cfg=cfg(input_dev, values({}))", + make_cfg_values_with_dummy(INPUT_DEV_FEATURES) ); println!( "cargo::rustc-check-cfg=cfg(vsock_dev, values({}, \"dummy\"))", diff --git a/drivers/kdriver/src/drivers.rs b/drivers/kdriver/src/drivers.rs index 50118379..8ed10c5f 100644 --- a/drivers/kdriver/src/drivers.rs +++ b/drivers/kdriver/src/drivers.rs @@ -51,18 +51,6 @@ register_block_driver!( ::Device ); -#[cfg(display_dev = "virtio-gpu")] -register_display_driver!( - ::Driver, - ::Device -); - -#[cfg(input_dev = "virtio-input")] -register_input_driver!( - ::Driver, - ::Device -); - #[cfg(vsock_dev = "virtio-socket")] register_vsock_driver!( ::Driver, diff --git a/drivers/kdriver/src/macros.rs b/drivers/kdriver/src/macros.rs index 7b59193b..461b4a58 100644 --- a/drivers/kdriver/src/macros.rs +++ b/drivers/kdriver/src/macros.rs @@ -67,16 +67,6 @@ macro_rules! for_each_drivers { type $drv_type = ::Driver; $code } - #[cfg(display_dev = "virtio-gpu")] - { - type $drv_type = ::Driver; - $code - } - #[cfg(input_dev = "virtio-input")] - { - type $drv_type = ::Driver; - $code - } #[cfg(vsock_dev = "virtio-socket")] { type $drv_type = ::Driver; diff --git a/drivers/kdriver/src/virtio.rs b/drivers/kdriver/src/virtio.rs index 4f278d59..34b36a81 100644 --- a/drivers/kdriver/src/virtio.rs +++ b/drivers/kdriver/src/virtio.rs @@ -67,36 +67,6 @@ cfg_if! { } } -cfg_if! { - if #[cfg(display_dev = "virtio-gpu")] { - pub struct VirtIoGpu; - - impl VirtIoDevMeta for VirtIoGpu { - const DEVICE_TYPE: DeviceKind = DeviceKind::Display; - type Device = virtio::VirtIoGpuDev; - - fn try_new(transport: VirtIoTransport, _irq: Option) -> DriverResult { - Ok(DeviceEnum::from_display(Self::Device::try_new(transport)?)) - } - } - } -} - -cfg_if! { - if #[cfg(input_dev = "virtio-input")] { - pub struct VirtIoInput; - - impl VirtIoDevMeta for VirtIoInput { - const DEVICE_TYPE: DeviceKind = DeviceKind::Input; - type Device = virtio::VirtIoInputDev; - - fn try_new(transport: VirtIoTransport, _irq: Option) -> DriverResult { - Ok(DeviceEnum::from_input(Self::Device::try_new(transport)?)) - } - } - } -} - cfg_if! { if #[cfg(vsock_dev = "virtio-socket")] { pub struct VirtIoSocket; @@ -150,8 +120,6 @@ impl DriverProbe for VirtIoDriver { match (D::DEVICE_TYPE, dev_info.device_id) { (DeviceKind::Net, 0x1000) | (DeviceKind::Net, 0x1041) => {} (DeviceKind::Block, 0x1001) | (DeviceKind::Block, 0x1042) => {} - (DeviceKind::Input, 0x1052) => {} - (DeviceKind::Display, 0x1050) => {} (DeviceKind::Vsock, 0x1053) => {} _ => return None, } diff --git a/drivers/virtio/Cargo.toml b/drivers/virtio/Cargo.toml index 032f97ee..158e3bca 100644 --- a/drivers/virtio/Cargo.toml +++ b/drivers/virtio/Cargo.toml @@ -14,16 +14,12 @@ categories.workspace = true [features] alloc = ["virtio-drivers/alloc"] block = ["dep:block"] -gpu = ["alloc", "display"] -input = ["alloc", "dep:input"] net = ["alloc", "dep:net"] socket = ["alloc", "dep:vsock"] [dependencies] driver_base = { workspace = true } block = { workspace = true, optional = true } -display = { workspace = true, optional = true } -input = { workspace = true, optional = true } net = { workspace = true, optional = true } vsock = { workspace = true, optional = true } log = { workspace = true } diff --git a/drivers/virtio/src/blk.rs b/drivers/virtio/src/blk.rs index 46982180..b619951f 100644 --- a/drivers/virtio/src/blk.rs +++ b/drivers/virtio/src/blk.rs @@ -5,13 +5,18 @@ //! VirtIO block driver adapter. use block::BlockDriverOps; use driver_base::{DeviceKind, DriverOps, DriverResult}; -use virtio_drivers::{Hal, device::blk::VirtIOBlk as InnerDev, transport::Transport}; +use virtio_drivers::{ + Hal, + device::blk::{SECTOR_SIZE, VirtIOBlk as InnerDev}, + transport::Transport, +}; use crate::as_driver_error; /// The VirtIO block device driver. pub struct VirtIoBlkDev { - inner: InnerDev, + device: InnerDev, + sector_size: usize, } unsafe impl Send for VirtIoBlkDev {} @@ -21,10 +26,28 @@ impl VirtIoBlkDev { /// Creates a new driver instance and initializes the device, or returns /// an error if any step fails. pub fn try_new(transport: T) -> DriverResult { + let device = Self::init_device(transport)?; Ok(Self { - inner: InnerDev::new(transport).map_err(as_driver_error)?, + device, + sector_size: SECTOR_SIZE, }) } + + fn init_device(transport: T) -> DriverResult> { + InnerDev::new(transport).map_err(as_driver_error) + } + + fn read_sector(&mut self, sector: u64, out_buf: &mut [u8]) -> DriverResult { + self.device + .read_blocks(sector as usize, out_buf) + .map_err(as_driver_error) + } + + fn write_sector(&mut self, sector: u64, in_buf: &[u8]) -> DriverResult { + self.device + .write_blocks(sector as usize, in_buf) + .map_err(as_driver_error) + } } impl DriverOps for VirtIoBlkDev { @@ -40,24 +63,20 @@ impl DriverOps for VirtIoBlkDev { impl BlockDriverOps for VirtIoBlkDev { #[inline] fn num_blocks(&self) -> u64 { - self.inner.capacity() + self.device.capacity() } #[inline] fn block_size(&self) -> usize { - virtio_drivers::device::blk::SECTOR_SIZE + self.sector_size } fn read_block(&mut self, block_id: u64, buf: &mut [u8]) -> DriverResult { - self.inner - .read_blocks(block_id as _, buf) - .map_err(as_driver_error) + self.read_sector(block_id, buf) } fn write_block(&mut self, block_id: u64, buf: &[u8]) -> DriverResult { - self.inner - .write_blocks(block_id as _, buf) - .map_err(as_driver_error) + self.write_sector(block_id, buf) } fn flush(&mut self) -> DriverResult { diff --git a/drivers/virtio/src/gpu.rs b/drivers/virtio/src/gpu.rs deleted file mode 100644 index a3cf6609..00000000 --- a/drivers/virtio/src/gpu.rs +++ /dev/null @@ -1,74 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2025 KylinSoft Co., Ltd. -// See LICENSES for license details. - -//! VirtIO GPU driver adapter. -use display::{DisplayDriverOps, DisplayInfo, FrameBuffer}; -use driver_base::{DeviceKind, DriverOps, DriverResult}; -use virtio_drivers::{Hal, device::gpu::VirtIOGpu as InnerDev, transport::Transport}; - -use crate::as_driver_error; - -/// The VirtIO GPU device driver. -pub struct VirtIoGpuDev { - inner: InnerDev, - info: DisplayInfo, -} - -unsafe impl Send for VirtIoGpuDev {} -unsafe impl Sync for VirtIoGpuDev {} - -impl VirtIoGpuDev { - /// Creates a new driver instance and initializes the device, or returns - /// an error if any step fails. - pub fn try_new(transport: T) -> DriverResult { - let mut virtio = InnerDev::new(transport).unwrap(); - - // get framebuffer - let fbuffer = virtio.setup_framebuffer().unwrap(); - let fb_base_vaddr = fbuffer.as_mut_ptr() as usize; - let fb_size = fbuffer.len(); - let (width, height) = virtio.resolution().unwrap(); - let info = DisplayInfo { - width, - height, - fb_base_vaddr, - fb_size, - }; - - Ok(Self { - inner: virtio, - info, - }) - } -} - -impl DriverOps for VirtIoGpuDev { - fn name(&self) -> &str { - "virtio-gpu" - } - - fn device_kind(&self) -> DeviceKind { - DeviceKind::Display - } -} - -impl DisplayDriverOps for VirtIoGpuDev { - fn info(&self) -> DisplayInfo { - self.info - } - - fn fb(&self) -> FrameBuffer<'_> { - unsafe { - FrameBuffer::from_raw_parts_mut(self.info.fb_base_vaddr as *mut u8, self.info.fb_size) - } - } - - fn need_flush(&self) -> bool { - true - } - - fn flush(&mut self) -> DriverResult { - self.inner.flush().map_err(as_driver_error) - } -} diff --git a/drivers/virtio/src/input.rs b/drivers/virtio/src/input.rs deleted file mode 100644 index 92203285..00000000 --- a/drivers/virtio/src/input.rs +++ /dev/null @@ -1,115 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// Copyright 2025 KylinSoft Co., Ltd. -// See LICENSES for license details. - -//! VirtIO input driver adapter. -use alloc::{borrow::ToOwned, string::String}; - -use driver_base::{DeviceKind, DriverError, DriverOps, DriverResult}; -use input::{Event, EventType, InputDeviceId, InputDriverOps}; -use virtio_drivers::{ - Hal, - device::input::{InputConfigSelect, VirtIOInput as InnerDev}, - transport::Transport, -}; - -use crate::as_driver_error; - -/// The VirtIO Input device driver. -pub struct VirtIoInputDev { - inner: InnerDev, - device_id: InputDeviceId, - name: String, -} - -unsafe impl Send for VirtIoInputDev {} -unsafe impl Sync for VirtIoInputDev {} - -impl VirtIoInputDev { - /// Creates a new driver instance and initializes the device, or returns - /// an error if any step fails. - pub fn try_new(transport: T) -> DriverResult { - let mut virtio = InnerDev::new(transport).map_err(as_driver_error)?; - let name = virtio.name().unwrap_or_else(|_| "".to_owned()); - let device_id = virtio.ids().map_err(as_driver_error)?; - let device_id = InputDeviceId { - bus_type: device_id.bustype, - vendor: device_id.vendor, - product: device_id.product, - version: device_id.version, - }; - - Ok(Self { - inner: virtio, - device_id, - name, - }) - } -} - -impl DriverOps for VirtIoInputDev { - fn name(&self) -> &str { - &self.name - } - - fn device_kind(&self) -> DeviceKind { - DeviceKind::Input - } -} - -impl InputDriverOps for VirtIoInputDev { - fn device_id(&self) -> InputDeviceId { - self.device_id - } - - fn physical_location(&self) -> &str { - // TODO: unique physical location - "virtio0/input0" - } - - fn unique_id(&self) -> &str { - // TODO: unique ID - "virtio" - } - - fn get_event_bits(&mut self, ty: EventType, out: &mut [u8]) -> DriverResult { - let read = self - .inner - .query_config_select(InputConfigSelect::EvBits, ty as u8, out); - Ok(read != 0) - } - - fn read_event(&mut self) -> DriverResult { - self.inner.ack_interrupt(); - self.inner - .pop_pending_event() - .map(|e| Event { - event_type: e.event_type, - code: e.code, - value: e.value, - }) - .ok_or(DriverError::WouldBlock) - } -} - -#[cfg(unittest)] -mod tests { - use unittest::{assert, def_test}; - - use super::*; - use crate::mock_virtio::{MockHal, MockTransport}; - - #[def_test] - fn test_virtio_input_init_failure() { - let mut transport = MockTransport::new(); - transport.device_type = virtio_drivers::transport::DeviceType::Input; - let dev = VirtIoInputDev::::try_new(transport); - assert!(dev.is_err()); - } - - #[def_test] - fn test_virtio_input_traits() { - fn assert_send_sync() {} - assert_send_sync::>(); - } -} diff --git a/drivers/virtio/src/lib.rs b/drivers/virtio/src/lib.rs index a9cad768..85b9f361 100644 --- a/drivers/virtio/src/lib.rs +++ b/drivers/virtio/src/lib.rs @@ -26,16 +26,6 @@ mod blk; #[cfg(feature = "block")] pub use self::blk::VirtIoBlkDev; -#[cfg(feature = "gpu")] -mod gpu; -#[cfg(feature = "gpu")] -pub use self::gpu::VirtIoGpuDev; - -#[cfg(feature = "input")] -mod input; -#[cfg(feature = "input")] -pub use self::input::VirtIoInputDev; - #[cfg(feature = "net")] mod net; #[cfg(feature = "net")] @@ -196,8 +186,6 @@ const fn as_device_kind(t: VirtIoDevType) -> Option { match t { Block => Some(DeviceKind::Block), Network => Some(DeviceKind::Net), - GPU => Some(DeviceKind::Display), - Input => Some(DeviceKind::Input), Socket => Some(DeviceKind::Vsock), _ => None, } diff --git a/drivers/virtio/src/socket.rs b/drivers/virtio/src/socket.rs index 7f2a15b2..47b08e6c 100644 --- a/drivers/virtio/src/socket.rs +++ b/drivers/virtio/src/socket.rs @@ -18,6 +18,23 @@ use crate::as_driver_error; /// Default buffer size for VirtIO socket device (32KB). const DEFAULT_BUFFER_SIZE: usize = 32 * 1024; +struct ConnectionArgs { + peer_addr: VsockAddr, + host_port: u32, +} + +impl ConnectionArgs { + fn from_conn_id(conn_id: VsockConnId) -> Self { + Self { + peer_addr: VsockAddr { + cid: conn_id.peer_addr.cid as _, + port: conn_id.peer_addr.port as _, + }, + host_port: conn_id.local_port, + } + } +} + /// The VirtIO socket device driver. pub struct VirtIoSocketDev { inner: InnerDev, @@ -30,11 +47,44 @@ impl VirtIoSocketDev { /// Creates a new driver instance and initializes the device, or returns /// an error if any step fails. pub fn try_new(transport: T) -> DriverResult { - let virtio_socket = VirtIOSocket::::new(transport).map_err(as_driver_error)?; + let virtio_socket = Self::open_socket(transport)?; Ok(Self { inner: InnerDev::new_with_capacity(virtio_socket, DEFAULT_BUFFER_SIZE as u32), }) } + + fn open_socket(transport: T) -> DriverResult> { + VirtIOSocket::::new(transport).map_err(as_driver_error) + } + + fn translate_event(event: VsockEvent) -> VsockDriverEventType { + let connection = VsockConnId { + peer_addr: vsock::VsockAddr { + cid: event.source.cid as _, + port: event.source.port as _, + }, + local_port: event.destination.port, + }; + + match event.event_type { + VsockEventType::ConnectionRequest => { + VsockDriverEventType::ConnectionRequest(connection) + } + VsockEventType::Connected => VsockDriverEventType::Connected(connection), + VsockEventType::Received { length } => { + VsockDriverEventType::Received(connection, length) + } + VsockEventType::Disconnected { .. } => VsockDriverEventType::Disconnected(connection), + VsockEventType::CreditUpdate => VsockDriverEventType::CreditUpdate(connection), + _ => VsockDriverEventType::Unknown, + } + } + + fn refresh_credit(&mut self, connection: &ConnectionArgs) { + let _ = self + .inner + .update_credit(connection.peer_addr, connection.host_port); + } } impl DriverOps for VirtIoSocketDev { @@ -47,16 +97,6 @@ impl DriverOps for VirtIoSocketDev { } } -fn extract_addr_and_port(cid: VsockConnId) -> (VsockAddr, u32) { - ( - VsockAddr { - cid: cid.peer_addr.cid as _, - port: cid.peer_addr.port as _, - }, - cid.local_port, - ) -} - impl VsockDriverOps for VirtIoSocketDev { fn guest_cid(&self) -> u64 { self.inner.guest_cid() @@ -67,88 +107,58 @@ impl VsockDriverOps for VirtIoSocketDev { } fn connect(&mut self, cid: VsockConnId) -> DriverResult<()> { - let (peer_addr, src_port) = extract_addr_and_port(cid); + let connection = ConnectionArgs::from_conn_id(cid); self.inner - .connect(peer_addr, src_port) + .connect(connection.peer_addr, connection.host_port) .map_err(as_driver_error) } fn send(&mut self, cid: VsockConnId, buf: &[u8]) -> DriverResult { - let (peer_addr, src_port) = extract_addr_and_port(cid); - match self.inner.send(peer_addr, src_port, buf) { + let connection = ConnectionArgs::from_conn_id(cid); + match self + .inner + .send(connection.peer_addr, connection.host_port, buf) + { Ok(()) => Ok(buf.len()), Err(e) => Err(as_driver_error(e)), } } fn recv(&mut self, cid: VsockConnId, buf: &mut [u8]) -> DriverResult { - let (peer_addr, src_port) = extract_addr_and_port(cid); + let connection = ConnectionArgs::from_conn_id(cid); let res = self .inner - .recv(peer_addr, src_port, buf) + .recv(connection.peer_addr, connection.host_port, buf) .map_err(as_driver_error); - let _ = self.inner.update_credit(peer_addr, src_port); + self.refresh_credit(&connection); res } fn recv_avail(&mut self, cid: VsockConnId) -> DriverResult { - let (peer_addr, src_port) = extract_addr_and_port(cid); + let connection = ConnectionArgs::from_conn_id(cid); self.inner - .recv_buffer_available_bytes(peer_addr, src_port) + .recv_buffer_available_bytes(connection.peer_addr, connection.host_port) .map_err(as_driver_error) } fn disconnect(&mut self, cid: VsockConnId) -> DriverResult<()> { - let (peer_addr, src_port) = extract_addr_and_port(cid); + let connection = ConnectionArgs::from_conn_id(cid); self.inner - .shutdown(peer_addr, src_port) + .shutdown(connection.peer_addr, connection.host_port) .map_err(as_driver_error) } fn abort(&mut self, cid: VsockConnId) -> DriverResult<()> { - let (peer_addr, src_port) = extract_addr_and_port(cid); + let connection = ConnectionArgs::from_conn_id(cid); self.inner - .force_close(peer_addr, src_port) + .force_close(connection.peer_addr, connection.host_port) .map_err(as_driver_error) } fn poll_event(&mut self) -> DriverResult> { - match self.inner.poll() { - Ok(None) => { - // no event - Ok(None) - } - Ok(Some(event)) => { - // translate event - let result = translate_virtio_event(event, &mut self.inner)?; - Ok(Some(result)) - } - Err(e) => { - // error - Err(as_driver_error(e)) - } - } - } -} - -fn translate_virtio_event( - event: VsockEvent, - _inner: &mut InnerDev, -) -> DriverResult { - let cid = VsockConnId { - peer_addr: vsock::VsockAddr { - cid: event.source.cid as _, - port: event.source.port as _, - }, - local_port: event.destination.port, - }; - - match event.event_type { - VsockEventType::ConnectionRequest => Ok(VsockDriverEventType::ConnectionRequest(cid)), - VsockEventType::Connected => Ok(VsockDriverEventType::Connected(cid)), - VsockEventType::Received { length } => Ok(VsockDriverEventType::Received(cid, length)), - VsockEventType::Disconnected { reason: _ } => Ok(VsockDriverEventType::Disconnected(cid)), - VsockEventType::CreditUpdate => Ok(VsockDriverEventType::CreditUpdate(cid)), - _ => Ok(VsockDriverEventType::Unknown), + let Some(event) = self.inner.poll().map_err(as_driver_error)? else { + return Ok(None); + }; + Ok(Some(Self::translate_event(event))) } } -- Gitee From 9723ed1ec237a15eb589d5041ef0b45a26bb76f7 Mon Sep 17 00:00:00 2001 From: sunhaosheng-kylin Date: Mon, 16 Mar 2026 10:02:01 +0800 Subject: [PATCH 2/3] revert gpu & input delete --- api/kfeat/Cargo.toml | 2 + drivers/kdriver/Cargo.toml | 2 + drivers/kdriver/build.rs | 20 ++---- drivers/kdriver/src/drivers.rs | 12 ++++ drivers/kdriver/src/macros.rs | 10 +++ drivers/kdriver/src/virtio.rs | 32 ++++++++++ drivers/virtio/Cargo.toml | 4 ++ drivers/virtio/src/gpu.rs | 67 +++++++++++++++++++ drivers/virtio/src/input.rs | 113 +++++++++++++++++++++++++++++++++ drivers/virtio/src/lib.rs | 12 ++++ 10 files changed, 260 insertions(+), 14 deletions(-) create mode 100644 drivers/virtio/src/gpu.rs create mode 100644 drivers/virtio/src/input.rs diff --git a/api/kfeat/Cargo.toml b/api/kfeat/Cargo.toml index 4e9c589b..924bd5dc 100644 --- a/api/kfeat/Cargo.toml +++ b/api/kfeat/Cargo.toml @@ -63,6 +63,7 @@ vsock = ["net", "kdriver/virtio-socket", "kruntime/vsock", "knet/vsock"] display = [ "alloc", "paging", + "kdriver/virtio-gpu", "dep:fbdevice", "kruntime/display", ] @@ -71,6 +72,7 @@ display = [ input = [ "alloc", "paging", + "kdriver/virtio-input", "dep:inputdev", "kruntime/input", ] diff --git a/drivers/kdriver/Cargo.toml b/drivers/kdriver/Cargo.toml index 2221d134..ca9c056d 100644 --- a/drivers/kdriver/Cargo.toml +++ b/drivers/kdriver/Cargo.toml @@ -27,6 +27,8 @@ virtio = ["dep:virtio", "dep:kalloc", "dep:khal"] virtio-blk = ["block", "virtio", "virtio/block"] virtio-net = ["net", "virtio", "virtio/net"] +virtio-gpu = ["display", "virtio", "virtio/gpu"] +virtio-input = ["input", "virtio", "virtio/input"] virtio-socket = ["vsock", "virtio", "virtio/socket"] ramdisk = ["block", "block/ramdisk"] # bcm2835-sdhci = ["block", "block/bcm2835-sdhci"] diff --git a/drivers/kdriver/build.rs b/drivers/kdriver/build.rs index 07e0f35d..6c02877c 100644 --- a/drivers/kdriver/build.rs +++ b/drivers/kdriver/build.rs @@ -4,8 +4,8 @@ const NET_DEV_FEATURES: &[&str] = &["fxmac", "ixgbe", "virtio-net"]; const BLOCK_DEV_FEATURES: &[&str] = &["ahci", "ramdisk", "sdmmc", "bcm2835-sdhci", "virtio-blk"]; -const DISPLAY_DEV_FEATURES: &[&str] = &[]; -const INPUT_DEV_FEATURES: &[&str] = &[]; +const DISPLAY_DEV_FEATURES: &[&str] = &["virtio-gpu"]; +const INPUT_DEV_FEATURES: &[&str] = &["virtio-input"]; const VSOCK_DEV_FEATURES: &[&str] = &["virtio-socket"]; fn make_cfg_values(str_list: &[&str]) -> String { @@ -16,14 +16,6 @@ fn make_cfg_values(str_list: &[&str]) -> String { .join(", ") } -fn make_cfg_values_with_dummy(str_list: &[&str]) -> String { - if str_list.is_empty() { - "\"dummy\"".to_owned() - } else { - format!("{}, \"dummy\"", make_cfg_values(str_list)) - } -} - fn has_feature(feature: &str) -> bool { std::env::var(format!( "CARGO_FEATURE_{}", @@ -85,12 +77,12 @@ fn main() { make_cfg_values(BLOCK_DEV_FEATURES) ); println!( - "cargo::rustc-check-cfg=cfg(display_dev, values({}))", - make_cfg_values_with_dummy(DISPLAY_DEV_FEATURES) + "cargo::rustc-check-cfg=cfg(display_dev, values({}, \"dummy\"))", + make_cfg_values(DISPLAY_DEV_FEATURES) ); println!( - "cargo::rustc-check-cfg=cfg(input_dev, values({}))", - make_cfg_values_with_dummy(INPUT_DEV_FEATURES) + "cargo::rustc-check-cfg=cfg(input_dev, values({}, \"dummy\"))", + make_cfg_values(INPUT_DEV_FEATURES) ); println!( "cargo::rustc-check-cfg=cfg(vsock_dev, values({}, \"dummy\"))", diff --git a/drivers/kdriver/src/drivers.rs b/drivers/kdriver/src/drivers.rs index 8ed10c5f..50118379 100644 --- a/drivers/kdriver/src/drivers.rs +++ b/drivers/kdriver/src/drivers.rs @@ -51,6 +51,18 @@ register_block_driver!( ::Device ); +#[cfg(display_dev = "virtio-gpu")] +register_display_driver!( + ::Driver, + ::Device +); + +#[cfg(input_dev = "virtio-input")] +register_input_driver!( + ::Driver, + ::Device +); + #[cfg(vsock_dev = "virtio-socket")] register_vsock_driver!( ::Driver, diff --git a/drivers/kdriver/src/macros.rs b/drivers/kdriver/src/macros.rs index 461b4a58..7b59193b 100644 --- a/drivers/kdriver/src/macros.rs +++ b/drivers/kdriver/src/macros.rs @@ -67,6 +67,16 @@ macro_rules! for_each_drivers { type $drv_type = ::Driver; $code } + #[cfg(display_dev = "virtio-gpu")] + { + type $drv_type = ::Driver; + $code + } + #[cfg(input_dev = "virtio-input")] + { + type $drv_type = ::Driver; + $code + } #[cfg(vsock_dev = "virtio-socket")] { type $drv_type = ::Driver; diff --git a/drivers/kdriver/src/virtio.rs b/drivers/kdriver/src/virtio.rs index 34b36a81..4f278d59 100644 --- a/drivers/kdriver/src/virtio.rs +++ b/drivers/kdriver/src/virtio.rs @@ -67,6 +67,36 @@ cfg_if! { } } +cfg_if! { + if #[cfg(display_dev = "virtio-gpu")] { + pub struct VirtIoGpu; + + impl VirtIoDevMeta for VirtIoGpu { + const DEVICE_TYPE: DeviceKind = DeviceKind::Display; + type Device = virtio::VirtIoGpuDev; + + fn try_new(transport: VirtIoTransport, _irq: Option) -> DriverResult { + Ok(DeviceEnum::from_display(Self::Device::try_new(transport)?)) + } + } + } +} + +cfg_if! { + if #[cfg(input_dev = "virtio-input")] { + pub struct VirtIoInput; + + impl VirtIoDevMeta for VirtIoInput { + const DEVICE_TYPE: DeviceKind = DeviceKind::Input; + type Device = virtio::VirtIoInputDev; + + fn try_new(transport: VirtIoTransport, _irq: Option) -> DriverResult { + Ok(DeviceEnum::from_input(Self::Device::try_new(transport)?)) + } + } + } +} + cfg_if! { if #[cfg(vsock_dev = "virtio-socket")] { pub struct VirtIoSocket; @@ -120,6 +150,8 @@ impl DriverProbe for VirtIoDriver { match (D::DEVICE_TYPE, dev_info.device_id) { (DeviceKind::Net, 0x1000) | (DeviceKind::Net, 0x1041) => {} (DeviceKind::Block, 0x1001) | (DeviceKind::Block, 0x1042) => {} + (DeviceKind::Input, 0x1052) => {} + (DeviceKind::Display, 0x1050) => {} (DeviceKind::Vsock, 0x1053) => {} _ => return None, } diff --git a/drivers/virtio/Cargo.toml b/drivers/virtio/Cargo.toml index 158e3bca..032f97ee 100644 --- a/drivers/virtio/Cargo.toml +++ b/drivers/virtio/Cargo.toml @@ -14,12 +14,16 @@ categories.workspace = true [features] alloc = ["virtio-drivers/alloc"] block = ["dep:block"] +gpu = ["alloc", "display"] +input = ["alloc", "dep:input"] net = ["alloc", "dep:net"] socket = ["alloc", "dep:vsock"] [dependencies] driver_base = { workspace = true } block = { workspace = true, optional = true } +display = { workspace = true, optional = true } +input = { workspace = true, optional = true } net = { workspace = true, optional = true } vsock = { workspace = true, optional = true } log = { workspace = true } diff --git a/drivers/virtio/src/gpu.rs b/drivers/virtio/src/gpu.rs new file mode 100644 index 00000000..fffeb78a --- /dev/null +++ b/drivers/virtio/src/gpu.rs @@ -0,0 +1,67 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2025 KylinSoft Co., Ltd. +// See LICENSES for license details. + +//! VirtIO GPU driver adapter. +use display::{DisplayDriverOps, DisplayInfo, FrameBuffer}; +use driver_base::{DeviceKind, DriverOps, DriverResult}; +use virtio_drivers::{Hal, device::gpu::VirtIOGpu as InnerDev, transport::Transport}; + +/// The VirtIO GPU device driver. +pub struct VirtIoGpuDev { + info: DisplayInfo, + inner: InnerDev, +} + +unsafe impl Send for VirtIoGpuDev {} +unsafe impl Sync for VirtIoGpuDev {} + +impl VirtIoGpuDev { + pub fn try_new(transport: T) -> DriverResult { + let mut device = InnerDev::new(transport).map_err(crate::as_driver_error)?; + let framebuffer = device.setup_framebuffer().map_err(crate::as_driver_error)?; + let fb_base_vaddr = framebuffer.as_mut_ptr() as usize; + let fb_size = framebuffer.len(); + let (width, height) = device.resolution().map_err(crate::as_driver_error)?; + + Ok(Self { + info: DisplayInfo { + width, + height, + fb_base_vaddr, + fb_size, + }, + inner: device, + }) + } +} + +impl DriverOps for VirtIoGpuDev { + fn name(&self) -> &str { + "virtio-gpu" + } + + fn device_kind(&self) -> DeviceKind { + DeviceKind::Display + } +} + +impl DisplayDriverOps for VirtIoGpuDev { + fn info(&self) -> DisplayInfo { + self.info + } + + fn fb(&self) -> FrameBuffer<'_> { + unsafe { + FrameBuffer::from_raw_parts_mut(self.info.fb_base_vaddr as *mut u8, self.info.fb_size) + } + } + + fn need_flush(&self) -> bool { + true + } + + fn flush(&mut self) -> DriverResult { + self.inner.flush().map_err(crate::as_driver_error) + } +} diff --git a/drivers/virtio/src/input.rs b/drivers/virtio/src/input.rs new file mode 100644 index 00000000..f65780ce --- /dev/null +++ b/drivers/virtio/src/input.rs @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: Apache-2.0 +// Copyright 2025 KylinSoft Co., Ltd. +// See LICENSES for license details. + +//! VirtIO input driver adapter. +use alloc::string::String; + +use driver_base::{DeviceKind, DriverError, DriverOps, DriverResult}; +use input::{Event, EventType, InputDeviceId, InputDriverOps}; +use virtio_drivers::{ + Hal, + device::input::{InputConfigSelect, VirtIOInput as InnerDev}, + transport::Transport, +}; + +use crate::as_driver_error; + +/// The VirtIO Input device driver. +pub struct VirtIoInputDev { + inner: InnerDev, + device_id: InputDeviceId, + name: String, +} + +unsafe impl Send for VirtIoInputDev {} +unsafe impl Sync for VirtIoInputDev {} + +impl VirtIoInputDev { + pub fn try_new(transport: T) -> DriverResult { + let mut device = InnerDev::new(transport).map_err(as_driver_error)?; + let name = device.name().unwrap_or_else(|_| "".to_owned()); + let ids = device.ids().map_err(as_driver_error)?; + + Ok(Self { + inner: device, + device_id: InputDeviceId { + bus_type: ids.bustype, + vendor: ids.vendor, + product: ids.product, + version: ids.version, + }, + name, + }) + } + + fn load_event_bits(&mut self, event_type: EventType, out: &mut [u8]) -> DriverResult { + let written = + self.inner + .query_config_select(InputConfigSelect::EvBits, event_type as u8, out); + Ok(written != 0) + } +} + +impl DriverOps for VirtIoInputDev { + fn name(&self) -> &str { + self.name.as_str() + } + + fn device_kind(&self) -> DeviceKind { + DeviceKind::Input + } +} + +impl InputDriverOps for VirtIoInputDev { + fn device_id(&self) -> InputDeviceId { + self.device_id + } + + fn physical_location(&self) -> &str { + "virtio0/input0" + } + + fn unique_id(&self) -> &str { + "virtio" + } + + fn get_event_bits(&mut self, ty: EventType, out: &mut [u8]) -> DriverResult { + self.load_event_bits(ty, out) + } + + fn read_event(&mut self) -> DriverResult { + let Some(event) = self.inner.pop_pending_event() else { + return Err(DriverError::WouldBlock); + }; + Ok(Event { + event_type: event.event_type, + code: event.code, + value: event.value, + }) + } +} + +#[cfg(unittest)] +mod tests { + use unittest::{assert, def_test}; + + use super::*; + use crate::mock_virtio::{MockHal, MockTransport}; + + #[def_test] + fn test_virtio_input_init_failure() { + let mut transport = MockTransport::new(); + transport.device_type = virtio_drivers::transport::DeviceType::Input; + let dev = VirtIoInputDev::::try_new(transport); + assert!(dev.is_err()); + } + + #[def_test] + fn test_virtio_input_traits() { + fn assert_send_sync() {} + assert_send_sync::>(); + } +} diff --git a/drivers/virtio/src/lib.rs b/drivers/virtio/src/lib.rs index 85b9f361..a9cad768 100644 --- a/drivers/virtio/src/lib.rs +++ b/drivers/virtio/src/lib.rs @@ -26,6 +26,16 @@ mod blk; #[cfg(feature = "block")] pub use self::blk::VirtIoBlkDev; +#[cfg(feature = "gpu")] +mod gpu; +#[cfg(feature = "gpu")] +pub use self::gpu::VirtIoGpuDev; + +#[cfg(feature = "input")] +mod input; +#[cfg(feature = "input")] +pub use self::input::VirtIoInputDev; + #[cfg(feature = "net")] mod net; #[cfg(feature = "net")] @@ -186,6 +196,8 @@ const fn as_device_kind(t: VirtIoDevType) -> Option { match t { Block => Some(DeviceKind::Block), Network => Some(DeviceKind::Net), + GPU => Some(DeviceKind::Display), + Input => Some(DeviceKind::Input), Socket => Some(DeviceKind::Vsock), _ => None, } -- Gitee From d7ba4dfba7fc97e605660509f102fcaabb5b6ee7 Mon Sep 17 00:00:00 2001 From: sunhaosheng-kylin Date: Mon, 16 Mar 2026 10:07:30 +0800 Subject: [PATCH 3/3] fix error --- drivers/virtio/src/input.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/virtio/src/input.rs b/drivers/virtio/src/input.rs index f65780ce..09bba2ef 100644 --- a/drivers/virtio/src/input.rs +++ b/drivers/virtio/src/input.rs @@ -28,7 +28,7 @@ unsafe impl Sync for VirtIoInputDev {} impl VirtIoInputDev { pub fn try_new(transport: T) -> DriverResult { let mut device = InnerDev::new(transport).map_err(as_driver_error)?; - let name = device.name().unwrap_or_else(|_| "".to_owned()); + let name = device.name().unwrap_or_else(|_| String::from("")); let ids = device.ids().map_err(as_driver_error)?; Ok(Self { -- Gitee