使用QOM方法在qemu
中模拟/添加新设备的步骤方法是什么?
关于DeviceState / BusState和其他属性的变化是什么以及在哪里?
答案 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。
我的Buildroot包装器已经将QEMU fork与子模块集成在一起,只需克隆并./run
。
ARM平台设备TYPE_SYS_BUS_DEVICE
SoC-land烘焙芯片中的大多数器件而不是PCI,这是一个最小的可运行示例:
-M versatilepb
:https://github.com/cirosantilli/qemu/blob/144ea94d710c666babd06ed733007377e132ed4a/hw/arm/versatilepb.c#L302使用sysbus_create_simple
,其中需要TYPE_SYS_BUS_DEVICE
类型的设备。versatilepb.c
compatible
匹配内核模块中的platform_driver.name
,并通知内核哪个模块将处理此设备。-dtb
带有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.html(http://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, };
表示用户类型的字符串。- Type的Object实例的
.name
一个字符串,指定此用户类型派生自的类型。.parent
大小。其分配将由QOM在内部执行。将在“对象实例化部分”中更详细地讨论对象。.instance_size
构造函数钩子。此函数将负责初始化Type的.class_init
实例。