diff --git a/bsp/qemu-virt64-aarch64/drivers/drv_virtio.c b/bsp/qemu-virt64-aarch64/drivers/drv_virtio.c index 2634da67732..69b4e64ac25 100644 --- a/bsp/qemu-virt64-aarch64/drivers/drv_virtio.c +++ b/bsp/qemu-virt64-aarch64/drivers/drv_virtio.c @@ -74,12 +74,17 @@ int rt_virtio_devices_init(void) mmio_config = (struct virtio_mmio_config *)mmio_base; if (mmio_config->magic != VIRTIO_MAGIC_VALUE || - mmio_config->version != RT_USING_VIRTIO_VERSION || mmio_config->vendor_id != VIRTIO_VENDOR_ID) { continue; } + /* Support both legacy (0x1) and modern (0x2) versions */ + if ((mmio_config->version < 1) || (mmio_config->version > 2)) + { + continue; + } + init_handler = virtio_device_init_handlers[mmio_config->device_id]; if (init_handler != RT_NULL) diff --git a/bsp/qemu-virt64-riscv/driver/drv_virtio.c b/bsp/qemu-virt64-riscv/driver/drv_virtio.c index e1289863b7e..5a6422c3c8e 100644 --- a/bsp/qemu-virt64-riscv/driver/drv_virtio.c +++ b/bsp/qemu-virt64-riscv/driver/drv_virtio.c @@ -80,12 +80,17 @@ int rt_virtio_devices_init(void) mmio_config = (struct virtio_mmio_config *)mmio_base; if (mmio_config->magic != VIRTIO_MAGIC_VALUE || - mmio_config->version != RT_USING_VIRTIO_VERSION || mmio_config->vendor_id != VIRTIO_VENDOR_ID) { continue; } + /* Support both legacy (0x1) and modern (0x2) versions */ + if ((mmio_config->version < 1) || (mmio_config->version > 2)) + { + continue; + } + init_handler = virtio_device_init_handlers[mmio_config->device_id]; if (init_handler != RT_NULL) diff --git a/components/drivers/virtio/Kconfig b/components/drivers/virtio/Kconfig index 8298ff75beb..2baffd23b0d 100644 --- a/components/drivers/virtio/Kconfig +++ b/components/drivers/virtio/Kconfig @@ -5,10 +5,26 @@ menuconfig RT_USING_VIRTIO if RT_USING_VIRTIO choice RT_USING_VIRTIO_VERSION prompt "VirtIO Version" - default RT_USING_VIRTIO10 + default RT_USING_VIRTIO_LEGACY + + config RT_USING_VIRTIO_LEGACY + bool "VirtIO Legacy (v0.95)" + help + Support for VirtIO legacy interface (version 0x1). + This is the older version compatible with most existing QEMU versions. config RT_USING_VIRTIO10 - bool "VirtIO v1.0" + bool "VirtIO Legacy (v1.0 - alias for compatibility)" + help + Alias for RT_USING_VIRTIO_LEGACY for backward compatibility. + Support for VirtIO legacy interface (version 0x1). + + config RT_USING_VIRTIO_MODERN + bool "VirtIO Modern (v1.0+)" + help + Support for VirtIO modern interface (version 0x2). + This version supports VirtIO 1.0, 1.1, and 1.2 specifications. + Requires QEMU 2.4+ or compatible hypervisor. endchoice config RT_USING_VIRTIO_MMIO_ALIGN diff --git a/components/drivers/virtio/README.md b/components/drivers/virtio/README.md new file mode 100644 index 00000000000..f605b7b3a2a --- /dev/null +++ b/components/drivers/virtio/README.md @@ -0,0 +1,101 @@ +# VirtIO Driver for RT-Thread + +[中文](README_zh.md) | English + +## Overview + +The VirtIO driver provides support for virtual I/O devices in RT-Thread, primarily used in virtualized environments like QEMU. + +## Supported Versions + +The driver now supports both legacy and modern VirtIO specifications: + +- **Legacy VirtIO (v0.95)**: Version field 0x1, compatible with older QEMU versions +- **Modern VirtIO (v1.0+)**: Version field 0x2, supports VirtIO 1.0, 1.1, and 1.2 specifications + +## Supported Devices + +- **VirtIO Block (virtio-blk)**: Virtual block device +- **VirtIO Network (virtio-net)**: Virtual network interface +- **VirtIO Console (virtio-console)**: Virtual serial console +- **VirtIO GPU (virtio-gpu)**: Virtual graphics device +- **VirtIO Input (virtio-input)**: Virtual input device (keyboard, mouse, tablet) + +## Configuration + +Use `menuconfig` to configure VirtIO support: + +``` +RT-Thread Components → Device Drivers → Using VirtIO device drivers +``` + +### Version Selection + +Choose between legacy and modern VirtIO: + +``` +RT-Thread Components → Device Drivers → Using VirtIO device drivers → VirtIO Version +``` + +Options: +- **VirtIO Legacy (v0.95)**: For compatibility with older QEMU versions (default) +- **VirtIO Modern (v1.0+)**: For newer QEMU versions (2.4+) with enhanced features + +### Device Selection + +Enable individual VirtIO devices: + +- `RT_USING_VIRTIO_BLK`: VirtIO block device support +- `RT_USING_VIRTIO_NET`: VirtIO network device support +- `RT_USING_VIRTIO_CONSOLE`: VirtIO console device support +- `RT_USING_VIRTIO_GPU`: VirtIO GPU device support +- `RT_USING_VIRTIO_INPUT`: VirtIO input device support + +## Key Differences + +### Legacy VirtIO (v0.95) +- 32-bit feature negotiation +- Single queue descriptor area +- Simple status flags +- Guest page size configuration + +### Modern VirtIO (v1.0+) +- 64-bit feature negotiation (supports more features) +- Separate descriptor/driver/device queue areas +- Enhanced status flow with FEATURES_OK check +- Better memory alignment and atomicity guarantees + +## Migration Guide + +### From Legacy to Modern + +1. Update your QEMU command line to use modern VirtIO devices (most recent QEMU versions default to modern) +2. Change the VirtIO version in menuconfig: + ``` + RT-Thread Components → Device Drivers → Using VirtIO device drivers → VirtIO Version + → Select "VirtIO Modern (v1.0+)" + ``` +3. Rebuild your application +4. The driver will automatically negotiate the VERSION_1 feature with the device + +### Backward Compatibility + +The driver automatically detects the device version from the MMIO config and adapts its behavior accordingly. Both legacy (version 0x1) and modern (version 0x2) devices are supported in the same build. + +## BSP Support + +The following BSPs have been updated to support both legacy and modern VirtIO: + +- `qemu-virt64-riscv`: QEMU RISC-V 64-bit +- `qemu-virt64-aarch64`: QEMU ARM64 (AArch64) + +## Reference Specifications + +- [VirtIO Specification v1.2](https://docs.oasis-open.org/virtio/virtio/v1.2/virtio-v1.2.html) (Latest, 2022) +- [VirtIO Specification v1.1](https://docs.oasis-open.org/virtio/virtio/v1.1/virtio-v1.1.html) (2019) +- [VirtIO Specification v1.0](https://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.html) (2016) +- [OASIS VirtIO TC](https://www.oasis-open.org/committees/virtio/) + +## License + +Apache-2.0 diff --git a/components/drivers/virtio/README_zh.md b/components/drivers/virtio/README_zh.md new file mode 100644 index 00000000000..d8ad9a2b63b --- /dev/null +++ b/components/drivers/virtio/README_zh.md @@ -0,0 +1,101 @@ +# RT-Thread VirtIO 驱动 + +[English](README.md) | 中文 + +## 概述 + +VirtIO 驱动为 RT-Thread 提供虚拟 I/O 设备支持,主要用于 QEMU 等虚拟化环境。 + +## 支持的版本 + +驱动现已支持传统版和现代版 VirtIO 规范: + +- **传统版 VirtIO (v0.95)**:版本字段为 0x1,兼容较旧的 QEMU 版本 +- **现代版 VirtIO (v1.0+)**:版本字段为 0x2,支持 VirtIO 1.0、1.1 和 1.2 规范 + +## 支持的设备 + +- **VirtIO 块设备 (virtio-blk)**:虚拟块设备 +- **VirtIO 网络设备 (virtio-net)**:虚拟网络接口 +- **VirtIO 控制台 (virtio-console)**:虚拟串口控制台 +- **VirtIO GPU (virtio-gpu)**:虚拟图形设备 +- **VirtIO 输入设备 (virtio-input)**:虚拟输入设备(键盘、鼠标、触摸板) + +## 配置 + +使用 `menuconfig` 配置 VirtIO 支持: + +``` +RT-Thread Components → Device Drivers → Using VirtIO device drivers +``` + +### 版本选择 + +在传统版和现代版 VirtIO 之间选择: + +``` +RT-Thread Components → Device Drivers → Using VirtIO device drivers → VirtIO Version +``` + +选项: +- **VirtIO Legacy (v0.95)**:与较旧的 QEMU 版本兼容(默认) +- **VirtIO Modern (v1.0+)**:用于较新的 QEMU 版本(2.4+),具有增强功能 + +### 设备选择 + +启用各个 VirtIO 设备: + +- `RT_USING_VIRTIO_BLK`:VirtIO 块设备支持 +- `RT_USING_VIRTIO_NET`:VirtIO 网络设备支持 +- `RT_USING_VIRTIO_CONSOLE`:VirtIO 控制台支持 +- `RT_USING_VIRTIO_GPU`:VirtIO GPU 支持 +- `RT_USING_VIRTIO_INPUT`:VirtIO 输入设备支持 + +## 主要区别 + +### 传统版 VirtIO (v0.95) +- 32 位特性协商 +- 单一队列描述符区域 +- 简单状态标志 +- 客户机页面大小配置 + +### 现代版 VirtIO (v1.0+) +- 64 位特性协商(支持更多特性) +- 独立的描述符/驱动/设备队列区域 +- 增强的状态流程,带 FEATURES_OK 检查 +- 更好的内存对齐和原子性保证 + +## 迁移指南 + +### 从传统版迁移到现代版 + +1. 更新 QEMU 命令行以使用现代版 VirtIO 设备(最新的 QEMU 版本默认使用现代版) +2. 在 menuconfig 中更改 VirtIO 版本: + ``` + RT-Thread Components → Device Drivers → Using VirtIO device drivers → VirtIO Version + → 选择 "VirtIO Modern (v1.0+)" + ``` +3. 重新构建应用程序 +4. 驱动将自动与设备协商 VERSION_1 特性 + +### 向后兼容性 + +驱动从 MMIO 配置中自动检测设备版本,并相应调整其行为。传统版(版本 0x1)和现代版(版本 0x2)设备在同一构建中都受支持。 + +## BSP 支持 + +以下 BSP 已更新以支持传统版和现代版 VirtIO: + +- `qemu-virt64-riscv`:QEMU RISC-V 64 位 +- `qemu-virt64-aarch64`:QEMU ARM64 (AArch64) + +## 规范参考 + +- [VirtIO 规范 v1.2](https://docs.oasis-open.org/virtio/virtio/v1.2/virtio-v1.2.html)(最新,2022) +- [VirtIO 规范 v1.1](https://docs.oasis-open.org/virtio/virtio/v1.1/virtio-v1.1.html)(2019) +- [VirtIO 规范 v1.0](https://docs.oasis-open.org/virtio/virtio/v1.0/virtio-v1.0.html)(2016) +- [OASIS VirtIO 技术委员会](https://www.oasis-open.org/committees/virtio/) + +## 许可证 + +Apache-2.0 diff --git a/components/drivers/virtio/virtio.c b/components/drivers/virtio/virtio.c index 0ad924e9d70..6f30a2c6aa0 100644 --- a/components/drivers/virtio/virtio.c +++ b/components/drivers/virtio/virtio.c @@ -38,7 +38,27 @@ void virtio_status_driver_ok(struct virtio_device *dev) { _virtio_dev_check(dev); - dev->mmio_config->status |= VIRTIO_STATUS_FEATURES_OK | VIRTIO_STATUS_DRIVER_OK; + if (dev->version == 1) + { + /* Legacy virtio */ + dev->mmio_config->status |= VIRTIO_STATUS_FEATURES_OK | VIRTIO_STATUS_DRIVER_OK; + } + else + { + /* Modern virtio: set FEATURES_OK and verify it */ + dev->mmio_config->status |= VIRTIO_STATUS_FEATURES_OK; + + /* Verify that device accepted the features */ + if (!(dev->mmio_config->status & VIRTIO_STATUS_FEATURES_OK)) + { + /* Device doesn't support our feature subset */ + dev->mmio_config->status |= VIRTIO_STATUS_FAILED; + return; + } + + /* Now set DRIVER_OK */ + dev->mmio_config->status |= VIRTIO_STATUS_DRIVER_OK; + } } void virtio_interrupt_ack(struct virtio_device *dev) @@ -59,7 +79,66 @@ rt_bool_t virtio_has_feature(struct virtio_device *dev, rt_uint32_t feature_bit) { _virtio_dev_check(dev); - return !!(dev->mmio_config->device_features & (1UL << feature_bit)); + if (dev->version == 1) + { + /* Legacy: 32-bit feature bits only */ + return !!(dev->mmio_config->device_features & (1UL << feature_bit)); + } + else + { + /* Modern: Use 64-bit feature access */ + rt_uint64_t features = virtio_get_features(dev); + return !!(features & (1ULL << feature_bit)); + } +} + +rt_uint64_t virtio_get_features(struct virtio_device *dev) +{ + rt_uint64_t features = 0; + + _virtio_dev_check(dev); + + if (dev->version == 1) + { + /* Legacy: only lower 32 bits */ + features = dev->mmio_config->device_features; + } + else + { + /* Modern: read both 32-bit halves */ + dev->mmio_config->device_features_sel = 0; + features = dev->mmio_config->device_features; + + dev->mmio_config->device_features_sel = 1; + features |= ((rt_uint64_t)dev->mmio_config->device_features) << 32; + } + + return features; +} + +void virtio_set_features(struct virtio_device *dev, rt_uint64_t features) +{ + _virtio_dev_check(dev); + + if (dev->version == 1) + { + /* Legacy: only lower 32 bits */ + dev->mmio_config->driver_features = (rt_uint32_t)features; + } + else + { + /* Modern: write both 32-bit halves */ + dev->mmio_config->driver_features_sel = 0; + dev->mmio_config->driver_features = (rt_uint32_t)features; + + dev->mmio_config->driver_features_sel = 1; + dev->mmio_config->driver_features = (rt_uint32_t)(features >> 32); + } +} + +rt_bool_t virtio_has_feature_64(struct virtio_device *dev, rt_uint64_t features, rt_uint32_t feature_bit) +{ + return !!(features & (1ULL << feature_bit)); } rt_err_t virtio_queues_alloc(struct virtio_device *dev, rt_size_t queues_num) @@ -93,6 +172,7 @@ rt_err_t virtio_queue_init(struct virtio_device *dev, rt_uint32_t queue_index, r void *pages; rt_size_t pages_total_size; struct virtq *queue; + rt_uint64_t desc_addr, avail_addr, used_addr; _virtio_dev_check(dev); @@ -123,18 +203,44 @@ rt_err_t virtio_queue_init(struct virtio_device *dev, rt_uint32_t queue_index, r rt_memset(pages, 0, pages_total_size); - dev->mmio_config->guest_page_size = VIRTIO_PAGE_SIZE; + /* Set queue selector */ dev->mmio_config->queue_sel = queue_index; dev->mmio_config->queue_num = ring_size; - dev->mmio_config->queue_align = VIRTIO_PAGE_SIZE; - dev->mmio_config->queue_pfn = VIRTIO_VA2PA(pages) >> VIRTIO_PAGE_SHIFT; + /* Calculate queue area addresses */ queue->num = ring_size; queue->desc = (struct virtq_desc *)((rt_ubase_t)pages); queue->avail = (struct virtq_avail *)(((rt_ubase_t)pages) + VIRTQ_DESC_TOTAL_SIZE(ring_size)); queue->used = (struct virtq_used *)VIRTIO_PAGE_ALIGN( (rt_ubase_t)&queue->avail->ring[ring_size] + VIRTQ_AVAIL_RES_SIZE); + desc_addr = VIRTIO_VA2PA(queue->desc); + avail_addr = VIRTIO_VA2PA(queue->avail); + used_addr = VIRTIO_VA2PA(queue->used); + + if (dev->version == 1) + { + /* Legacy virtio: use queue_pfn */ + dev->mmio_config->guest_page_size = VIRTIO_PAGE_SIZE; + dev->mmio_config->queue_align = VIRTIO_PAGE_SIZE; + dev->mmio_config->queue_pfn = desc_addr >> VIRTIO_PAGE_SHIFT; + } + else + { + /* Modern virtio: use separate descriptor/driver/device registers */ + dev->mmio_config->queue_desc_low = (rt_uint32_t)desc_addr; + dev->mmio_config->queue_desc_high = (rt_uint32_t)(desc_addr >> 32); + + dev->mmio_config->queue_driver_low = (rt_uint32_t)avail_addr; + dev->mmio_config->queue_driver_high = (rt_uint32_t)(avail_addr >> 32); + + dev->mmio_config->queue_device_low = (rt_uint32_t)used_addr; + dev->mmio_config->queue_device_high = (rt_uint32_t)(used_addr >> 32); + + /* Enable the queue */ + dev->mmio_config->queue_ready = 1; + } + queue->used_idx = 0; /* All descriptors start out unused */ @@ -165,7 +271,17 @@ void virtio_queue_destroy(struct virtio_device *dev, rt_uint32_t queue_index) rt_free_align((void *)queue->desc); dev->mmio_config->queue_sel = queue_index; - dev->mmio_config->queue_pfn = RT_NULL; + + if (dev->version == 1) + { + /* Legacy virtio */ + dev->mmio_config->queue_pfn = 0; + } + else + { + /* Modern virtio */ + dev->mmio_config->queue_ready = 0; + } queue->num = 0; queue->desc = RT_NULL; diff --git a/components/drivers/virtio/virtio.h b/components/drivers/virtio/virtio.h index 3807585d826..7064544baa9 100644 --- a/components/drivers/virtio/virtio.h +++ b/components/drivers/virtio/virtio.h @@ -24,8 +24,13 @@ #error "Please set RT_NAME_MAX to at lest 16" #endif -#ifdef RT_USING_VIRTIO10 -#define RT_USING_VIRTIO_VERSION 0x1 +/* VirtIO version configuration */ +#if defined(RT_USING_VIRTIO_LEGACY) || defined(RT_USING_VIRTIO10) +#define RT_USING_VIRTIO_VERSION 0x1 /* Legacy interface */ +#elif defined(RT_USING_VIRTIO_MODERN) +#define RT_USING_VIRTIO_VERSION 0x2 /* Modern interface (1.0+) */ +#else +#define RT_USING_VIRTIO_VERSION 0x1 /* Default to legacy */ #endif #include @@ -111,6 +116,7 @@ enum struct virtio_device { rt_uint32_t irq; + rt_uint32_t version; /* VirtIO version from MMIO config */ struct virtq *queues; rt_size_t queues_num; @@ -136,6 +142,11 @@ void virtio_status_driver_ok(struct virtio_device *dev); void virtio_interrupt_ack(struct virtio_device *dev); rt_bool_t virtio_has_feature(struct virtio_device *dev, rt_uint32_t feature_bit); +/* Modern VirtIO feature negotiation (64-bit features) */ +rt_uint64_t virtio_get_features(struct virtio_device *dev); +void virtio_set_features(struct virtio_device *dev, rt_uint64_t features); +rt_bool_t virtio_has_feature_64(struct virtio_device *dev, rt_uint64_t features, rt_uint32_t feature_bit); + rt_err_t virtio_queues_alloc(struct virtio_device *dev, rt_size_t queues_num); void virtio_queues_free(struct virtio_device *dev); rt_err_t virtio_queue_init(struct virtio_device *dev, rt_uint32_t queue_index, rt_size_t ring_size); diff --git a/components/drivers/virtio/virtio_blk.c b/components/drivers/virtio/virtio_blk.c index 4161e5907be..df4e31fa640 100644 --- a/components/drivers/virtio/virtio_blk.c +++ b/components/drivers/virtio/virtio_blk.c @@ -178,6 +178,7 @@ rt_err_t rt_virtio_blk_init(rt_ubase_t *mmio_base, rt_uint32_t irq) char dev_name[RT_NAME_MAX]; struct virtio_device *virtio_dev; struct virtio_blk_device *virtio_blk_dev; + rt_uint64_t device_features, driver_features; virtio_blk_dev = rt_malloc(sizeof(struct virtio_blk_device)); @@ -189,6 +190,7 @@ rt_err_t rt_virtio_blk_init(rt_ubase_t *mmio_base, rt_uint32_t irq) virtio_dev = &virtio_blk_dev->virtio_dev; virtio_dev->irq = irq; virtio_dev->mmio_base = mmio_base; + virtio_dev->version = virtio_dev->mmio_config->version; virtio_blk_dev->config = (struct virtio_blk_config *)virtio_dev->mmio_config->config; @@ -200,14 +202,23 @@ rt_err_t rt_virtio_blk_init(rt_ubase_t *mmio_base, rt_uint32_t irq) virtio_status_acknowledge_driver(virtio_dev); /* Negotiate features */ - virtio_dev->mmio_config->driver_features = virtio_dev->mmio_config->device_features & ~( - (1 << VIRTIO_BLK_F_RO) | - (1 << VIRTIO_BLK_F_MQ) | - (1 << VIRTIO_BLK_F_SCSI) | - (1 << VIRTIO_BLK_F_CONFIG_WCE) | - (1 << VIRTIO_F_ANY_LAYOUT) | - (1 << VIRTIO_F_RING_EVENT_IDX) | - (1 << VIRTIO_F_RING_INDIRECT_DESC)); + device_features = virtio_get_features(virtio_dev); + driver_features = device_features & ~( + (1ULL << VIRTIO_BLK_F_RO) | + (1ULL << VIRTIO_BLK_F_MQ) | + (1ULL << VIRTIO_BLK_F_SCSI) | + (1ULL << VIRTIO_BLK_F_CONFIG_WCE) | + (1ULL << VIRTIO_F_ANY_LAYOUT) | + (1ULL << VIRTIO_F_RING_EVENT_IDX) | + (1ULL << VIRTIO_F_RING_INDIRECT_DESC)); + + /* For modern virtio, we must support VERSION_1 */ + if (virtio_dev->version == 2) + { + driver_features |= (1ULL << VIRTIO_F_VERSION_1); + } + + virtio_set_features(virtio_dev, driver_features); /* Tell device that feature negotiation is complete and we're completely ready */ virtio_status_driver_ok(virtio_dev); diff --git a/components/drivers/virtio/virtio_console.c b/components/drivers/virtio/virtio_console.c index 7ad171cec37..2ebcd0881bf 100644 --- a/components/drivers/virtio/virtio_console.c +++ b/components/drivers/virtio/virtio_console.c @@ -674,6 +674,7 @@ rt_err_t rt_virtio_console_init(rt_ubase_t *mmio_base, rt_uint32_t irq) char dev_name[RT_NAME_MAX]; struct virtio_device *virtio_dev; struct virtio_console_device *virtio_console_dev; + rt_uint64_t device_features, driver_features; RT_ASSERT(RT_USING_VIRTIO_CONSOLE_PORT_MAX_NR > 0); @@ -687,6 +688,7 @@ rt_err_t rt_virtio_console_init(rt_ubase_t *mmio_base, rt_uint32_t irq) virtio_dev = &virtio_console_dev->virtio_dev; virtio_dev->irq = irq; virtio_dev->mmio_base = mmio_base; + virtio_dev->version = virtio_dev->mmio_config->version; virtio_console_dev->config = (struct virtio_console_config *)virtio_dev->mmio_config->config; @@ -697,9 +699,19 @@ rt_err_t rt_virtio_console_init(rt_ubase_t *mmio_base, rt_uint32_t irq) virtio_reset_device(virtio_dev); virtio_status_acknowledge_driver(virtio_dev); - virtio_dev->mmio_config->driver_features = virtio_dev->mmio_config->device_features & ~( - (1 << VIRTIO_F_RING_EVENT_IDX) | - (1 << VIRTIO_F_RING_INDIRECT_DESC)); + /* Negotiate features */ + device_features = virtio_get_features(virtio_dev); + driver_features = device_features & ~( + (1ULL << VIRTIO_F_RING_EVENT_IDX) | + (1ULL << VIRTIO_F_RING_INDIRECT_DESC)); + + /* For modern virtio, we must support VERSION_1 */ + if (virtio_dev->version == 2) + { + driver_features |= (1ULL << VIRTIO_F_VERSION_1); + } + + virtio_set_features(virtio_dev, driver_features); virtio_status_driver_ok(virtio_dev); diff --git a/components/drivers/virtio/virtio_gpu.c b/components/drivers/virtio/virtio_gpu.c index fa8981e56c4..9c051a50c01 100644 --- a/components/drivers/virtio/virtio_gpu.c +++ b/components/drivers/virtio/virtio_gpu.c @@ -850,6 +850,7 @@ rt_err_t rt_virtio_gpu_init(rt_ubase_t *mmio_base, rt_uint32_t irq) char dev_name[RT_NAME_MAX]; struct virtio_device *virtio_dev; struct virtio_gpu_device *virtio_gpu_dev; + rt_uint64_t device_features, driver_features; virtio_gpu_dev = rt_malloc(sizeof(struct virtio_gpu_device)); @@ -861,6 +862,7 @@ rt_err_t rt_virtio_gpu_init(rt_ubase_t *mmio_base, rt_uint32_t irq) virtio_dev = &virtio_gpu_dev->virtio_dev; virtio_dev->irq = irq; virtio_dev->mmio_base = mmio_base; + virtio_dev->version = virtio_dev->mmio_config->version; virtio_gpu_dev->pmode_id = VIRTIO_GPU_INVALID_PMODE_ID; virtio_gpu_dev->display_resource_id = 0; @@ -877,9 +879,19 @@ rt_err_t rt_virtio_gpu_init(rt_ubase_t *mmio_base, rt_uint32_t irq) virtio_reset_device(virtio_dev); virtio_status_acknowledge_driver(virtio_dev); - virtio_dev->mmio_config->driver_features = virtio_dev->mmio_config->device_features & ~( - (1 << VIRTIO_F_RING_EVENT_IDX) | - (1 << VIRTIO_F_RING_INDIRECT_DESC)); + /* Negotiate features */ + device_features = virtio_get_features(virtio_dev); + driver_features = device_features & ~( + (1ULL << VIRTIO_F_RING_EVENT_IDX) | + (1ULL << VIRTIO_F_RING_INDIRECT_DESC)); + + /* For modern virtio, we must support VERSION_1 */ + if (virtio_dev->version == 2) + { + driver_features |= (1ULL << VIRTIO_F_VERSION_1); + } + + virtio_set_features(virtio_dev, driver_features); virtio_status_driver_ok(virtio_dev); diff --git a/components/drivers/virtio/virtio_input.c b/components/drivers/virtio/virtio_input.c index 564b32bcaf6..916a0fe4736 100644 --- a/components/drivers/virtio/virtio_input.c +++ b/components/drivers/virtio/virtio_input.c @@ -346,6 +346,7 @@ rt_err_t rt_virtio_input_init(rt_ubase_t *mmio_base, rt_uint32_t irq) char dev_name[RT_NAME_MAX]; struct virtio_device *virtio_dev; struct virtio_input_device *virtio_input_dev; + rt_uint64_t device_features, driver_features; virtio_input_dev = rt_malloc(sizeof(struct virtio_input_device)); @@ -357,6 +358,7 @@ rt_err_t rt_virtio_input_init(rt_ubase_t *mmio_base, rt_uint32_t irq) virtio_dev = &virtio_input_dev->virtio_dev; virtio_dev->irq = irq; virtio_dev->mmio_base = mmio_base; + virtio_dev->version = virtio_dev->mmio_config->version; virtio_input_dev->config = (struct virtio_input_config *)virtio_dev->mmio_config->config; virtio_input_dev->bsct_handler = RT_NULL; @@ -368,9 +370,19 @@ rt_err_t rt_virtio_input_init(rt_ubase_t *mmio_base, rt_uint32_t irq) virtio_reset_device(virtio_dev); virtio_status_acknowledge_driver(virtio_dev); - virtio_dev->mmio_config->driver_features = virtio_dev->mmio_config->device_features & ~( - (1 << VIRTIO_F_RING_EVENT_IDX) | - (1 << VIRTIO_F_RING_INDIRECT_DESC)); + /* Negotiate features */ + device_features = virtio_get_features(virtio_dev); + driver_features = device_features & ~( + (1ULL << VIRTIO_F_RING_EVENT_IDX) | + (1ULL << VIRTIO_F_RING_INDIRECT_DESC)); + + /* For modern virtio, we must support VERSION_1 */ + if (virtio_dev->version == 2) + { + driver_features |= (1ULL << VIRTIO_F_VERSION_1); + } + + virtio_set_features(virtio_dev, driver_features); virtio_status_driver_ok(virtio_dev); diff --git a/components/drivers/virtio/virtio_net.c b/components/drivers/virtio/virtio_net.c index d92421b656c..ce40728a920 100644 --- a/components/drivers/virtio/virtio_net.c +++ b/components/drivers/virtio/virtio_net.c @@ -195,6 +195,7 @@ rt_err_t rt_virtio_net_init(rt_ubase_t *mmio_base, rt_uint32_t irq) char dev_name[RT_NAME_MAX]; struct virtio_device *virtio_dev; struct virtio_net_device *virtio_net_dev; + rt_uint64_t device_features, driver_features; virtio_net_dev = rt_malloc(sizeof(struct virtio_net_device)); @@ -206,15 +207,26 @@ rt_err_t rt_virtio_net_init(rt_ubase_t *mmio_base, rt_uint32_t irq) virtio_dev = &virtio_net_dev->virtio_dev; virtio_dev->irq = irq; virtio_dev->mmio_base = mmio_base; + virtio_dev->version = virtio_dev->mmio_config->version; virtio_net_dev->config = (struct virtio_net_config *)virtio_dev->mmio_config->config; virtio_reset_device(virtio_dev); virtio_status_acknowledge_driver(virtio_dev); - virtio_dev->mmio_config->driver_features = virtio_dev->mmio_config->device_features & ~( - (1 << VIRTIO_NET_F_CTRL_VQ) | - (1 << VIRTIO_F_RING_EVENT_IDX)); + /* Negotiate features */ + device_features = virtio_get_features(virtio_dev); + driver_features = device_features & ~( + (1ULL << VIRTIO_NET_F_CTRL_VQ) | + (1ULL << VIRTIO_F_RING_EVENT_IDX)); + + /* For modern virtio, we must support VERSION_1 */ + if (virtio_dev->version == 2) + { + driver_features |= (1ULL << VIRTIO_F_VERSION_1); + } + + virtio_set_features(virtio_dev, driver_features); virtio_status_driver_ok(virtio_dev);