NetBSD Qemu Edu - hpaluch/hpaluch.github.io GitHub Wiki
Goal: try to write both kernel (and partially user-space) driver for QEMU EDU Device (educational virtual device with emulated Interrupt and DMA) for NetBSD Guest.
- Host: openSUSE LEAP 15.6 with LibVirt + KVM (qemu 8.2.10).
- Guest: NetBSD 11 RC1 (snapshot 20260206082425Z).
On host we have to add -device edu to enable virtual EDU Device to NetBSD guest.
- in case of LibVirt we have to follow: https://libvirt.org/drvqemu.html
- use
virsh edit VM_NAMEand: - add on top namespace
xmlns:qemu:<domain type='qemu' xmlns:qemu='http://libvirt.org/schemas/domain/qemu/1.0'> - and at the bottom (right before closing element
</domain>):<qemu:commandline> <qemu:arg value='-device'/> <qemu:arg value='edu,addr=0xa'/> </qemu:commandline>
- note:
addr=0xais address override to avoid conflict on QEMU start (LibVirt will allocate some devices in lower addresses preventing QEMU to start)
Above configuration will create new PCI device with:
- Vendor ID:
0x1234(Yes, that "round" number) - Device ID:
0x11e8
Once you boot NetBSD Guest VM, you should see new PCI device:
(run as root):
$ dmesg -t | grep 1234
vendor 1234 product 11e8 (prehistoric, subclass 0xff, revision 0x10) at pci0 dev 10 function 0 not configured
(Full device list with kernel drivers)
$ pcictl pci0 list -N
000:00:0: Intel 82441FX (PMC) PCI and Memory Controller (host bridge, revision 0x02) [pchb0]
000:01:0: Intel 82371SB (PIIX3) PCI-ISA Bridge (ISA bridge) [pcib0]
000:01:1: Intel 82371SB (PIIX3) IDE Interface (IDE mass storage, interface 0x80) [piixide0]
000:01:3: Intel 82371AB (PIIX4) Power Management Controller (miscellaneous bridge, revision 0x03) [piixpm0]
000:02:0: Red Hat QXL Video (VGA display, revision 0x05) [vga0]
000:03:0: Qumranet Virtio Network (ethernet network) [virtio0]
000:04:0: Intel 82801FB/FR High Definition Audio Controller (mixed mode multimedia, HD Audio 1.0, revision 0x01) [hdaudio0]
000:05:0: Intel 82801I USB UHCI Controller (USB serial bus, UHCI, revision 0x03) [uhci0]
000:05:1: Intel 82801I USB UHCI Controller (USB serial bus, UHCI, revision 0x03) [uhci1]
000:05:2: Intel 82801I USB UHCI Controller (USB serial bus, UHCI, revision 0x03) [uhci2]
000:05:7: Intel 82801I USB EHCI Controller (USB serial bus, EHCI, revision 0x03) [ehci0]
000:06:0: Intel 82801I AHCI SATA Controller w/ 6 ports (SATA mass storage, AHCI 1.0, revision 0x02) [ahcisata0]
000:07:0: Qumranet Virtio Console (miscellaneous communications) [virtio1]
000:08:0: Qumranet Virtio Storage (SCSI mass storage, vendor-specific) [virtio2]
000:09:0: Qumranet Virtio Memory Balloon (prehistoric, subclass 0xff) [virtio3]
000:10:0: vendor 1234 product 11e8 (prehistoric, subclass 0xff, revision 0x10)
(Huh - we are lucky - with 0xa address (10 decimal) - first free address in PCI space...)
$ pcictl pci0 list | grep 1234
000:10:0: vendor 1234 product 11e8 (prehistoric, subclass 0xff, revision 0x10)
(dump most useful information:)
$ pcictl pci0 dump -d 10 | sed -n '/register at 0x10/,/base/p;/ID:/p;/Command register:/,/Interrupt disable:/p'
Vendor ID: 0x1234
Device ID: 0x11e8
Command register: 0x0103
I/O space accesses: on
Memory space accesses: on
Bus mastering: off
Special cycles: off
MWI transactions: off
Palette snooping: off
Parity error checking: off
Address/data stepping: off
System error (SERR): on
Fast back-to-back transactions: off
Interrupt disable: off
Subclass ID: 0xff
Revision ID: 0x10
Base address register at 0x10
type: 32-bit nonprefetchable memory
base: 0xfc000000
Subsystem vendor ID: 0x1af4
Subsystem ID: 0x1100Note:
- we see base address of BAR0 register
0xfc000000, but not its size (we will need it for memory map) - in qemu source we can found:
memory_region_init_io(&edu->mmio, OBJECT(edu), &edu_mmio_ops, edu, "edu-mmio", 1 * MiB);
- so it should be 1 MiB big (0x100000)
- to determine BAR size we have to use this clumsy process (TODO):
- Disable IO and MEM access (Command register)
- Save BAR register value
- Write all 1s to BAR
- Readback - determine size
- Restore BAR value
- Enable IO and MEM access (Command register)
To access PCI from user-space - most useful seems to be:
/usr/xsrc/external/mit/libpciaccess/dist/src/netbsd_pci.c- for kernel level access there are many other examples - best
is to search for
pci_mapreg_map
This work is licensed under a