SimpleKernel 1.17.0
Loading...
Searching...
No Matches
VirtioDriver Class Reference

统一 VirtIO 驱动 More...

#include <virtio_driver.hpp>

Collaboration diagram for VirtioDriver:
Collaboration graph

Public Types

enum class  DeviceId : uint32_t {
  kNet = 1 , kBlock = 2 , kConsole = 3 , kEntropy = 4 ,
  kGpu = 16 , kInput = 18
}
 VirtIO 设备类型枚举(来自 VirtIO 1.2 规范) More...
 

Public Member Functions

auto Probe (DeviceNode &node) -> Expected< void >
 初始化 VirtIO 设备
 
auto Remove (DeviceNode &node) -> Expected< void >
 卸载所有 VirtIO 块设备
 
auto GetBlkDevice () -> virtio::blk::VirtioBlk<> *
 获取第一个 VirtIO 块设备实例
 
auto GetIrq () const -> uint32_t
 获取第一个块设备的 IRQ 号
 
template<typename CompletionCallback >
auto HandleInterrupt (CompletionCallback &&on_complete) -> void
 处理所有块设备中断
 
构造/析构函数
 VirtioDriver ()=default
 
 VirtioDriver (const VirtioDriver &)=delete
 
 VirtioDriver (VirtioDriver &&)=delete
 
auto operator= (const VirtioDriver &) -> VirtioDriver &=delete
 
auto operator= (VirtioDriver &&) -> VirtioDriver &=delete
 
 ~VirtioDriver ()=default
 

Static Public Member Functions

static auto GetEntry () -> const DriverEntry &
 返回驱动注册入口
 
static auto MatchStatic (DeviceNode &node) -> bool
 硬件检测:验证 VirtIO magic number
 

Static Public Attributes

static constexpr uint32_t kDefaultQueueCount = 1
 
static constexpr uint32_t kDefaultQueueSize = 128
 
static constexpr size_t kMinDmaBufferSize = 32768
 

Private Attributes

std::array< std::optional< virtio::blk::VirtioBlk<> >, kMaxBlkDevicesblk_devices_
 
std::array< etl::unique_ptr< IoBuffer >, kMaxBlkDevicesdma_buffers_
 
std::array< etl::unique_ptr< IoBuffer >, kMaxBlkDevicesslot_buffers_
 
std::array< uint32_t, kMaxBlkDevicesirqs_ {}
 
size_t blk_device_count_ {0}
 
std::array< std::optional< virtio::blk::VirtioBlkVfsAdapter >, kMaxBlkDevicesblk_adapters_
 
size_t blk_adapter_count_ {0}
 

Static Private Attributes

static constexpr MatchEntry kMatchTable []
 
static constexpr size_t kMaxBlkDevices = 4
 

Detailed Description

统一 VirtIO 驱动

匹配所有 virtio,mmio 和 virtio,pci 兼容设备。 Probe() 运行期读取 device_id 寄存器,自动分发到对应设备实现 并注册到 DeviceManager。调用方无需关心具体 VirtIO 设备类型。

Definition at line 32 of file virtio_driver.hpp.

Member Enumeration Documentation

◆ DeviceId

enum class VirtioDriver::DeviceId : uint32_t
strong

VirtIO 设备类型枚举(来自 VirtIO 1.2 规范)

Enumerator
kNet 
kBlock 
kConsole 
kEntropy 
kGpu 
kInput 

Definition at line 35 of file virtio_driver.hpp.

Constructor & Destructor Documentation

◆ VirtioDriver() [1/3]

VirtioDriver::VirtioDriver ( )
default
Here is the caller graph for this function:

◆ VirtioDriver() [2/3]

VirtioDriver::VirtioDriver ( const VirtioDriver )
delete

◆ VirtioDriver() [3/3]

VirtioDriver::VirtioDriver ( VirtioDriver &&  )
delete

◆ ~VirtioDriver()

VirtioDriver::~VirtioDriver ( )
default

Member Function Documentation

◆ GetBlkDevice()

auto VirtioDriver::GetBlkDevice ( ) -> virtio::blk::VirtioBlk<>*
inline

获取第一个 VirtIO 块设备实例

Returns
设备实例指针,若不存在则返回 nullptr

Definition at line 111 of file virtio_driver.hpp.

111 {
112 return (blk_device_count_ > 0 && blk_devices_[0].has_value())
113 ? &blk_devices_[0].value()
114 : nullptr;
115 }
std::array< std::optional< virtio::blk::VirtioBlk<> >, kMaxBlkDevices > blk_devices_
size_t blk_device_count_

◆ GetEntry()

static auto VirtioDriver::GetEntry ( ) -> const DriverEntry&
inlinestatic

