Come aggiungere un nuovo dispositivo nel codice sorgente QEMU?

Quale potrebbe essere l’approccio graduale per emulare / aggiungere un nuovo dispositivo in qemu usando l’approccio QOM?

Quali e dove potrebbero essere le modifiche rispetto a DeviceState / BusState e ad altre proprietà?

dispositivo PCI educativo edu in-tree

È molto facile da capire e ben documentato, quindi ti consiglio di studiarlo.

Espone un dispositivo PCI minimo, con IO di base, generazione di interrupt e DMA.

Ho scritto un modulo del kernel Linux minimo + test userland per giocarci su:

Dispositivo PCI minimo

Ho ridotto al minimo EDU ancora di più di un quarto delle dimensioni sul mio fork QEMU: https://github.com/cirosantilli/qemu/blob/22e7e210d6fbe54c35a5ae32450a4419df25a13b/hw/misc/lkmc_pci_min.c No DMA.

Driver del kernel: https://github.com/cirosantilli/linux-kernel-module-cheat/blob/1cd55ebf53542208f7a614a856066123b93d303d/kernel_module/pci_min.c

Il mio wrapper Buildroot integra già la fork QEMU con un sottomodulo, solo clone e ./run .

Dispositivo a piattaforma ARM TYPE_SYS_BUS_DEVICE

SoC-land cuoce la maggior parte dei dispositivi nel silicio anziché nel PCI, ecco un esempio eseguibile minimo:

Il fork di Linux con la modifica del DTC è un sottomodulo del repository del wrapper Buildroot, quindi solo clone e ./run -a arm .

Dispositivi fuori dall’arca

Ho chiesto se è ansible realizzare dispositivi fuori dalla struttura in: Come creare dispositivi QEMU fuori dall’area? ma non sembra.

Ci sono alcune parti dell’esempio in “QOM esegesi e apocalisse” presentazione del 2014 su http://events.linuxfoundation.org/sites/events/files/slides/kvmforum14-qom_0.pdf

Creare un object

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

Proprietà interne

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

(confronta con il codice attuale: http://code.metager.de/source/xref/qemu/backends/rng.c e una implementazione di RNG_BACKEND http://code.metager.de/source/xref/qemu/backends/ rng-random.c )

Queste due pagine possono essere anche utili: * http://wiki.qemu.org/Features/QOM * http://wiki.qemu.org/QOMConventions

Il post “Essential QEMU PCI API” di Siro Mugabi: 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 ) ha un esempio completo di driver PCI abilitato per QOM.

QEMU Object Model (QOM) fornisce un framework per la registrazione dei tipi creatable dell’utente. QOM modella bus, interfacce, dispositivi, ecc. Come tipi. In QOM, le informazioni di un utente Type vengono utilizzate per creare l’istanza ObjectClass e l’istanza Object. Questa informazione è specificata in una struttura TypeInfo ( include/qom/object.h ). Per esempio:

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

dove:

  • .name una stringa che indica l’utente Type.
  • .parent una stringa che specifica il tipo da cui deriva questo tipo di utente.
  • .instance_size size dell’istanza dell’object del tipo. La sua allocazione verrà eseguita internamente da QOM. Gli oggetti saranno discussi più dettagliatamente nella sezione Oggetto Instantiation.
  • .class_init il hook del costruttore. Questa funzione sarà responsabile per l’inizializzazione dell’istanza ObjectClass di Type.