Как добавить новое устройство в исходный код QEMU?
Каким может быть пошаговый подход для эмуляции / добавления нового устройства в qemu
используя подход QOM?
Что и где могут быть изменения в отношении DeviceState/BusState и других свойств?
2 ответа
edu
встроенное учебное PCI-устройство
- https://github.com/qemu/qemu/blob/v2.7.0/hw/misc/edu.c
- https://github.com/qemu/qemu/blob/v2.7.0/docs/specs/edu.txt
Это очень легко понять и хорошо задокументировано, поэтому я рекомендую вам изучить его.
Он предоставляет минимальное PCI-устройство с базовым вводом-выводом, генерацией прерываний и DMA.
Я написал минимальный модуль ядра Linux + пользовательские тесты, чтобы поиграть с ним по адресу:
- https://github.com/cirosantilli/linux-kernel-module-cheat/blob/6788a577c394a2fc512d8f3df0806d84dc09f355/rootfs_overlay/pci.sh
- https://github.com/cirosantilli/linux-kernel-module-cheat/blob/6788a577c394a2fc512d8f3df0806d84dc09f355/kernel_module/pci.c
Минимальное PCI-устройство
Я уменьшил edu до четверти размера моего форка QEMU: https://github.com/cirosantilli/qemu/blob/22e7e210d6fbe54c35a5ae32450a4419df25a13b/hw/misc/lkmc_pci_min.c Нет DMA.
Моя оболочка Buildroot уже включает в себя ветку QEMU с подмодулем, просто клонировать и ./run
,
Устройство на платформе ARMTYPE_SYS_BUS_DEVICE
SoC-land запекает большинство устройств в кремнии вместо PCI, вот минимальный работоспособный пример:
- QEMU fork:
- устройство https://github.com/cirosantilli/qemu/blob/144ea94d710c666babd06ed733007377e132ed4a/hw/misc/lkmc_platform_device.c
- вставить устройство в
-M versatilepb
Использование: https://github.com/cirosantilli/qemu/blob/144ea94d710c666babd06ed733007377e132ed4a/hw/arm/versatilepb.c#L302sysbus_create_simple
, который ожидает устройство типаTYPE_SYS_BUS_DEVICE
,
- модуль ядра: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/05fa0105eaccf37d6a675f9b2bae833fd78d4270/kernel_module/platform_device.c Пишет в память при проверке для проверки, что также генерирует IRQ.
- Патч универсального DTS для Linux: https://github.com/cirosantilli/linux/blob/361bb623671a52a36a077a6dd45843389a687a33/arch/arm/boot/dts/versatile-pb.dts#L42
- Информирует ядро, где расположены регистры и IRQ, и сопоставляет параметры в QEMU.
versatilepb.c
compatible
соответствуетplatform_driver.name
в модуле ядра, и сообщает ядру, какой модуль будет обрабатывать это устройство.- перешел на прошивку QEMU с
-dtb
- Информирует ядро, где расположены регистры и IRQ, и сопоставляет параметры в QEMU.
Разветвление Linux с модификацией DTC является подмодулем репозитория Buildroot, так что просто клонируйте и ./run -a arm
,
Устройства вне дерева
Я спросил, возможно ли сделать устройства из дерева по адресу: Как создавать устройства QEMU из дерева? но это не похоже на это.
Некоторые примеры приведены в презентации 2014 года "Экзегезы и апокалипсис QOM" по адресу http://events.linuxfoundation.org/sites/events/files/slides/kvmforum14-qom_0.pdf
Создание объекта
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
Сообщение "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) содержит полный пример драйвера PCI с поддержкой QOM.
Объектная модель 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, };
где:
.name
строка, которая указывает тип пользователя..parent
строка, которая определяет тип, из которого происходит этот тип пользователя..instance_size
размер экземпляра объекта типа. Его распределение будет выполнено внутри QOM. Объекты будут обсуждаться более подробно в разделе "Реализация объекта"..class_init
крюк конструктора. Эта функция будет отвечать за инициализацию типаObjectClass
пример.