Как добавить новое устройство в исходный код QEMU?

Каким может быть пошаговый подход для эмуляции / добавления нового устройства в qemu используя подход QOM?

Что и где могут быть изменения в отношении DeviceState/BusState и других свойств?

2 ответа

eduвстроенное учебное PCI-устройство

Это очень легко понять и хорошо задокументировано, поэтому я рекомендую вам изучить его.

Он предоставляет минимальное PCI-устройство с базовым вводом-выводом, генерацией прерываний и 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 с подмодулем, просто клонировать и ./run,

Устройство на платформе ARMTYPE_SYS_BUS_DEVICE

SoC-land запекает большинство устройств в кремнии вместо PCI, вот минимальный работоспособный пример:

Разветвление 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 пример.
Другие вопросы по тегам