|
SimpleKernel 1.17.0
|
Split Virtqueue 管理类 More...
#include <split.hpp>


Classes | |
| struct | Avail |
| Virtqueue Available Ring. More... | |
| struct | Desc |
| Virtqueue 描述符表条目 More... | |
| struct | Used |
| Virtqueue Used Ring. More... | |
| struct | UsedElem |
| Virtqueue Used Ring 元素 More... | |
Public Types | |
| enum class | DescFlags : uint16_t { kDescFNext = 1 , kDescFWrite = 2 , kDescFIndirect = 4 } |
| Descriptor Flags. More... | |
| enum class | AvailFlags : uint16_t { kAvailFNoInterrupt = 1 } |
| Available Ring Flags. More... | |
| enum class | UsedFlags : uint16_t { kUsedFNoNotify = 1 } |
| Used Ring Flags. More... | |
Public Member Functions | |
| SplitVirtqueue (const DmaRegion &dma, uint16_t queue_size, bool event_idx, size_t used_align=Used::kAlign) | |
| 从预分配的 DMA 缓冲区构造 SplitVirtqueue | |
| auto | IsValid () const -> bool |
| 检查 virtqueue 是否成功初始化 | |
| auto | AllocDesc () -> Expected< uint16_t > |
| 从空闲链表分配一个描述符 | |
| auto | FreeDesc (uint16_t idx) -> Expected< void > |
| 归还描述符到空闲链表 | |
| auto | GetDesc (uint16_t idx) -> Expected< volatile Desc * > |
| 获取描述符的可变引用 | |
| auto | GetDesc (uint16_t idx) const -> Expected< const volatile Desc * > |
| 获取描述符的只读引用 | |
| auto | Submit (uint16_t head) -> void |
| 将描述符链提交到 Available Ring | |
| auto | HasUsed () const -> bool |
| 检查 Used Ring 中是否有已完成的缓冲区 | |
| auto | PopUsed () -> Expected< UsedElem > |
| 从 Used Ring 弹出一个已完成的元素 | |
| auto | SubmitChain (const IoVec *readable, size_t readable_count, const IoVec *writable, size_t writable_count) -> Expected< uint16_t > |
| 提交 Scatter-Gather 描述符链 | |
| auto | FreeChain (uint16_t head) -> Expected< void > |
| 释放整条描述符链 | |
| auto | DescPhys () const -> uint64_t |
| 获取描述符表的物理地址 | |
| auto | AvailPhys () const -> uint64_t |
| 获取 Available Ring 的物理地址 | |
| auto | UsedPhys () const -> uint64_t |
| 获取 Used Ring 的物理地址 | |
| auto | Size () const -> uint16_t |
| 获取队列大小 | |
| auto | NumFree () const -> uint16_t |
| 获取当前空闲描述符数量 | |
| auto | AvailUsedEvent () -> volatile uint16_t * |
| 获取 Available Ring 的 used_event 字段 | |
| auto | AvailUsedEvent () const -> const volatile uint16_t * |
| auto | UsedAvailEvent () -> volatile uint16_t * |
| 获取 Used Ring 的 avail_event 字段 | |
| auto | UsedAvailEvent () const -> const volatile uint16_t * |
| auto | EventIdxEnabled () const -> bool |
| 检查是否启用了 VIRTIO_F_EVENT_IDX 特性 | |
| auto | AvailIdx () const -> uint16_t |
| 获取当前 Available Ring 索引 | |
| auto | LastUsedIdx () const -> uint16_t |
| 获取驱动程序上次处理到的 Used Ring 索引 | |
构造/析构函数 | |
| SplitVirtqueue ()=delete | |
| SplitVirtqueue (const SplitVirtqueue &)=delete | |
| auto | operator= (const SplitVirtqueue &) -> SplitVirtqueue &=delete |
| auto | operator= (SplitVirtqueue &&) -> SplitVirtqueue &=delete |
| SplitVirtqueue (SplitVirtqueue &&other) noexcept | |
| ~SplitVirtqueue ()=default | |
Public Member Functions inherited from virtio::VirtqueueBase | |
| auto | SubmitChainWithBarrier (this auto &&self, const IoVec *readable, size_t readable_count, const IoVec *writable, size_t writable_count) -> Expected< uint16_t > |
| 提交 Scatter-Gather 链并通知设备 | |
| template<typename Callback > | |
| auto | ProcessUsedWithCallback (this auto &&self, Callback &&callback) -> uint32_t |
| 处理已完成的缓冲区并释放描述符链 | |
Static Public Member Functions | |
| static constexpr auto | CalcSize (uint16_t queue_size, bool event_idx=true, size_t used_align=Used::kAlign) -> size_t |
| 计算给定队列大小所需的 DMA 内存字节数 | |
Private Attributes | |
| volatile Desc * | desc_ {nullptr} |
| 描述符表指针(指向 DMA 内存) | |
| volatile Avail * | avail_ {nullptr} |
| Available Ring 指针(指向 DMA 内存) | |
| volatile Used * | used_ {nullptr} |
| Used Ring 指针(指向 DMA 内存) | |
| uint16_t | queue_size_ {0} |
| 队列大小(描述符数量,必须为 2 的幂) | |
| uint16_t | free_head_ {0} |
| 空闲描述符链表头索引 | |
| uint16_t | num_free_ {0} |
| 空闲描述符数量 | |
| uint16_t | last_used_idx_ {0} |
| 上次处理到的 Used Ring 索引(用于 PopUsed) | |
| uint64_t | phys_base_ {0} |
| DMA 内存物理基地址(客户机物理地址) | |
| size_t | desc_offset_ {0} |
| 描述符表在 DMA 内存中的偏移量(字节) | |
| size_t | avail_offset_ {0} |
| Available Ring 在 DMA 内存中的偏移量(字节) | |
| size_t | used_offset_ {0} |
| Used Ring 在 DMA 内存中的偏移量(字节) | |
| bool | event_idx_enabled_ {false} |
| 是否启用 VIRTIO_F_EVENT_IDX 特性 | |
| bool | is_valid_ {false} |
| 初始化是否成功 | |
Additional Inherited Members | |
Protected Member Functions inherited from virtio::VirtqueueBase | |
| VirtqueueBase ()=default | |
| ~VirtqueueBase ()=default | |
| VirtqueueBase (VirtqueueBase &&) noexcept=default | |
| auto | operator= (VirtqueueBase &&) noexcept -> VirtqueueBase &=default |
| VirtqueueBase (const VirtqueueBase &)=delete | |
| auto | operator= (const VirtqueueBase &) -> VirtqueueBase &=delete |
Split Virtqueue 管理类
管理 split virtqueue 的描述符分配/释放、缓冲区提交、已用缓冲区回收。 使用预分配的 DMA 内存,自身不进行任何堆内存分配。
内存布局(在 DMA 缓冲区中连续排列):
|
strong |
Available Ring Flags.
| Enumerator | |
|---|---|
| kAvailFNoInterrupt | 设备应该不发送中断 |
|
strong |
Descriptor Flags.
| Enumerator | |
|---|---|
| kDescFNext | 标记缓冲区通过 next 字段继续 |
| kDescFWrite | 标记缓冲区为设备只写(否则为设备只读) |
| kDescFIndirect | 标记缓冲区包含描述符列表(间接描述符) |
|
strong |
Used Ring Flags.
| Enumerator | |
|---|---|
| kUsedFNoNotify | 驱动不需要通知 |
|
inline |
从预分配的 DMA 缓冲区构造 SplitVirtqueue
| dma | DMA 区域描述符(包含虚拟地址、物理地址和大小, 必须已清零,大小 >= CalcSize()) |
| queue_size | 队列大小(必须为 2 的幂) |
| event_idx | 是否启用 VIRTIO_F_EVENT_IDX 特性 |
| used_align | Used Ring 的对齐要求(modern = 4,legacy MMIO = 4096) |
Definition at line 240 of file split.hpp.

|
delete |
|
delete |
|
inlinenoexcept |
Definition at line 643 of file split.hpp.
|
default |
|
inline |
从空闲链表分配一个描述符
从空闲描述符链表中取出一个描述符,供上层使用。 调用者必须填充描述符的 addr、len、flags 和 next 字段。
|
inline |
获取当前 Available Ring 索引
Definition at line 630 of file split.hpp.
|
inline |
获取 Available Ring 的物理地址
|
inline |
获取 Available Ring 的 used_event 字段
Definition at line 598 of file split.hpp.

|
inline |
|
inlinestaticconstexpr |
计算给定队列大小所需的 DMA 内存字节数
| queue_size | 队列大小(必须为 2 的幂) |
| event_idx | 是否启用 VIRTIO_F_EVENT_IDX 特性 |
| used_align | Used Ring 的对齐要求 |
Definition at line 203 of file split.hpp.

|
inline |
获取描述符表的物理地址
|
inline |
检查是否启用了 VIRTIO_F_EVENT_IDX 特性
|
inline |
释放整条描述符链
从链头开始,沿 next 指针遍历并释放所有描述符,直到遇到 不含 kDescFNext 标志的描述符为止。
典型用法:在 PopUsed() 获取已完成请求的 head 后, 用此方法一次性归还整条链的描述符。
| head | 描述符链头索引 |
Definition at line 530 of file split.hpp.
|
inline |
归还描述符到空闲链表
将不再使用的描述符放回空闲链表,供后续分配使用。 对于描述符链,调用者必须按正确的顺序释放链中的每个描述符。
| idx | 要释放的描述符索引(必须为之前分配的有效索引) |
获取描述符的可变引用
用于设置描述符的 addr、len、flags 和 next 字段。 调用者必须确保索引有效(通过 AllocDesc() 分配)。
| idx | 描述符索引(必须 < queue_size) |
Definition at line 342 of file split.hpp.
|
inline |
检查 Used Ring 中是否有已完成的缓冲区
通过比较驱动程序上次处理的 idx 与设备当前的 idx, 判断是否有新的已处理缓冲区可供回收。
Definition at line 399 of file split.hpp.

