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

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

DeviceState / BusState和其他属性的变化和变化在哪里?

Solutions Collecting From Web of "如何在QEMU源代码中添加新设备?"

edu in-tree教育PCI设备

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

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

我已经写了一个最小的Linux内核模块+用户环境测试,以在它:

最小的PCI设备

我甚至进一步减少了四分之一的大小,在我的QEMU叉:edu:

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

我的Buildroot包装已经集成了QEMU分叉与子模块,只是克隆和./run

ARM平台设备TYPE_SYS_BUS_DEVICE

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

  • QEMU前叉:
  • 内核模块: https : //github.com/cirosantilli/linux-kernel-module-cheat/blob/05fa0105eaccf37d6a675f9b2bae833fd78d4270/kernel_module/platform_device.c写入探针上的内存来测试事情,这也会产生一个IRQ。
  • Linux多功能DTS补丁: https : //github.com/cirosantilli/linux/blob/361bb623671a52a36a077a6dd45843389a687a33/arch/arm/boot/dts/versatile-pb.dts#L42
    • 通知内核寄存器和IRQ所在的位置,并匹配QEMU的versatilepb.c中的参数
    • compatible与内核模块中的platform_driver.name匹配,并通知内核哪个模块将处理该设备。
    • 通过-dtb传递给QEMU的固件

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

树外设备

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

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); 

内部属性

 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, }; 

(与实际代码比较: 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发布的“Essential 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实例以及其Object实例。 该信息在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, }; 

哪里:

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