Hansen's ink

Back

QEMU 自定义外设模板#

此模板为开发 QEMU 中的外设提供了指南。它包含了详细的解释和代码注释。


1. 引入必要的头文件#

这些头文件是大多数 QEMU 设备模型所必需的。

#include "qemu/osdep.h"             // OS 兼容层
#include "hw/irq.h"                 // 中断请求 (IRQ) 处理
#include "hw/qdev-properties.h"     // QEMU 设备属性管理
#include "migration/vmstate.h"      // 虚拟机迁移支持
#include "qemu/log.h"               // QEMU 日志功能
#include "qemu/module.h"            // QEMU 模块初始化
c

2. 定义设备状态结构体#

定义一个结构体来保存自定义设备的内部状态。这包括设备所需的寄存器和状态标志。

typedef struct CustomDeviceState {
    SysBusDevice parent_obj;   // 系统总线设备的基础结构
    uint32_t reg1;             // 示例寄存器 1
    uint32_t reg2;             // 示例寄存器 2
    uint64_t tick_offset;      // 时间或时钟偏移
    bool enable;               // 设备启用标志
    QEMUTimer *timer;          // 定时器,用于计划事件
    qemu_irq irq;              // 中断请求
    MemoryRegion iomem;        // 内存映射 I/O 区域
} CustomDeviceState;
c

3. 设备初始化与重置#

  • reset(): 重置设备的内部状态和寄存器。
  • init(): 初始化设备,包括内存和中断连接。

4. 实现读写函数#

这些函数定义了设备如何处理对寄存器的读写请求。


5. 定义 MemoryRegion 操作#

此部分将读写函数绑定到设备的内存区域。

static const MemoryRegionOps custom_device_ops = {
    .read = custom_device_read,    // 绑定读取函数
    .write = custom_device_write,  // 绑定写入函数
    .endianness = DEVICE_NATIVE_ENDIAN,  // 使用本地字节序
};
c

6. 支持虚拟机迁移(可选)#

如果设备需要支持虚拟机迁移,开发者需要定义哪些字段应被保存和恢复。

static const VMStateDescription vmstate_custom_device = {
    .name = "custom_device",       // VM 状态名称
    .version_id = 1,               // 状态版本 ID
    .minimum_version_id = 1,       // 最小兼容版本 ID
    .fields = (VMStateField[]) {
        VMSTATE_UINT32(reg1, CustomDeviceState),  // 保存/恢复 reg1
        VMSTATE_UINT32(reg2, CustomDeviceState),  // 保存/恢复 reg2
        VMSTATE_END_OF_LIST()                     // 状态字段列表结束
    }
};
c

7. 实现并注册设备#

此函数实现设备的逻辑。在这里,我们初始化定时器并连接中断。


通过遵循此模板,开发者可以在 QEMU 中实现支持 MMIO、中断和可选迁移功能的自定义外设。你可以根据具体的设备需求修改此模板。

QEMU 外设建模模板
https://astro-pure.js.org/blog/simulator/qemu-device
Author Hansen W.
Published at January 28, 2025
Comment seems to stuck. Try to refresh?✨