|
inline |
|
inline |
|
inline |
|
delete |
|
delete |
从 Used Ring 弹出一个已完成的元素
从 Used Ring 中取出下一个设备已处理完成的缓冲区。 返回的 UsedElem 包含:
Definition at line 417 of file split.hpp.

|
inline |
|
inline |
将描述符链提交到 Available Ring
将描述符链的头部索引放入 Available Ring,使其对设备可见。 调用此方法后,调用者应使用内存屏障确保 idx 更新对设备可见, 然后通过 Transport::NotifyQueue() 通知设备。
| head | 描述符链头部索引(必须为有效的已分配描述符) |
Definition at line 380 of file split.hpp.


|
inline |
提交 Scatter-Gather 描述符链
从空闲链表分配描述符,按顺序组装 readable(设备只读)和 writable(设备可写) 缓冲区为描述符链,自动设置 NEXT 标志串联,并提交到 Available Ring。
描述符链顺序:[readable_0, ..., readable_N, writable_0, ..., writable_M]
调用者在调用此方法后仍需调用内存屏障 + Transport::NotifyQueue() 通知设备。
| readable | 设备只读缓冲区数组(如请求头、写入数据) |
| readable_count | readable 数组中的元素数量 |
| writable | 设备可写缓冲区数组(如读取数据、状态字节) |
| writable_count | writable 数组中的元素数量 |
Definition at line 460 of file split.hpp.

|
inline |
获取 Used Ring 的 avail_event 字段
Definition at line 612 of file split.hpp.

|
inline |
|
inline |
获取 Used Ring 的物理地址
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |
|
private |