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

时间:2015-02-04 06:56:25

标签: linux kernel emulation hardware qemu

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

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

2 个答案:

答案 0 :(得分:11)

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

树外设备

我问是否可以在How to create out-of-tree QEMU devices?处制作树外设备,但它看起来不像。

答案 1 :(得分:4)

2014年“{QOM exegesis and apocalypse”演讲中有一些例子是http://events.linuxfoundation.org/sites/events/files/slides/kvmforum14-qom_0.pdf

  

创建对象

-- You will need to implement this constraint 
-- in the application code or using triggers.
     

内部属性

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

(与实际代码: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.htmlhttp://web.archive.org/web/20151116022950/http://nairobi-embedded.org/001_qemu_pci_device_essentials.html)有完整的QOM启用PCI驱动程序示例。

  

QEMU对象模型(QOM)提供了一个用于注册用户可创建类型的框架。 QOM将总线,接口,设备等作为类型进行建模。在QOM中,用户Type的信息用于创建其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, }; 实例及其Object实例。此信息在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, }; 表示用户类型的字符串。
  •   
  • .name一个字符串,指定此用户类型派生自的类型。
  •   Type的Object实例的
  • .parent大小。其分配将由QOM在内部执行。将在“对象实例化部分”中更详细地讨论对象。
  •   
  • .instance_size构造函数钩子。此函数将负责初始化Type的.class_init实例。
  •