如何在QEMU源代码中添加新设备?

San*_*San 13 linux hardware kernel qemu emulation

qemu使用QOM方法模拟/添加新设备的步骤方法是什么?

DeviceState/BusState和其他属性的变化是什么以及在哪里?

Cir*_*四事件 14

edu 树内教育PCI设备

它很容易理解和记录,所以我建议你研究它.

它暴露了最小的PCI设备,具有基本IO,中断生成和DMA.

我已经编写了一个最小的Linux内核模块+用户态测试来使用它:

最小的PCI设备

我已经将edu最小化到我的QEMU分支上的四分之一:https://github.com/cirosantilli/qemu/blob/22e7e210d6fbe54c35a5ae32450a4419df25a13b/hw/misc/lkmc_pci_min.c没有DMA.

内核驱动程序:https://github.com/cirosantilli/linux-kernel-module-cheat/blob/1cd55ebf53542208f7a614a856066123b93d303d/kernel_module/pci_min.c

我的Buildroot包装器已经将QEMU fork与子模块集成,只需克隆和./run.

ARM平台设备 TYPE_SYS_BUS_DEVICE

SoC-land烘焙硅中的大多数器件而不是PCI,这是一个最小的可运行示例:

带有DTC修改的Linux fork是Buildroot包装器repo的子模块,所以只需克隆和./run -a arm.

树外设备

我询问是否可以在以下位置制作树外设备:如何创建树外QEMU设备?但它看起来不像.


osg*_*sgx 5

http://events.linuxfoundation.org/sites/events/files/slides/kvmforum14-qom_0.pdf 上的“QOM 释经和启示录”2014 演示中有一些示例

创建对象

Object *o = object_new(TYPE_RNG_BACKEND_RANDOM);
object_property_set_str(o, "filename", "/dev/random", NULL);
object_property_set_bool(o, "opened", "true", NULL);
object_property_add_child(container_get("/somewhere"), "my-rng", o, NULL);
object_unref(o);
Run Code Online (Sandbox Code Playgroud)

内部属性

static bool rng_get_opened(Object *obj, Error **errp)
{
    RngBackend *s = RNG_BACKEND(obj);
    return s->opened;
}
static void rng_set_opened(Object *obj, bool value, Error **errp)
{
    RngBackend *s = RNG_BACKEND(obj);
    RngBackendClass *k = RNG_BACKEND_GET_CLASS(s);
    ...
    if (k->opened) {
        k->opened(s, errp)
    }
}
static void rng_backend_init(Object *obj)
{
    object_property_add_bool(obj, "opened",
        rng_get_opened, rng_set_opened, NULL);
}
static const TypeInfo rng_backend_info = {
   .name = TYPE_RNG_BACKEND,
   .parent = TYPE_OBJECT,
   .instance_size = sizeof(RngBackend),
   .instance_init = rng_backend_init,
   .class_size = sizeof(RngBackendClass),
   .abstract = true,
};
Run Code Online (Sandbox Code Playgroud)

(与实际代码比较:http : //code.metager.de/source/xref/qemu/backends/rng.c 和 RNG_BACKEND 的一种实现http://code.metager.de/source/xref/qemu/backends/ rng-random.c )

这两个页面也可能有用: * http://wiki.qemu.org/Features/QOM * http://wiki.qemu.org/QOMConventions

Siro Mugabi 的帖子“基本 QEMU PCI API”:http : //nairobi-embedded.org/001_qemu_pci_device_essentials.html ( http://web.archive.org/web/20151116022950/http://nairobi-embedded.org/ 001_qemu_pci_device_essentials.html ) 有启用 QOM 的 PCI 驱动程序的完整示例。

QEMU 对象模型 (QOM) 提供了一个用于注册用户可创建类型的框架。QOM 将总线、接口、设备等建模为类型。在 QOM 中,用户类型的信息用于创建其ObjectClass实例以及其对象实例。此信息在TypeInfo结构 ( include/qom/object.h) 中指定。例如:

/* hw/misc/pci-testdev.c */

static const TypeInfo pci_testdev_info = {
        .name          = TYPE_PCI_TEST_DEV,
        .parent        = TYPE_PCI_DEVICE,
        .instance_size = sizeof(PCITestDevState),
        .class_init    = pci_testdev_class_init,
};
Run Code Online (Sandbox Code Playgroud)

在哪里:

  • .name 指示用户类型的字符串。
  • .parent 一个字符串,指定从中派生此用户类型的类型。
  • .instance_size类型的对象实例的大小。它的分配将由 QOM 在内部执行。对象将在部分对象实例化中更详细地讨论。
  • .class_init构造函数钩子。该函数将负责初始化 Type 的ObjectClass实例。