返回驱动注册入口

匹配 virtio,mmio 兼容字符串;MatchStatic 检查 VirtIO magic number。

Definition at line 53 of file virtio_driver.hpp.

53 {
54 static const DriverEntry entry{
55 .name = "virtio",
56 .match_table = etl::span<const MatchEntry>(kMatchTable),
57 .match = etl::delegate<bool(
58 DeviceNode&)>::create<&VirtioDriver::MatchStatic>(),
59 .probe = etl::delegate<Expected<void>(DeviceNode&)>::create<
61 etl::singleton<VirtioDriver>::instance()),
62 .remove = etl::delegate<Expected<void>(DeviceNode&)>::create<
64 etl::singleton<VirtioDriver>::instance()),
65 };
66 return entry;
67 }
auto Remove(DeviceNode &node) -> Expected< void >
卸载所有 VirtIO 块设备
VirtioDriver()=default
auto Probe(DeviceNode &node) -> Expected< void >
初始化 VirtIO 设备
static constexpr MatchEntry kMatchTable[]
std::expected< T, Error > Expected
std::expected 别名模板
Definition expected.hpp:365
单个设备的硬件资源描述。
类型擦除的驱动条目 — 每个已注册驱动对应一条。
const char * name
Here is the call graph for this function:
Here is the caller graph for this function:

◆ GetIrq()

auto VirtioDriver::GetIrq ( ) const -> uint32_t
inline

获取第一个块设备的 IRQ 号

Returns
IRQ 号,若无设备则返回 0

Definition at line 121 of file virtio_driver.hpp.

121 {
122 return blk_device_count_ > 0 ? irqs_[0] : 0;
123 }
std::array< uint32_t, kMaxBlkDevices > irqs_

◆ HandleInterrupt()

template<typename CompletionCallback >
auto VirtioDriver::HandleInterrupt ( CompletionCallback &&  on_complete) -> void
inline

处理所有块设备中断

Template Parameters
CompletionCallback完成回调类型
Parameters
on_complete回调函数

Definition at line 131 of file virtio_driver.hpp.

131 {
132 for (size_t i = 0; i < blk_device_count_; ++i) {
133 if (blk_devices_[i].has_value()) {
134 blk_devices_[i].value().HandleInterrupt(
135 static_cast<CompletionCallback&&>(on_complete));
136 }
137 }
138 }

◆ MatchStatic()

auto VirtioDriver::MatchStatic ( DeviceNode node) -> bool
static

硬件检测:验证 VirtIO magic number

只检查 magic number(0x74726976),不检查 device_id—— device_id 的分发在 Probe() 中完成。

Precondition
node.mmio_base != 0
Returns
true 如果设备响应 VirtIO magic

Definition at line 16 of file virtio_driver.cpp.

16 {
17 return node.mmio_base != 0 && node.mmio_size != 0;
18}
uint64_t mmio_base
第一个 MMIO 区域(需要多 BAR 支持时扩展为数组)
size_t mmio_size
Here is the caller graph for this function:

◆ operator=() [1/2]

auto VirtioDriver::operator= ( const VirtioDriver ) -> VirtioDriver &=delete
delete

◆ operator=() [2/2]

auto VirtioDriver::operator= ( VirtioDriver &&  ) -> VirtioDriver &=delete
delete

◆ Probe()

auto VirtioDriver::Probe ( DeviceNode node) -> Expected<void>

初始化 VirtIO 设备

运行期读取 device_id,分发到对应设备实现,创建并注册设备。

Precondition
node.mmio_base != 0,MatchStatic() 已返回 true
Postcondition
设备已注册到 DeviceManager(node.block_device 已填入适配器指针)

Definition at line 20 of file virtio_driver.cpp.

