Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Qemu device prototyping

Using QEMU for HW device prototyping and testing: quick walkthrough on how to create a PCI device in QEMU.

  • Login to see the comments

  • Be the first to like this

Qemu device prototyping

  1. 1. QEMU AND DEVICE EMULATION Yan Vugenfirer, yan@daynix.com Daynix Computing LTD
  2. 2. Daynix Computing LTD AGENDA • Introduction to QEMU • Development environment • Examples of existing devices • Adding a new device to QEMU
  3. 3. Daynix Computing LTD WHAT IS QEMU? • Open source project (GPLv2.0+ license) • Machine emulator • Virtualizer • Works together with KVM and Xen
  4. 4. Daynix Computing LTD WHY SHOULDYOU CARE? • Open source • Easy to add additional devices • Emulates different HW architectures • Can be used for SW development long before HW is ready
  5. 5. Daynix Computing LTD GET IT NOW • Project website: http://wiki.qemu.org/Main_Page • Code repository: git clone git://git.qemu- project.org/qemu.git
  6. 6. Daynix Computing LTD PREPARING DEVELOPMENT ENVIRONMENT • Installing the packages on Ubuntu • sudo apt-get update • sudo apt-get install git • sudo apt-get install build-essential • sudo apt-get install pkg-config • sudo apt-get install zlib zlib-dev • sudo apt-get install zlib1g-dev zlib1g • sudo apt-get install glib2.0 • sudo apt-get install libpixman-1-0 • sudo apt-get install libtool • sudo apt-get install dh-autoreconf • sudo apt-get install bridge-utils
  7. 7. Daynix Computing LTD COMPILING QEMU • git clone https://github.com/qemu/qemu.git • cd qemu • git submodule update --init pixman • ./configure --disable-docs —target-list=x86_64-softmmu • make -j 8 • Skip if development version only: make install
  8. 8. Daynix Computing LTD NETWORK CONFIGURATION Linux host Virtual machine QEMU process NIC Linux bridge Physical NIC
  9. 9. Daynix Computing LTD NETWORK CONFIGURATION • On the host edit /etc/network/interfaces # The loopback network interface auto lo iface lo inet loopback # The primary network interface #auto eth0 #iface eth0 inet dhcp iface eth0 inet manual auto br0 iface br0 inet dhcp bridge_ports eth0
  10. 10. Daynix Computing LTD #!/bin/sh switch=br0 /sbin/ifconfig $1 promisc 0.0.0.0 /sbin/brctl addif ${switch} $1 QEMU-IFUP SCRIPT • Create qemu-ifup script with following content
  11. 11. Daynix Computing LTD STORAGE • Download Ubuntu server - http:// www.ubuntu.com/download/server • CreateVM image • qemu-img create -f qcow ubuntu.qcow 8G
  12. 12. Daynix Computing LTD RUNNINGYOU FIRSTVIRTUAL MACHINE ./qemu/x86_64-softmmu/qemu-system-x86_64 -M pc -name Test_VM -smp 2 -m 512M -drive file=/home/qemu/images/ubuntu.qcow,if=ide -usbdevice tablet -boot order=cdn,once=c,menu=on -netdev tap,id=hostnet1,script=/home/qemu/dev/qemu- ifup,ifname=testvm_nic -device e1000,netdev=hostnet1,mac=56:54:46:6b:64:22,bus=pci. 0,id=e1000_01 -cdrom /ISO/ubuntu-14.04.1-server-amd64.iso -vnc :5
  13. 13. Daynix Computing LTD CONNECTINGTOVM • Use theVNC viewer of your choice • ssh after you configured networking
  14. 14. Daynix Computing LTD CODETREE • cd qemu/HW
  15. 15. Daynix Computing LTD QEMU DEVICE MODEL • QDev device model abstraction • Tree of devices connected by buses • Represented by DeviceState and BusState • Devices have common API • Devices have properties • Check include/hw/qdev-core.h for more info
  16. 16. Daynix Computing LTD EXAMPLES OF EXISTING DEVICES • e1000 • qemu/hw/net/e1000.c • virtio family -base code • qemu/hw/virtio/virtio-pci.c, qemu/hw/virtio/virtio-rng.c • virtio-net • qemu/hw/net/virtio-net.c • vmxnet3 • qemu/hw/net/vmxnet3.c
  17. 17. LET’S CODE!
  18. 18. Daynix Computing LTD ADDING NEW DEVICE • Basic source file for the device • Enable the compilation of the device • Command line options • Step by step enhancement of the device
  19. 19. Daynix Computing LTD ADDING NEW DEVICE • In qemu/HW/net/ let’s create devix.c • Add CONFIG_DEVIX_PCI option to default-configs/ pci.mak • Add devix.o to hw/net/Makefile.objs
  20. 20. Daynix Computing LTD COMPILATION diff --git a/default-configs/pci.mak b/default-configs/ pci.mak index 91b1e92..fcf2cf2 100644 --- a/default-configs/pci.mak +++ b/default-configs/pci.mak @@ -30,3 +30,4 @@ CONFIG_IPACK=y CONFIG_WDT_IB6300ESB=y CONFIG_PCI_TESTDEV=y CONFIG_NVME_PCI=y +CONFIG_DEVIX_PCI=y
  21. 21. Daynix Computing LTD COMPILATION diff --git a/hw/net/Makefile.objs b/hw/net/Makefile.objs index ea93293..7800755 100644 --- a/hw/net/Makefile.objs +++ b/hw/net/Makefile.objs @@ -10,6 +10,7 @@ common-obj-$(CONFIG_E1000_PCI) += e1000.o common-obj-$(CONFIG_RTL8139_PCI) += rtl8139.o common-obj-$(CONFIG_VMXNET3_PCI) += vmxnet_tx_pkt.o vmxnet_rx_pkt.o common-obj-$(CONFIG_VMXNET3_PCI) += vmxnet3.o +common-obj-$(CONFIG_DEVIX_PCI) += devix.o
  22. 22. Daynix Computing LTD REGISTERYOUR DEVICETYPE static const TypeInfo devix_info = { .name = TYPE_DEVIX, .parent = TYPE_PCI_DEVICE, .instance_size = sizeof(DEVIXState), .class_init = devix_class_init, .instance_init = devix_instance_init, }; static void devix_register_types(void) { DVX_CBPRN("devix_register_types called..."); type_register_static(&devix_info); } type_init(devix_register_types)
  23. 23. Daynix Computing LTD DEVICETYPE INITIALIZATION static void devix_class_init(ObjectClass *class, void *data) { DeviceClass *dc = DEVICE_CLASS(class); PCIDeviceClass *c = PCI_DEVICE_CLASS(class); c->init = devix_pci_init; c->exit = devix_pci_uninit; c->vendor_id = PCI_VENDOR_ID_DAYNIX; c->device_id = PCI_DEVICE_ID_DAYNIX_DEVIX; c->revision = PCI_DEVICE_ID_DAYNIX_DEVIX_REVISION; c->class_id = PCI_CLASS_NETWORK_ETHERNET; c->subsystem_vendor_id = PCI_VENDOR_ID_DAYNIX; c->subsystem_id = PCI_DEVICE_ID_DAYNIX_DEVIX; c->config_write = devix_write_config; c->config_read = devix_read_config; dc->desc = "Daynix educational device v1"; dc->reset = devix_qdev_reset; dc->vmsd = &vmstate_devix; dc->props = devix_properties; set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); }
  24. 24. Daynix Computing LTD PCI CONFIGURATION SPACE ACCESS CALLBACKS static void uint32_t devix_read_config(PCIDevice *pci_dev, uint32_t address, int len) { return pci_default_read_config(pci_dev, address, len); } static void devix_write_config(PCIDevice *pci_dev, uint32_t address, uint32_t val, int len) { pci_default_write_config(pci_dev, address, val, len); }
  25. 25. • At this point we have PCI device • No BARs or Interrupts… yet
  26. 26. Daynix Computing LTD VM POINT OFVIEW 00:04.0 Ethernet controller: Device 9696:1234 (rev 01) Subsystem: Device 9696:1234 Physical Slot: 4 Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx- Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx- • sudo lspci -vv
  27. 27. Daynix Computing LTD • Register IO and memory space • Configure interrupts • Our own device initializations PCI INITIALIZATION
  28. 28. Daynix Computing LTD MEMORY REGIONS typedef struct { PCIDevice parent_obj; MemoryRegion bar0; MemoryRegion bar1; } DEVIXState; • Add placeholders for memory regions into device state structure
  29. 29. Daynix Computing LTD REGISTER MEMORY REGIONS static int devix_pci_init(PCIDevice *pci_dev) { DeviceState *dev = DEVICE(pci_dev); DEVIXState *s = DEVIX(pci_dev); DVX_CBPRN("Starting init..."); memory_region_init_io(&s->bar0, OBJECT(s), &b0_ops, s, "devix-b0", DEVIX_BAR0_SIZE); pci_register_bar(pci_dev, DEVIX_BAR0_IDX, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->bar0); memory_region_init_io(&s->bar1, OBJECT(s), &b1_ops, s, "devix-b1", DEVIX_BAR1_SIZE); pci_register_bar(pci_dev, DEVIX_BAR1_IDX, PCI_BASE_ADDRESS_SPACE_IO, &s->bar1); devix_net_init(s); return 0; }
  30. 30. Daynix Computing LTD ACCESS CALLBACKS static const MemoryRegionOps b0_ops = { .read = devix_io_bar0_read, .write = devix_io_bar0_write, .endianness = DEVICE_LITTLE_ENDIAN, .impl = { .min_access_size = 4, .max_access_size = 4, }, };
  31. 31. Daynix Computing LTD ACCESS CALLBACKS - WRITE static void devix_io_bar0_write(void *opaque, hwaddr addr, uint64_t val, unsigned size) { DEVIXState *s = opaque; DVX_WRPRN("BAR0 write [%" PRIx64 "] = %" PRIx64 ", size %d", (uint64_t) addr, val, size); } • Size • Address • Value
  32. 32. Daynix Computing LTD ACCESS CALLBACKS - READ static uint64_t devix_io_bar0_read(void *opaque, hwaddr addr, unsigned size) { DEVIXState *s = opaque; uint64_t ret = 0; DVX_CBPRN("Read BAR0 [%" PRIx64 "], size %d",(uint64_t) addr, size); return ret; /* Returns value of the read register */ } • Size • Address • Return the value
  33. 33. Daynix Computing LTD VM POINT OFVIEW 00:04.0 Ethernet controller: Device 9696:1234 (rev 01) Subsystem: Device 9696:1234 Physical Slot: 4 Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx- Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx- Region 0: Memory at febd2000 (32-bit, non- prefetchable) [size=4K] Region 1: I/O ports at c000 [size=512] • sudo lspci -vv
  34. 34. Daynix Computing LTD LEGACY INTERRUPTS • Add interrupt line in pci_init /* Interrupt pin A */ pci_dev->config[PCI_INTERRUPT_PIN] = 0x01;
  35. 35. Daynix Computing LTD LEGACY INTERRUPTS • Call to void pci_irq_assert(PCIDevice *pci_dev) when you want to raise interrupt • Call void pci_irq_deassert(PCIDevice *pci_dev) to de-assert interrupt from one of your registers callback depending on clear interrupt logic
  36. 36. Daynix Computing LTD VM POINT OFVIEW 00:04.0 Ethernet controller: Device 9696:1234 (rev 01) Subsystem: Device 9696:1234 Physical Slot: 4 Control: I/O+ Mem+ BusMaster- SpecCycle- MemWINV- VGASnoop- ParErr- Stepping- SERR+ FastB2B- DisINTx- Status: Cap- 66MHz- UDF- FastB2B- ParErr- DEVSEL=fast >TAbort- <TAbort- <MAbort- >SERR- <PERR- INTx- Interrupt: pin A routed to IRQ 11 Region 0: Memory at febd2000 (32-bit, non- prefetchable) [size=4K] Region 1: I/O ports at c000 [size=512] • sudo lspci -vv
  37. 37. Daynix Computing LTD “DMA” • Actually guest memory access • Synchronous • void cpu_physical_memory_read(hwaddr addr, void *buf, int len) • void cpu_physical_memory_write(hwaddr addr, const void *buf, int len) • iov_xxx functions • Check include/exec/cpu-common.h for more access functions
  38. 38. DEMO
  39. 39. Daynix Computing LTD WHAT’S NEXT? • Add network back end • Add MSI and MSI-x support • Littlebig endian considerations
  40. 40. Q&A
  41. 41. Daynix Computing LTD LINKS • Project website: http://wiki.qemu.org/Main_Page • Code repository: git clone git://git.qemu-project.org/ qemu.git • QEMU new device model - http://www.linux-kvm.org/ wiki/images/f/fe/2010-forum-armbru-qdev.pdf • Daynix - www.daynix.com

×