20 {
21 if (node.mmio_size == 0) {
22 klog::Err("VirtioDriver: FDT reg property missing size for node '{}'",
23 node.name);
24 return std::unexpected(Error(ErrorCode::kInvalidArgument));
25 }
26 auto ctx = mmio_helper::Prepare(node, node.mmio_size);
27 if (!ctx) {
28 return std::unexpected(ctx.error());
29 }
30
31 etl::io_port_ro<uint32_t> magic_reg{reinterpret_cast<void*>(ctx->base)};
32 if (magic_reg.read() != virtio::kMmioMagicValue) {
33 return std::unexpected(Error(ErrorCode::kNotSupported));
34 }
35
36 // 读取 device_id
37 etl::io_port_ro<uint32_t> device_id_reg{reinterpret_cast<void*>(
38 ctx->base +
40 const auto device_id = static_cast<DeviceId>(device_id_reg.read());
41
42 switch (device_id) {
43 case DeviceId::kBlock: {
46 "VirtioDriver: blk device pool full, device at {:#x} skipped",
47 ctx->base);
48 return std::unexpected(Error(ErrorCode::kOutOfMemory));
49 }
50 const size_t idx = blk_device_count_;
51
52 // 分配 DMA buffer
53 dma_buffers_[idx] = kstd::make_unique<IoBuffer>(kMinDmaBufferSize);
54 if (!dma_buffers_[idx] || !dma_buffers_[idx]->IsValid() ||
55 dma_buffers_[idx]->GetBuffer().size() < kMinDmaBufferSize) {
56 klog::Err("VirtioDriver: failed to allocate DMA buffer at {:#x}",
57 ctx->base);
58 return std::unexpected(Error(ErrorCode::kOutOfMemory));
59 }
60
61 // Allocate slot DMA buffer
62 auto [slot_size, slot_align] =
64 slot_buffers_[idx] = kstd::make_unique<IoBuffer>(slot_size, slot_align);
65 if (!slot_buffers_[idx] || !slot_buffers_[idx]->IsValid()) {
66 klog::Err("VirtioDriver: failed to allocate slot DMA buffer at {:#x}",
67 ctx->base);
68 dma_buffers_[idx].reset();
69 return std::unexpected(Error(ErrorCode::kOutOfMemory));
70 }
71
72 uint64_t extra_features =
73 static_cast<uint64_t>(virtio::blk::BlkFeatureBit::kSegMax) |
74 static_cast<uint64_t>(virtio::blk::BlkFeatureBit::kSizeMax) |
75 static_cast<uint64_t>(virtio::blk::BlkFeatureBit::kBlkSize) |
76 static_cast<uint64_t>(virtio::blk::BlkFeatureBit::kFlush) |
77 static_cast<uint64_t>(virtio::blk::BlkFeatureBit::kGeometry);
78
79 auto vq_dma = dma_buffers_[idx]->ToDmaRegion();
80 auto slot_dma = slot_buffers_[idx]->ToDmaRegion();
81
83 ctx->base, vq_dma, slot_dma, IdentityVirtToPhys, kDefaultQueueCount,
84 kDefaultQueueSize, extra_features);
85 if (!result.has_value()) {
86 klog::Err("VirtioDriver: VirtioBlk Create failed at {:#x}", ctx->base);
87 dma_buffers_[idx].reset();
88 slot_buffers_[idx].reset();
89 return std::unexpected(Error(result.error().code));
90 }
91
92 blk_devices_[idx].emplace(std::move(*result));
94 irqs_[idx] = node.irq;
95
96 // Register adapter in pool and expose via DeviceNode.
98 const auto adapter_idx = static_cast<uint32_t>(blk_adapter_count_);
99 blk_adapters_[blk_adapter_count_].emplace(&blk_devices_[idx].value(),
100 adapter_idx);
103 } else {
105 "VirtioDriver: blk adapter pool full, device at {:#x} skipped",
106 ctx->base);
107 }
108
111 "VirtioDriver: block device at {:#x}, capacity={} sectors, irq={}",
112 ctx->base, blk_devices_[idx].value().GetCapacity(), irqs_[idx]);
113 return {};
114 }
115
116 default:
117 return std::unexpected(Error(ErrorCode::kNotSupported));
118 }
119}
size_t blk_adapter_count_
DeviceId
VirtIO 设备类型枚举(来自 VirtIO 1.2 规范)
static constexpr size_t kMinDmaBufferSize
static constexpr uint32_t kDefaultQueueSize
static constexpr uint32_t kDefaultQueueCount
static constexpr size_t kMaxBlkDevices
std::array< etl::unique_ptr< IoBuffer >, kMaxBlkDevices > dma_buffers_
std::array< etl::unique_ptr< IoBuffer >, kMaxBlkDevices > slot_buffers_
std::array< std::optional< virtio::blk::VirtioBlkVfsAdapter >, kMaxBlkDevices > blk_adapters_
static auto Create(uint64_t mmio_base, const DmaRegion &vq_dma, const DmaRegion &slot_dma, VirtToPhysFunc virt_to_phys=IdentityVirtToPhys, uint16_t queue_count=1, uint32_t queue_size=128, uint64_t driver_features=0) -> Expected< VirtioBlk >
创建并初始化块设备
static constexpr auto GetRequiredSlotMemSize() -> std::pair< size_t, size_t >
计算 RequestSlot DMA 内存所需字节数
@ kBlock
块设备(磁盘等)
@ kInvalidArgument
@ kNotSupported
不支持的操作(通用,非设备特定)
auto IdentityVirtToPhys(uintptr_t virt) -> uintptr_t
恒等映射:物理地址 == 虚拟地址(早期启动 / 无 MMU 时的默认实现)
Definition io_buffer.hpp:25
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
auto Warn(etl::format_string< Args... > fmt, Args &&... args) -> void
以 WARN 级别记录日志
auto Prepare(const DeviceNode &node, size_t default_size) -> Expected< ProbeContext >
从节点提取 MMIO base/size 并通过 VirtualMemory 映射该区域。
@ kSegMax
设备配置空间中 seg_max 字段有效 (VIRTIO_BLK_F_SEG_MAX)
@ kSizeMax
设备配置空间中 size_max 字段有效 (VIRTIO_BLK_F_SIZE_MAX)
@ kBlkSize
设备配置空间中 blk_size 字段有效 (VIRTIO_BLK_F_BLK_SIZE)
@ kFlush
设备支持缓存刷新命令 (VIRTIO_BLK_F_FLUSH)
@ kGeometry
设备配置空间中 geometry 字段有效 (VIRTIO_BLK_F_GEOMETRY)
static constexpr uint32_t kMmioMagicValue
MMIO 魔数: little-endian "virt" = 0x74726976.
Definition mmio.hpp:31
uint32_t irq
第一条中断线(需要多 IRQ 支持时扩展)
vfs::BlockDevice * block_device
char name[32]
可读的设备名称(来自 FDT 节点名)
DeviceType type
错误类型,用于 std::expected
Definition expected.hpp:343
Here is the call graph for this function:
Here is the caller graph for this function:

◆ Remove()

auto VirtioDriver::Remove ( DeviceNode node) -> Expected<void>
inline

卸载所有 VirtIO 块设备

Parameters
node设备节点
Returns
Expected<void> 成功返回空值

Definition at line 95 of file virtio_driver.hpp.

96 {
97 for (size_t i = 0; i < blk_device_count_; ++i) {
98 blk_devices_[i].reset();
99 dma_buffers_[i].reset();
100 slot_buffers_[i].reset();
101 }
104 return {};
105 }
Here is the caller graph for this function:

Member Data Documentation

◆ blk_adapter_count_

size_t VirtioDriver::blk_adapter_count_ {0}
private

Definition at line 167 of file virtio_driver.hpp.

167{0};

◆ blk_adapters_

std::array<std::optional<virtio::blk::VirtioBlkVfsAdapter>, kMaxBlkDevices> VirtioDriver::blk_adapters_
private

Definition at line 166 of file virtio_driver.hpp.

◆ blk_device_count_

size_t VirtioDriver::blk_device_count_ {0}
private

Definition at line 162 of file virtio_driver.hpp.

162{0};

◆ blk_devices_

std::array<std::optional<virtio::blk::VirtioBlk<> >, kMaxBlkDevices> VirtioDriver::blk_devices_
private

Definition at line 158 of file virtio_driver.hpp.

◆ dma_buffers_

std::array<etl::unique_ptr<IoBuffer>, kMaxBlkDevices> VirtioDriver::dma_buffers_
private

Definition at line 159 of file virtio_driver.hpp.

◆ irqs_

std::array<uint32_t, kMaxBlkDevices> VirtioDriver::irqs_ {}
private

Definition at line 161 of file virtio_driver.hpp.

161{};

◆ kDefaultQueueCount

constexpr uint32_t VirtioDriver::kDefaultQueueCount = 1
staticconstexpr

Definition at line 44 of file virtio_driver.hpp.

◆ kDefaultQueueSize

constexpr uint32_t VirtioDriver::kDefaultQueueSize = 128
staticconstexpr

Definition at line 45 of file virtio_driver.hpp.

◆ kMatchTable

constexpr MatchEntry VirtioDriver::kMatchTable[]
staticconstexprprivate
Initial value:
= {
{BusType::kPlatform, "virtio,mmio"},
}

Definition at line 151 of file virtio_driver.hpp.

151 {
152 {BusType::kPlatform, "virtio,mmio"},
153 };

◆ kMaxBlkDevices

constexpr size_t VirtioDriver::kMaxBlkDevices = 4
staticconstexprprivate

Definition at line 155 of file virtio_driver.hpp.

◆ kMinDmaBufferSize

constexpr size_t VirtioDriver::kMinDmaBufferSize = 32768
staticconstexpr

Definition at line 46 of file virtio_driver.hpp.

◆ slot_buffers_

std::array<etl::unique_ptr<IoBuffer>, kMaxBlkDevices> VirtioDriver::slot_buffers_
private

Definition at line 160 of file virtio_driver.hpp.


The documentation for this class was generated from the following files: