56
QEMU interface introspection: From hacks to solutions Markus Armbruster <[email protected]> KVM Forum 2015

QEMU interface introspection: From hacks to solutions › images › 7 › ...Armbruster-QEMU_interface_introspe… · to. fd.].. ". > host.],].][,connect=:]

  • Upload
    others

  • View
    1

  • Download
    0

Embed Size (px)

Citation preview

  • QEMU interface introspection:From hacks to solutions

    Markus Armbruster KVM Forum 2015

  • Part IWhat’s the problem?

  • Interfacing with QEMUQEMU provides interfaces

    QMP MonitorCommand line

    to management applications like libvirt

    QEMU evolves rapidly Many interface versions

  • Our command line is big

    In v2.4:139 total options-14 deprecated-2 internal use

    123 supported options

    If I had a coin for each of them. . .0.5

    7kg

  • It’s big: output of -help

    QEMU emulator version 2.3.93, Copyright (c) 2003-2008 Fabrice Bellardusage: upstream-qemu [options] [disk_image]

    ’disk_image’ is a raw hard disk image for IDE hard disk 0

    Standard options:-h or -help display this help and exit-version display version information and exit-machine [type=]name[,prop[=value][,...]]

    selects emulated machine (’-machine help’ for list)property accel=accel1[:accel2[:...]] selects acceleratorsupported accelerators are kvm, xen, tcg (default: tcg)kernel_irqchip=on|off controls accelerated irqchip supportvmport=on|off|auto controls emulation of vmport (default: auto)kvm_shadow_mem=size of KVM shadow MMUdump-guest-core=on|off include guest memory in a core dump (default=on)mem-merge=on|off controls memory merge support (default: on)iommu=on|off controls emulated Intel IOMMU (VT-d) support (default=off)aes-key-wrap=on|off controls support for AES key wrapping (default=on)dea-key-wrap=on|off controls support for DEA key wrapping (default=on)suppress-vmdesc=on|off disables self-describing migration (default=off)

    -cpu cpu select CPU (’-cpu help’ for list)-smp [cpus=]n[,maxcpus=cpus][,cores=cores][,threads=threads][,sockets=sockets]

    set the number of CPUs to ’n’ [default=1]maxcpus= maximum number of total cpus, includingoffline CPUs for hotplug, etccores= number of CPU cores on one socketthreads= number of threads on one CPU coresockets= number of discrete sockets in the system

    -numa node[,mem=size][,cpus=cpu[-cpu]][,nodeid=node]-numa node[,memdev=id][,cpus=cpu[-cpu]][,nodeid=node]-add-fd fd=fd,set=set[,opaque=opaque]

    Add ’fd’ to fd ’set’-set group.id.arg=value

    set parameter for item of type i.e. -set drive.$id.file=/path/to/image

    -global driver.property=value-global driver=driver,property=property,value=value

    set a global default for a driver property-boot [order=drives][,once=drives][,menu=on|off]

    [,splash=sp_name][,splash-time=sp_time][,reboot-timeout=rb_time][,strict=on|off]’drives’: floppy (a), hard disk (c), CD-ROM (d), network (n)’sp_name’: the file’s name that would be passed to bios as logo picture, if menu=on’sp_time’: the period that splash picture last if menu=on, unit is ms’rb_timeout’: the timeout before guest reboot when boot failed, unit is ms

    -m[emory] [size=]megs[,slots=n,maxmem=size]configure guest RAMsize: initial amount of guest memoryslots: number of hotplug slots (default: none)maxmem: maximum amount of guest memory (default: none)

    NOTE: Some architectures might enforce a specific granularity-mem-path FILE provide backing storage for guest RAM-mem-prealloc preallocate guest memory (use with -mem-path)-k language use keyboard layout (for example ’fr’ for French)-audio-help print list of audio drivers and their options-soundhw c1,... enable audio support

    and only specified sound cards (comma separated list)use ’-soundhw help’ to get the list of supported cardsuse ’-soundhw all’ to enable all of them

    -balloon none disable balloon device-balloon virtio[,addr=str]

    enable virtio balloon device (default)-device driver[,prop[=value][,...]]

    add device (based on driver)prop=value,... sets driver propertiesuse ’-device help’ to print all possible driversuse ’-device driver,help’ to print all possible properties

    -name string1[,process=string2][,debug-threads=on|off]set the name of the gueststring1 sets the window title and string2 the process name (on Linux)When debug-threads is enabled, individual threads are given a separate name (on Linux)NOTE: The thread names are for debugging and not a stable API.

    -uuid %08x-%04x-%04x-%04x-%012xspecify machine UUID

    Block device options:-fda/-fdb file use ’file’ as floppy disk 0/1 image-hda/-hdb file use ’file’ as IDE hard disk 0/1 image-hdc/-hdd file use ’file’ as IDE hard disk 2/3 image-cdrom file use ’file’ as IDE cdrom image (cdrom is ide1 master)-drive [file=file][,if=type][,bus=n][,unit=m][,media=d][,index=i]

    [,cyls=c,heads=h,secs=s[,trans=t]][,snapshot=on|off][,cache=writethrough|writeback|none|directsync|unsafe][,format=f][,serial=s][,addr=A][,rerror=ignore|stop|report][,werror=ignore|stop|report|enospc][,id=name][,aio=threads|native][,readonly=on|off][,copy-on-read=on|off][,discard=ignore|unmap][,detect-zeroes=on|off|unmap][[,bps=b]|[[,bps_rd=r][,bps_wr=w]]][[,iops=i]|[[,iops_rd=r][,iops_wr=w]]][[,bps_max=bm]|[[,bps_rd_max=rm][,bps_wr_max=wm]]][[,iops_max=im]|[[,iops_rd_max=irm][,iops_wr_max=iwm]]][[,iops_size=is]][[,group=g]]

    use ’file’ as a drive image-mtdblock file use ’file’ as on-board Flash memory image-sd file use ’file’ as SecureDigital card image-pflash file use ’file’ as a parallel flash image-snapshot write to temporary files instead of disk image files-hdachs c,h,s[,t]

    force hard disk 0 physical geometry and the optional BIOStranslation (t=none or lba) (usually QEMU can guess them)

    -fsdev fsdriver,id=id[,path=path,][security_model={mapped-xattr|mapped-file|passthrough|none}][,writeout=immediate][,readonly][,socket=socket|sock_fd=sock_fd]

    -virtfs local,path=path,mount_tag=tag,security_model=[mapped-xattr|mapped-file|passthrough|none][,writeout=immediate][,readonly][,socket=socket|sock_fd=sock_fd]

    -virtfs_synth Create synthetic file system image

    USB options:-usb enable the USB driver (will be the default soon)-usbdevice name add the host or guest USB device ’name’

    Display options:-display sdl[,frame=on|off][,alt_grab=on|off][,ctrl_grab=on|off]

    [,window_close=on|off]|curses|none|gtk[,grab_on_hover=on|off]|vnc=[,]

    select display type-nographic disable graphical output and redirect serial I/Os to console-curses use a curses/ncurses interface instead of SDL-no-frame open SDL window without a frame and window decorations

    -alt-grab use Ctrl-Alt-Shift to grab mouse (instead of Ctrl-Alt)-ctrl-grab use Right-Ctrl to grab mouse (instead of Ctrl-Alt)-no-quit disable SDL window close capability-sdl enable SDL-spice [port=port][,tls-port=secured-port][,x509-dir=]

    [,x509-key-file=][,x509-key-password=][,x509-cert-file=][,x509-cacert-file=][,x509-dh-key-file=][,addr=addr][,ipv4|ipv6|unix][,tls-ciphers=][,tls-channel=[main|display|cursor|inputs|record|playback]][,plaintext-channel=[main|display|cursor|inputs|record|playback]][,sasl][,password=][,disable-ticketing][,image-compression=[auto_glz|auto_lz|quic|glz|lz|off]][,jpeg-wan-compression=[auto|never|always]][,zlib-glz-wan-compression=[auto|never|always]][,streaming-video=[off|all|filter]][,disable-copy-paste][,disable-agent-file-xfer][,agent-mouse=[on|off]][,playback-compression=[on|off]][,seamless-migration=[on|off]]

    enable spiceat least one of {port, tls-port} is mandatory

    -portrait rotate graphical output 90 deg left (only PXA LCD)-rotate rotate graphical output some deg left (only PXA LCD)-vga [std|cirrus|vmware|qxl|xenfb|tcx|cg3|virtio|none]

    select video card type-full-screen start in full screen-vnc display start a VNC server on display

    i386 target only:-win2k-hack use it when installing Windows 2000 to avoid a disk full bug-no-fd-bootchk disable boot signature checking for floppy disks-no-acpi disable ACPI-no-hpet disable HPET-acpitable [sig=str][,rev=n][,oem_id=str][,oem_table_id=str][,oem_rev=n]

    [,asl_compiler_id=str][,asl_compiler_rev=n][,{data|file}=file1[:file2]...]ACPI table description

    -smbios file=binaryload SMBIOS entry from binary file

    -smbios type=0[,vendor=str][,version=str][,date=str][,release=%d.%d][,uefi=on|off]

    specify SMBIOS type 0 fields-smbios type=1[,manufacturer=str][,product=str][,version=str][,serial=str]

    [,uuid=uuid][,sku=str][,family=str]specify SMBIOS type 1 fields

    -smbios type=2[,manufacturer=str][,product=str][,version=str][,serial=str][,asset=str][,location=str]

    specify SMBIOS type 2 fields-smbios type=3[,manufacturer=str][,version=str][,serial=str][,asset=str]

    [,sku=str]specify SMBIOS type 3 fields

    -smbios type=4[,sock_pfx=str][,manufacturer=str][,version=str][,serial=str][,asset=str][,part=str]

    specify SMBIOS type 4 fields-smbios type=17[,loc_pfx=str][,bank=str][,manufacturer=str][,serial=str]

    [,asset=str][,part=str][,speed=%d]specify SMBIOS type 17 fields

    Network options:-netdev user,id=str[,net=addr[/mask]][,host=addr][,restrict=on|off]

    [,hostname=host][,dhcpstart=addr][,dns=addr][,dnssearch=domain][,tftp=dir][,bootfile=f][,hostfwd=rule][,guestfwd=rule][,smb=dir[,smbserver=addr]]

    configure a user mode network backend with ID ’str’,its DHCP server and optional services

    -netdev tap,id=str[,fd=h][,fds=x:y:...:z][,ifname=name][,script=file][,downscript=dfile][,helper=helper][,sndbuf=nbytes][,vnet_hdr=on|off][,vhost=on|off][,vhostfd=h][,vhostfds=x:y:...:z][,vhostforce=on|off][,queues=n]

    configure a host TAP network backend with ID ’str’use network scripts ’file’ (default=/etc/qemu-ifup)to configure it and ’dfile’ (default=/etc/qemu-ifdown)to deconfigure ituse ’[down]script=no’ to disable script executionuse network helper ’helper’ (default=/usr/local/libexec/qemu-bridge-helper) toconfigure ituse ’fd=h’ to connect to an already opened TAP interfaceuse ’fds=x:y:...:z’ to connect to already opened multiqueue capable TAP interfacesuse ’sndbuf=nbytes’ to limit the size of the send buffer (thedefault is disabled ’sndbuf=0’ to enable flow control set ’sndbuf=1048576’)use vnet_hdr=off to avoid enabling the IFF_VNET_HDR tap flaguse vnet_hdr=on to make the lack of IFF_VNET_HDR support an error conditionuse vhost=on to enable experimental in kernel accelerator

    (only has effect for virtio guests which use MSIX)use vhostforce=on to force vhost on for non-MSIX virtio guestsuse ’vhostfd=h’ to connect to an already opened vhost net deviceuse ’vhostfds=x:y:...:z to connect to multiple already opened vhost net devicesuse ’queues=n’ to specify the number of queues to be created for multiqueue TAP

    -netdev bridge,id=str[,br=bridge][,helper=helper]configure a host TAP network backend with ID ’str’ that isconnected to a bridge (default=br0)using the program ’helper (default=/usr/local/libexec/qemu-bridge-helper)

    -netdev l2tpv3,id=str,src=srcaddr,dst=dstaddr[,srcport=srcport][,dstport=dstport][,rxsession=rxsession],txsession=txsession[,ipv6=on/off][,udp=on/off][,cookie64=on/off][,counter][,pincounter][,txcookie=txcookie][,rxcookie=rxcookie][,offset=offset]

    configure a network backend with ID ’str’ connected toan Ethernet over L2TPv3 pseudowire.Linux kernel 3.3+ as well as most routers can talkL2TPv3. This transport allows connecting a VM to a VM,VM to a router and even VM to Host. It is a nearly-universalstandard (RFC3391). Note - this implementation uses staticpre-configured tunnels (same as the Linux kernel).use ’src=’ to specify source addressuse ’dst=’ to specify destination addressuse ’udp=on’ to specify udp encapsulationuse ’srcport=’ to specify source udp portuse ’dstport=’ to specify destination udp portuse ’ipv6=on’ to force v6L2TPv3 uses cookies to prevent misconfiguration aswell as a weak security measureuse ’rxcookie=0x012345678’ to specify a rxcookieuse ’txcookie=0x012345678’ to specify a txcookieuse ’cookie64=on’ to set cookie size to 64 bit, otherwise 32use ’counter=off’ to force a ’cut-down’ L2TPv3 with no counteruse ’pincounter=on’ to work around broken counter handling in peeruse ’offset=X’ to add an extra offset between header and data

    -netdev socket,id=str[,fd=h][,listen=[host]:port][,connect=host:port]configure a network backend to connect to another networkusing a socket connection

    -netdev socket,id=str[,fd=h][,mcast=maddr:port[,localaddr=addr]]configure a network backend to connect to a multicast maddr and portuse ’localaddr=addr’ to specify the host address to send packets from

    -netdev socket,id=str[,fd=h][,udp=host:port][,localaddr=host:port]

    configure a network backend to connect to another networkusing an UDP tunnel

    -netdev vhost-user,id=str,chardev=dev[,vhostforce=on|off]configure a vhost-user network, backed by a chardev ’dev’

    -netdev hubport,id=str,hubid=nconfigure a hub port on QEMU VLAN ’n’

    -net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]old way to create a new NIC and connect it to VLAN ’n’(use the ’-device devtype,netdev=str’ option if possible instead)

    -net dump[,vlan=n][,file=f][,len=n]dump traffic on vlan ’n’ to file ’f’ (max n bytes per packet)

    -net none use it alone to have zero network devices. If no -net optionis provided, the default is ’-net nic -net user’

    -net [user|tap|bridge|socket][,vlan=n][,option][,option][,...]old way to initialize a host network interface(use the -netdev option if possible instead)

    Character device options:-chardev null,id=id[,mux=on|off]-chardev socket,id=id[,host=host],port=port[,to=to][,ipv4][,ipv6][,nodelay][,reconnect=seconds]

    [,server][,nowait][,telnet][,reconnect=seconds][,mux=on|off] (tcp)-chardev socket,id=id,path=path[,server][,nowait][,telnet][,reconnect=seconds][,mux=on|off] (unix)-chardev udp,id=id[,host=host],port=port[,localaddr=localaddr]

    [,localport=localport][,ipv4][,ipv6][,mux=on|off]-chardev msmouse,id=id[,mux=on|off]-chardev vc,id=id[[,width=width][,height=height]][[,cols=cols][,rows=rows]]

    [,mux=on|off]-chardev ringbuf,id=id[,size=size]-chardev file,id=id,path=path[,mux=on|off]-chardev pipe,id=id,path=path[,mux=on|off]-chardev pty,id=id[,mux=on|off]-chardev stdio,id=id[,mux=on|off][,signal=on|off]-chardev braille,id=id[,mux=on|off]-chardev serial,id=id,path=path[,mux=on|off]-chardev tty,id=id,path=path[,mux=on|off]-chardev parallel,id=id,path=path[,mux=on|off]-chardev parport,id=id,path=path[,mux=on|off]-chardev spicevmc,id=id,name=name[,debug=debug]-chardev spiceport,id=id,name=name[,debug=debug]

    Device URL Syntax:-iscsi [user=user][,password=password]

    [,header-digest=CRC32C|CR32C-NONE|NONE-CRC32C|NONE[,initiator-name=initiator-iqn][,id=target-iqn][,timeout=timeout]

    iSCSI session parametersBluetooth(R) options:-bt hci,null dumb bluetooth HCI - doesn’t respond to commands-bt hci,host[:id]

    use host’s HCI with the given name-bt hci[,vlan=n]

    emulate a standard HCI in virtual scatternet ’n’-bt vhci[,vlan=n]

    add host computer to virtual scatternet ’n’ using VHCI-bt device:dev[,vlan=n]

    emulate a bluetooth device ’dev’ in scatternet ’n’

    TPM device options:-tpmdev passthrough,id=id[,path=path][,cancel-path=path]

    use path to provide path to a character device; default is /dev/tpm0use cancel-path to provide path to TPM’s cancel sysfs entry; ifnot provided it will be searched for in /sys/class/misc/tpm?/device

    Linux/Multiboot boot specific:-kernel bzImage use ’bzImage’ as kernel image-append cmdline use ’cmdline’ as kernel command line-initrd file use ’file’ as initial ram disk-dtb file use ’file’ as device tree image

    Debug/Expert options:-fw_cfg [name=],file=

    add named fw_cfg entry from file-serial dev redirect the serial port to char device ’dev’-parallel dev redirect the parallel port to char device ’dev’-monitor dev redirect the monitor to char device ’dev’-qmp dev like -monitor but opens in ’control’ mode-qmp-pretty dev like -qmp but uses pretty JSON formatting-mon [chardev=]name[,mode=readline|control][,default]-debugcon dev redirect the debug console to char device ’dev’-pidfile file write PID to ’file’-singlestep always run in singlestep mode-S freeze CPU at startup (use ’c’ to start execution)-realtime [mlock=on|off]

    run qemu with realtime featuresmlock=on|off controls mlock support (default: on)

    -gdb dev wait for gdb connection on ’dev’-s shorthand for -gdb tcp::1234-d item1,... enable logging of specified items (use ’-d help’ for a list of log items)-D logfile output log to logfile (default stderr)-L path set the directory for the BIOS, VGA BIOS and keymaps-bios file set the filename for the BIOS-enable-kvm enable KVM full virtualization support-xen-domid id specify xen guest domain id-xen-create create domain using xen hypercalls, bypassing xend

    warning: should not be used when xend is in use-xen-attach attach to existing xen domain

    xend will use this when starting QEMU-no-reboot exit instead of rebooting-no-shutdown stop before shutdown-loadvm [tag|id]

    start right away with a saved state (loadvm in monitor)-daemonize daemonize QEMU after initializing-option-rom rom load a file, rom, into the option ROM space-rtc [base=utc|localtime|date][,clock=host|rt|vm][,driftfix=none|slew]

    set the RTC base and clock, enable drift fix for clock ticks (x86 only)-icount [shift=N|auto][,align=on|off][,sleep=no]

    enable virtual instruction counter with 2^N clock ticks perinstruction, enable aligning the host and virtual clocksor disable real time cpu sleeping

    -watchdog modelenable virtual hardware watchdog [default=none]

    -watchdog-action reset|shutdown|poweroff|pause|debug|noneaction when watchdog fires [default=reset]

    -echr chr set terminal escape character instead of ctrl-a-virtioconsole c

    set virtio console-show-cursor show cursor-tb-size n set TB size-incoming tcp:[host]:port[,to=maxport][,ipv4][,ipv6]-incoming rdma:host:port[,ipv4][,ipv6]

    -incoming rdma:host:port[,ipv4][,ipv6]-incoming unix:socketpath

    prepare for incoming migration, listen onspecified protocol and socket address

    -incoming fd:fd-incoming exec:cmdline

    accept incoming migration on given file descriptoror from given external command

    -incoming deferwait for the URI to be specified via migrate_incoming

    -nodefaults don’t create default devices-chroot dir chroot to dir just before starting the VM-runas user change to user id user just before starting the VM-sandbox Enable seccomp mode 2 system call filter (default ’off’).-readconfig -writeconfig

    read/write config file-nodefconfig

    do not load default config files at startup-no-user-config

    do not load user-provided config files at startup-trace [events=][,file=]

    specify tracing options-enable-fips enable FIPS 140-2 compliance-msg timestamp[=on|off]

    change the format of messageson|off controls leading timestamps (default:on)

    -dump-vmstate Output vmstate information in JSON format to file.Use the scripts/vmstate-static-checker.py file tocheck for possible regressions in migration codeby comparing two such vmstate dumps.Generic object creation

    -object TYPENAME[,PROP1=VALUE1,...]create a new object of type TYPENAME setting propertiesin the order they are specified. Note that the ’id’property must be set. These objects are placed in the’/objects’ path.

    During emulation, the following keys are useful:ctrl-alt-f toggle full screenctrl-alt-n switch to virtual console ’n’ctrl-alt toggle mouse and keyboard grab

    When using -nographic, press ’ctrl-a h’ to get some help.

  • Really big: its manual sectionChapter 3: QEMU PC System emulator 5

    3.3 Invocation

    usage: qemu-system-i386 [options] [disk_image]

    disk image is a raw hard disk image for IDE hard disk 0. Some targets do not need a diskimage.

    Standard options:

    -h Display help and exit

    -version Display version information and exit

    -machine [type=]name[,prop=value[,...]]

    Select the emulated machine by name. Use -machine help to list availablemachines. Supported machine properties are:

    accel=accels1[:accels2[:...]]

    This is used to enable an accelerator. Depending on the targetarchitecture, kvm, xen, or tcg can be available. By default, tcg isused. If there is more than one accelerator specified, the next oneis used if the previous one fails to initialize.

    kernel_irqchip=on|off

    Enables in-kernel irqchip support for the chosen accelerator whenavailable.

    vmport=on|off|auto

    Enables emulation of VMWare IO port, for vmmouse etc. auto saysto select the value based on accel. For accel=xen the default is offotherwise the default is on.

    kvm_shadow_mem=size

    Defines the size of the KVM shadow MMU.

    dump-guest-core=on|off

    Include guest memory in a core dump. The default is on.

    mem-merge=on|off

    Enables or disables memory merge support. This feature, whensupported by the host, de-duplicates identical memory pages amongVMs instances (enabled by default).

    iommu=on|off

    Enables or disables emulated Intel IOMMU (VT-d) support. Thedefault is off.

    aes-key-wrap=on|off

    Enables or disables AES key wrapping support on s390-ccw hosts.This feature controls whether AES wrapping keys will be createdto allow execution of AES cryptographic functions. The default ison.

    dea-key-wrap=on|off

    Enables or disables DEA key wrapping support on s390-ccw hosts.This feature controls whether DEA wrapping keys will be created

    Chapter 3: QEMU PC System emulator 6

    to allow execution of DEA cryptographic functions. The default ison.

    -cpu model

    Select CPU model (-cpu help for list and additional feature selection)

    -smp

    [cpus=]n[,cores=cores][,threads=threads][,sockets=sockets][,maxcpus=maxcpus]

    Simulate an SMP system with n CPUs. On the PC target, up to 255 CPUs aresupported. On Sparc32 target, Linux limits the number of usable CPUs to 4.For the PC target, the number of cores per socket, the number of threads percores and the total number of sockets can be specified. Missing values will becomputed. If any on the three values is given, the total number of CPUs n canbe omitted. maxcpus specifies the maximum number of hotpluggable CPUs.

    -numa node[,mem=size][,cpus=cpu[-cpu]][,nodeid=node]

    -numa node[,memdev=id][,cpus=cpu[-cpu]][,nodeid=node]

    Simulate a multi node NUMA system. If ‘mem’, ‘memdev’ and ‘cpus’ are omitted,resources are split equally. Also, note that the -numa option doesn’t allocate anyof the specified resources. That is, it just assigns existing resources to NUMAnodes. This means that one still has to use the -m, -smp options to allocateRAM and VCPUs respectively, and possibly -object to specify the memorybackend for the ‘memdev’ suboption.

    ‘mem’ and ‘memdev’ are mutually exclusive. Furthermore, if one node uses‘memdev’, all of them have to use it.

    -add-fd fd=fd,set=set[,opaque=opaque]

    Add a file descriptor to an fd set. Valid options are:

    fd=fd This option defines the file descriptor of which a duplicate is addedto fd set. The file descriptor cannot be stdin, stdout, or stderr.

    set=set This option defines the ID of the fd set to add the file descriptorto.

    opaque=opaque

    This option defines a free-form string that can be used to describefd.

    You can open an image using pre-opened file descriptors from an fd set:

    qemu-system-i386

    -add-fd fd=3,set=2,opaque="rdwr:/path/to/file"

    -add-fd fd=4,set=2,opaque="rdonly:/path/to/file"

    -drive file=/dev/fdset/2,index=0,media=disk

    -set group.id.arg=value

    Set parameter arg for item id of type group\n"

    -global driver.prop=value

    -global driver=driver,property=property,value=value

    Set default value of driver’s property prop to value, e.g.:

    Chapter 3: QEMU PC System emulator 7

    qemu-system-i386 -global ide-drive.physical_block_size=4096 -drive file=file,if=ide,index=0,media=disk

    In particular, you can use this to set driver properties for devices which arecreated automatically by the machine model. To create a device which is notcreated automatically and set properties on it, use -device.

    -global driver.prop=value is shorthand for -global driver=driver,property=prop,value=value.The longhand syntax works even when driver contains a dot.

    -boot [order=drives][,once=drives][,menu=on|off][,splash=sp_

    name][,splash-time=sp_time][,reboot-timeout=rb_timeout][,strict=on|off]

    Specify boot order drives as a string of drive letters. Valid drive letters dependon the target architecture. The x86 PC uses: a, b (floppy 1 and 2), c (first harddisk), d (first CD-ROM), n-p (Etherboot from network adapter 1-4), hard diskboot is the default. To apply a particular boot order only on the first startup,specify it via once.

    Interactive boot menus/prompts can be enabled via menu=on as far asfirmware/BIOS supports them. The default is non-interactive boot.

    A splash picture could be passed to bios, enabling user to show it as logo,when option splash=sp name is given and menu=on, If firmware/BIOS sup-ports them. Currently Seabios for X86 system support it. limitation: Thesplash file could be a jpeg file or a BMP file in 24 BPP format(true color).The resolution should be supported by the SVGA mode, so the recommendedis 320x240, 640x480, 800x640.

    A timeout could be passed to bios, guest will pause for rb timeout ms whenboot failed, then reboot. If rb timeout is ’-1’, guest will not reboot, qemu passes’-1’ to bios by default. Currently Seabios for X86 system support it.

    Do strict boot via strict=on as far as firmware/BIOS supports it. This onlyeffects when boot priority is changed by bootindex options. The default isnon-strict boot.

    # try to boot from network first, then from hard disk

    qemu-system-i386 -boot order=nc

    # boot from CD-ROM first, switch back to default order after reboot

    qemu-system-i386 -boot once=d

    # boot with a splash picture for 5 seconds.

    qemu-system-i386 -boot menu=on,splash=/root/boot.bmp,splash-time=5000

    Note: The legacy format ’-boot drives’ is still supported but its use is discour-aged as it may be removed from future versions.

    -m [size=]megs[,slots=n,maxmem=size]

    Sets guest startup RAM size to megs megabytes. Default is 128 MiB. Op-tionally, a suffix of “M” or “G” can be used to signify a value in megabytesor gigabytes respectively. Optional pair slots, maxmem could be used to setamount of hotpluggable memory slots and maximum amount of memory. Notethat maxmem must be aligned to the page size.

    For example, the following command-line sets the guest startup RAM size to1GB, creates 3 slots to hotplug additional memory and sets the maximummemory the guest can reach to 4GB:

    Chapter 3: QEMU PC System emulator 8

    qemu-system-x86_64 -m 1G,slots=3,maxmem=4G

    If slots and maxmem are not specified, memory hotplug won’t be enabled andthe guest startup RAM will never increase.

    -mem-path path

    Allocate guest RAM from a temporarily created file in path.

    -mem-prealloc

    Preallocate memory when using -mem-path.

    -k language

    Use keyboard layout language (for example fr for French). This option is onlyneeded where it is not easy to get raw PC keycodes (e.g. on Macs, with someX11 servers or with a VNC display). You don’t normally need to use it onPC/Linux or PC/Windows hosts.

    The available layouts are:

    ar de-ch es fo fr-ca hu ja mk no pt-br sv

    da en-gb et fr fr-ch is lt nl pl ru th

    de en-us fi fr-be hr it lv nl-be pt sl tr

    The default is en-us.

    -audio-help

    Will show the audio subsystem help: list of drivers, tunable parameters.

    -soundhw card1[,card2,...] or -soundhw all

    Enable audio and selected sound hardware. Use ’help’ to print all availablesound hardware.

    qemu-system-i386 -soundhw sb16,adlib disk.img

    qemu-system-i386 -soundhw es1370 disk.img

    qemu-system-i386 -soundhw ac97 disk.img

    qemu-system-i386 -soundhw hda disk.img

    qemu-system-i386 -soundhw all disk.img

    qemu-system-i386 -soundhw help

    Note that Linux’s i810 audio OSS kernel (for AC97) module might requiremanually specifying clocking.

    modprobe i810_audio clocking=48000

    -balloon none

    Disable balloon device.

    -balloon virtio[,addr=addr]

    Enable virtio balloon device (default), optionally with PCI address addr.

    -device driver[,prop[=value][,...]]

    Add device driver. prop=value sets driver properties. Valid properties dependon the driver. To get help on possible drivers and properties, use -device helpand -device driver,help.

    -name name

    Sets the name of the guest. This name will be displayed in the SDL windowcaption. The name will also be used for the VNC server. Also optionally set

    Chapter 3: QEMU PC System emulator 9

    the top visible process name in Linux. Naming of individual threads can alsobe enabled on Linux to aid debugging.

    -uuid uuid

    Set system UUID.

    Block device options:

    -fda file

    -fdb file Use file as floppy disk 0/1 image (see Section 3.6 [disk images], page 57).

    -hda file

    -hdb file

    -hdc file

    -hdd file Use file as hard disk 0, 1, 2 or 3 image (see Section 3.6 [disk images], page 57).

    -cdrom file

    Use file as CD-ROM image (you cannot use -hdc and -cdrom at the sametime). You can use the host CD-ROM by using /dev/cdrom as filename (seeSection 3.6.7 [host drives], page 69).

    -drive option[,option[,option[,...]]]

    Define a new drive. Valid options are:

    file=file

    This option defines which disk image (see Section 3.6 [disk images],page 57) to use with this drive. If the filename contains comma, youmust double it (for instance, "file=my,,file" to use file "my,file").

    Special files such as iSCSI devices can be specified using protocolspecific URLs. See the section for "Device URL Syntax" for moreinformation.

    if=interface

    This option defines on which type on interface the drive is con-nected. Available types are: ide, scsi, sd, mtd, floppy, pflash, virtio.

    bus=bus,unit=unit

    These options define where is connected the drive by defining thebus number and the unit id.

    index=index

    This option defines where is connected the drive by using an indexin the list of available connectors of a given interface type.

    media=media

    This option defines the type of the media: disk or cdrom.

    cyls=c,heads=h,secs=s[,trans=t]

    These options have the same definition as they have in -hdachs.

    snapshot=snapshot

    snapshot is "on" or "off" and controls snapshot mode for the givendrive (see -snapshot).

    Chapter 3: QEMU PC System emulator 10

    cache=cache

    cache is "none", "writeback", "unsafe", "directsync" or"writethrough" and controls how the host cache is used to accessblock data.

    aio=aio aio is "threads", or "native" and selects between pthread baseddisk I/O and native Linux AIO.

    discard=discard

    discard is one of "ignore" (or "off") or "unmap" (or "on") andcontrols whether discard (also known as trim or unmap) requestsare ignored or passed to the filesystem. Some machine types maynot support discard requests.

    format=format

    Specify which disk format will be used rather than detecting theformat. Can be used to specifiy format=raw to avoid interpretingan untrusted format header.

    serial=serial

    This option specifies the serial number to assign to the device.

    addr=addr

    Specify the controller’s PCI address (if=virtio only).

    werror=action,rerror=action

    Specify which action to take on write and read errors. Valid actionsare: "ignore" (ignore the error and try to continue), "stop" (pauseQEMU), "report" (report the error to the guest), "enospc" (pauseQEMU only if the host disk is full; report the error to the guest oth-erwise). The default setting is werror=enospc and rerror=report.

    readonly Open drive file as read-only. Guest write attempts will fail.

    copy-on-read=copy-on-read

    copy-on-read is "on" or "off" and enables whether to copy readbacking file sectors into the image file.

    detect-zeroes=detect-zeroes

    detect-zeroes is "off", "on" or "unmap" and enables the automaticconversion of plain zero writes by the OS to driver specific optimizedzero write commands. You may even choose "unmap" if discard isset to "unmap" to allow a zero write to be converted to an UNMAPoperation.

    By default, the cache=writeback mode is used. It will report data writes ascompleted as soon as the data is present in the host page cache. This is safe aslong as your guest OS makes sure to correctly flush disk caches where needed.If your guest OS does not handle volatile disk write caches correctly and yourhost crashes or loses power, then the guest may experience data corruption.

    For such guests, you should consider using cache=writethrough. This meansthat the host page cache will be used to read and write data, but write notifi-

    Chapter 3: QEMU PC System emulator 11

    cation will be sent to the guest only after QEMU has made sure to flush eachwrite to the disk. Be aware that this has a major impact on performance.

    The host page cache can be avoided entirely with cache=none. This will at-tempt to do disk IO directly to the guest’s memory. QEMU may still performan internal copy of the data. Note that this is considered a writeback modeand the guest OS must handle the disk write cache correctly in order to avoiddata corruption on host crashes.

    The host page cache can be avoided while only sending write notifications tothe guest when the data has been flushed to the disk using cache=directsync.

    In case you don’t care about data integrity over host failures, use cache=unsafe.This option tells QEMU that it never needs to write any data to the disk butcan instead keep things in cache. If anything goes wrong, like your host losingpower, the disk storage getting disconnected accidentally, etc. your image willmost probably be rendered unusable. When using the -snapshot option, unsafecaching is always used.

    Copy-on-read avoids accessing the same backing file sectors repeatedly and isuseful when the backing file is over a slow network. By default copy-on-read isoff.

    Instead of -cdrom you can use:

    qemu-system-i386 -drive file=file,index=2,media=cdrom

    Instead of -hda, -hdb, -hdc, -hdd, you can use:

    qemu-system-i386 -drive file=file,index=0,media=disk

    qemu-system-i386 -drive file=file,index=1,media=disk

    qemu-system-i386 -drive file=file,index=2,media=disk

    qemu-system-i386 -drive file=file,index=3,media=disk

    You can open an image using pre-opened file descriptors from an fd set:

    qemu-system-i386

    -add-fd fd=3,set=2,opaque="rdwr:/path/to/file"

    -add-fd fd=4,set=2,opaque="rdonly:/path/to/file"

    -drive file=/dev/fdset/2,index=0,media=disk

    You can connect a CDROM to the slave of ide0:

    qemu-system-i386 -drive file=file,if=ide,index=1,media=cdrom

    If you don’t specify the "file=" argument, you define an empty drive:

    qemu-system-i386 -drive if=ide,index=1,media=cdrom

    You can connect a SCSI disk with unit ID 6 on the bus #0:

    qemu-system-i386 -drive file=file,if=scsi,bus=0,unit=6

    Instead of -fda, -fdb, you can use:

    qemu-system-i386 -drive file=file,index=0,if=floppy

    qemu-system-i386 -drive file=file,index=1,if=floppy

    By default, interface is "ide" and index is automatically incremented:

    qemu-system-i386 -drive file=a -drive file=b"

    is interpreted like:

    Chapter 3: QEMU PC System emulator 12

    qemu-system-i386 -hda a -hdb b

    -mtdblock file

    Use file as on-board Flash memory image.

    -sd file Use file as SecureDigital card image.

    -pflash file

    Use file as a parallel flash image.

    -snapshot

    Write to temporary files instead of disk image files. In this case, the raw diskimage you use is not written back. You can however force the write back bypressing C-a s (see Section 3.6 [disk images], page 57).

    -hdachs c,h,s,[,t]

    Force hard disk 0 physical geometry (1

  • This is how it’s used in anger$ /usr/bin/qemu-system-x86_64 -machine accel=kvm -name boxes-unknown -S -machine pc-i440fx-1.6,accel=kvm,usb=off -cpu \Penryn -m 3115 -realtime mlock=off -smp 4,sockets=1,cores=4,threads=1 -uuid 8bd53789-adab-484f-8c53-a6df9d5f1dbf -no-u\ser-config -nodefaults -chardev socket,id=charmonitor,path=/home/guillaume/.config/libvirt/qemu/lib/boxes-unknown.moni\tor,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc,driftfix=slew -global kvm-pit.lost_ti\ck_policy=discard -no-shutdown -global PIIX4_PM.disable_s3=1 -global PIIX4_PM.disable_s4=1 -boot strict=on -device ich\9-usb-ehci1,id=usb,bus=pci.0,addr=0x5.0x7 -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=o\n,addr=0x5 -device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x5.0x1-device ich9-usb-uhci3,masterbus=u\sb.0,firstport=4,bus=pci.0,addr=0x5.0x2 -device virtio-serial-pci,id=virtio-serial0,bus=pci.0,addr=0x6 -device usb-cci\d,id=ccid0 -drive file=/home/guillaume/.local/share/gnome-boxes/images/boxes-unknown,if=none,id=drive-ide0-0-0,format=\qcow2,cache=none -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=1 -drive if=none,id=drive-\ide0-1-0,readonly=on,format=raw -device ide-cd,bus=ide.1,unit=0,drive=drive-ide0-1-0,id=ide0-1-0 -netdev tap,fd=23,id=\hostnet0 -device rtl8139,netdev=hostnet0,id=net0,mac=52:54:00:db:56:54,bus=pci.0,addr=0x3 -chardev spicevmc,id=charsma\rtcard0,name=smartcard -device ccid-card-passthru,chardev=charsmartcard0,id=smartcard0,bus=ccid0.0 -chardev pty,id=cha\rserial0 -device isa-serial,chardev=charserial0,id=serial0 -chardev spicevmc,id=charchannel0,name=vdagent -device virt\serialport,bus=virtio-serial0.0,nr=1,chardev=charchannel0,id=channel0,name=com.redhat.spice.0 -device usb-tablet,id=in\put0 -spice port=5901,addr=127.0.0.1,disable-ticketing,image-compression=off,seamless-migration=on -device qxl-vga,id=\video0,ram_size=67108864,vram_size=67108864,vgamem_mb=16,bus=pci.0,addr=0x2 -device AC97,id=sound0,bus=pci.0,addr=0x4 \-chardev spicevmc,id=charredir0,name=usbredir -device usb-redir,chardev=charredir0,id=redir0 -chardev spicevmc,id=char\redir1,name=usbredir -device usb-redir,chardev=charredir1,id=redir1 -chardev spicevmc,id=charredir2,name=usbredir -dev\ice usb-redir,chardev=charredir2,id=redir2 -chardev spicevmc,id=charredir3,name=usbredir -device usb-redir,chardev=cha\rredir3,id=redir3 -incoming fd:20 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x7 -msg timestamp=on

  • QMP is even bigger126 commands + 33 eventsMore than 700 named arguments and resultsDefined in the (book-sized) QAPI/QMP schema

    0 5 10 15 20 25 30

    qemu-doc.texiGospel of LukeQMP schemaGenesis

    #words [thousands]

  • Command line evolves fast

    1.62013-08

    1.7 2.0 2.1 2.2 2.32015-082.4

    30

    35

    40

    45

    300

    350

    400

    450

    Pagesin

    manual

    +20%

    p.a.

    Linesin

    -hel

    p

  • QMP evolves faster

    1.62013-08

    1.7 2.0 2.1 2.2 2.32015-082.4

    120

    140

    160

    12,000

    14,000

    16,000

    18,000

    20,000

    22,000

    Commands

    +Ev

    ents

    +25%

    p.a.!

    Words

    inSchema

  • Why interface introspection?

    QEMU provides big, rapidly evolving interfacesA program can

    Tie to a specific build of QEMUWrong talk, you can break for coffee nowFigure out what the QEMU it got can doEasiest when interfaces support introspection

    Trouble is our interfaces don’t fully support it, yet

  • Part IIPrior work

  • Version numbers?QEMU says 0.12.1, but. . .

    base2009-12

    6.0 6.1 6.2 6.3 6.4 6.5 6.62015-066.7

    50

    100

    150

    200

    400

    600

    800

    +250%

    UpstreamRHEL-6

    Commands

    +Ev

    ents

    +35% Lines

    in-h

    elp

    Backports make the upstream version meaningless

  • Downstream version?

    We provide for downstreams adding their versionBut: not always stepped Downstream version often meaningless, tooEven if it wasn’t:#downstreams × #releases = heaps of versionsUpstream wise guy shrugs “downstream problem”

  • Version numbers insufficient!

    Upstream 2.4 development cycle:$ git-diff --shortstat v2.3.0..v2.4.01414 files changed, 72635 insertions(+),25875 deletions(-)

    $ git-log --oneline v2.3.0..v2.4.0 | wc -l2147

    Version for 1901 out of 2147 commits: 2.3.50Development can’t wait for the version to change!Upstream wise guy gets enlightened

  • Just try to use it

    Workable in simple casesExample: libvirt tries QMP inject-nmi,

    falls back to old HMP nmi

    Complex, slow, fragile in not so simple casesRecovery may need to recognize exact errorProbe by trying may need complex scaffoldingProbe must avoid unwanted effects

  • A real-world failure of “just try”

    block-commit new in v1.3, and libvirt just tried it:Run block-commit, and if it succeedswait for event BLOCK_JOB_COMPLETED

    Before v2.0, block-commit fails for active layerSince then, it succeeds, but requires manual

    block-job-complete to complete

    Old libvirt hangs on BLOCK_JOB_COMPLETED

    Relying on behaviour in error cases is fragile

  • Pretend to be human: read help

    Examples: -help-device help-device virtio-net,help-drive format=help

    Drawbacks:Parsing help is painful and fragileHelp text becomes de facto ABIHelp is incomplete (e.g. no -drive if=help)

    Everyone did this until QEMU grew real interfaces

  • QMP query-commands

    Example:QMP> { "execute":"query-commands" }{ "return":[ . . . { "name":"eject" }, . . . ] }

    This is very limited QMP interface introspection:can check presence of commandssilent on arguments & results

    Plenty useful, but we need arguments & results now

  • QMP query-command-line-options

    Example:QMP> { "execute":"query-command-line-options" }{ "return":[ . . .{ "option":"memory", "parameters":[{ "name":"slots", "type":"number" },{ "name":"size", "type":"size" } ],. . . } ] }

    This tries to be command line introspectionWhat’s wrong with it? Dear God, where to begin!

  • query-c-l-options is incomplete

    some parametersname wrong

    completemissing, inessential

    missing, no excuse

    no parameters

    Probably better than nothingCertainly less than needed

  • query-c-l-options is inexpressive

    Things we’d like to know, but it can’t tell:Formats supported by -drive?It only tells us parameter format is “string”Parameters supported with -chardev socket?It tells us parameters supported by any backend

    Structural weaknessesWorse than merely incomplete

  • Look for a witness

    Example: how libvirt probes for -spiceNew in v0.14No query-command-line-options back thenWith -spice, we added QMP query-spiceCan probe that one with query-commandsUse query-spice as a witness for -spice

    Useful when direct probe is impracticaland a suitable witness exists

  • Add an ad hoc query command

    9♣

    9♣

    9♣

    9♣

    ♣♣

    ♣♣

    chardev-

    backends

    chardev-

    backends

    8♥

    8♥

    8♥

    8♥

    ♥ ♥♥ ♥cpu

    -definitions cpu-

    definitions

    7♠

    7♠

    7♠

    7♠

    ♠ ♠♠ ♠dum

    p-gu

    est-

    mem

    ory-

    capa

    bility

    dump-guest-

    mem

    ory-

    capability

    6♦

    6♦

    6♦

    6♦

    ♦ ♦♦ ♦

    kvm

    kvm

    5♣

    5♣

    5♣

    5♣

    ♣ ♣♣ ♣

    machine

    s machines

    4♥

    4♥

    4♥

    4♥

    ♥ ♥

    ♥ ♥

    migrate-

    capa

    bilities

    migrate-

    capabilities

    3♠

    3♠

    3♠

    3♠

    tpm-m

    odels

    tpm-m

    odels

    2♦

    2♦

    2♦

    2♦

    tpm-types

    tpm-types

    Deck of

    Queries

    Deck of

    Queries

    Deck of

    Queries

    Deck of

    Queries

    Deck of

    Queries

    Got several alreadyHow many more?

  • Add an ad hoc query command

    9♣

    9♣

    9♣

    9♣

    ♣♣

    ♣♣

    chardev-

    backends

    chardev-

    backends

    8♥

    8♥

    8♥

    8♥

    ♥ ♥♥ ♥cpu

    -definitions cpu-

    definitions

    7♠

    7♠

    7♠

    7♠

    ♠ ♠♠ ♠dum

    p-gu

    est-

    mem

    ory-

    capa

    bility

    dump-guest-

    mem

    ory-

    capability

    6♦

    6♦

    6♦

    6♦

    ♦ ♦♦ ♦

    kvm

    kvm

    5♣

    5♣

    5♣

    5♣

    ♣ ♣♣ ♣

    machine

    s machines

    4♥

    4♥

    4♥

    4♥

    ♥ ♥

    ♥ ♥

    migrate-

    capa

    bilities

    migrate-

    capabilities

    3♠

    3♠

    3♠

    3♠

    tpm-m

    odels

    tpm-m

    odels

    2♦

    2♦

    2♦

    2♦

    tpm-types

    tpm-types

    JOKERJOKER

    Got several alreadyHow many more?

    Can we get a joker instead?

  • Where do we stand now?

    Current introspection solutions work,but won’t cut it much longer:

    query-command-line-optionstoo incomplete and inexpressivequery-commands too limitedwe need arguments & resultsAdding a query-FOO for every FOOwill result in a mess

    Time to crack QMP introspection for real!

  • Part IIIQMP Introspection

  • The basic ideaInterface introspection turns interface into dataQMP is defined by QAPI schemaSchema is data, so let clients query for it!However:

    Geared towards humans, not machinesMixes up ABI aspects and internal detail

    Instead of simply dumping QAPI schema:Expose only its QMP wire ABI aspectsDesign query output for machines

  • Cooking: query-schemaComing in v2.5:QMP> { "execute":"query-schema" }{"return":[ . . . {"name": "eject", . . . ] }

    Exposes QMP wire ABI as defined in the schema:Commands, events with arguments & resultsArguments & results fully typedEnumerations (find supported values)Variants records. . .

    By yours truly, with heaps of help from Eric Blake

  • Let’s introspect a commandQAPI Schema for query-block:{ ’command’: ’query-block’,

    ’returns’: [’BlockInfo’] }

    Relevant part of query-schema’s return:{ "name":"query-block",

    "meta-type":"command","arg-type":"15", "ret-type":"101" },

    { "name":"15", "meta-type":"object","members":[] },

    { "name":"101", "meta-type":"array","element-type":"183" }

  • Let’s introspect a commandQAPI Schema for query-block:{ ’command’: ’query-block’’command’: ’query-block’,

    ’returns’: [’BlockInfo’] }

    Relevant part of query-schema’s return:{ "name":"query-block""name":"query-block",

    "meta-type":"command""meta-type":"command","arg-type":"15", "ret-type":"101" },

    { "name":"15", "meta-type":"object","members":[] },

    { "name":"101", "meta-type":"array","element-type":"183" }

    “query-block”is a command

  • Let’s introspect a commandQAPI Schema for query-block:{ ’command’: ’query-block’, # no arguments# no arguments

    ’returns’: [’BlockInfo’] }

    Relevant part of query-schema’s return:{ "name":"query-block",

    "meta-type":"command","arg-type":"15""arg-type":"15", "ret-type":"101" },

    { "name":"15", "meta-type":"object",{ "name":"15", "meta-type":"object","members":[] },"members":[] },

    { "name":"101", "meta-type":"array","element-type":"183" }

    It has an empty argument type(normalized from no arguments)

  • Let’s introspect a commandQAPI Schema for query-block:{ ’command’: ’query-block’,

    ’returns’: [’BlockInfo’]’returns’: [’BlockInfo’] }

    Relevant part of query-schema’s return:{ "name":"query-block",

    "meta-type":"command","arg-type":"15", "ret-type":"101""ret-type":"101" },

    { "name":"15", "meta-type":"object","members":[] },

    { "name":"101", "meta-type":"array",{ "name":"101", "meta-type":"array","element-type":"183" }"element-type":"183" }

    Return type is array of BlockInfo

  • Let’s introspect a commandQAPI Schema for query-block:{ ’command’: ’query-block’,

    ’returns’: [’BlockInfo’] }

    Relevant part of query-schema’s return:{ "name":"query-block",

    "meta-type":"command","arg-type":"15", "ret-type":"101" },

    { "name":"15", "meta-type":"object","members":[] },

    { "name":"101", "meta-type":"array","element-type":"183""183" }

    Type name’BlockInfo’ masked

    (not ABI)

  • Let’s introspect a commandQAPI Schema for query-block:{ ’command’: ’query-block’,

    ’returns’: [’BlockInfo’] }

    Relevant part of query-schema’s return:{ "name":"query-block",

    "meta-type":"command","arg-type":"15", "ret-type":"101" },

    { "name":"15", "meta-type":"object","members":[] },

    { "name":"101", "meta-type":"array","element-type":"183" }

    Tediously explicit

  • Let’s introspect introspection!QAPI Schema for query-schema:{ ’command’: ’query-schema’,

    ’returns’: [’SchemaInfo’’SchemaInfo’] }

    Relevant part of query-schema’s return:{ "name":"query-schema",

    "meta-type":"command","arg-type":"15", "ret-type":"129" },

    { "name":"15", "meta-type":"object","members":[] },

    { "name":"129", "meta-type":"array","element-type":"203""element-type":"203" }

    Like query-block,with SchemaInfo

    instead ofBlockInfo

  • Drill down into SchemaInfo{ ’union’: ’SchemaInfo’,

    ’base’: ’SchemaInfoBase’,’discriminator’: ’meta-type’,’data’: {

    ’command’: ’SchemaInfoCommand’,’enum’: ’SchemaInfoEnum’,’object’: ’SchemaInfoObject’,. . . } }

    { ’struct’: ’SchemaInfoBase’,’data’: { ’name’: ’str’,’meta-type’: ’SchemaMetaType’ } }

    { ’enum’: ’SchemaMetaType’,’data’: [’builtin’, ’enum’, ’array’, ’object’,

    ’alternate’, ’command’, ’event’] }

  • Drill down into SchemaInfo{ ’union’: ’SchemaInfo’,

    ’base’: ’SchemaInfoBase’,’discriminator’: ’meta-type’,’data’: {

    ’command’: ’SchemaInfoCommand’,’enum’: ’SchemaInfoEnum’,’object’: ’SchemaInfoObject’,. . . } }

    { ’struct’: ’SchemaInfoBase’,’data’: { ’name’: ’str’,’meta-type’: ’SchemaMetaType’ } }

    { ’enum’: ’SchemaMetaType’,’data’: [’builtin’, ’enum’, ’array’, ’object’,

    ’alternate’, ’command’, ’event’] }

    QAPI schema gobbledygook decoded:

    SchemaInfo is a variant recordCommon members: name, meta-typeVariant members depend on meta-type:meta-type variant memberscommand arg-type, ret-typearray element-typeobject members, tag, variants. . .

  • Introspect SchemaInfo{ "name":"203", "meta-type":"object",

    "members":[{ "name":"name", "type":"str" },{ "name":"meta-type", "type":"271" }],

    "tag":"meta-type","variants":

    [{ "case":"builtin", "type":"272" },{ "case":"enum", "type":"273" },{ "case":"array", "type":"274" },{ "case":"object", "type":"275" },{ "case":"alternate", "type":"276" },{ "case":"command", "type":"277" },{ "case":"event", "type":"278" }] }

  • Introspect SchemaInfo{ "name":"203", "meta-type":"object","meta-type":"object",

    "members":[{ "name":"name", "type":"str" },{ "name":"meta-type", "type":"271" }],

    "tag":"meta-type","variants":

    [{ "case":"builtin", "type":"272" },{ "case":"enum", "type":"273" },{ "case":"array", "type":"274" },{ "case":"object", "type":"275" },{ "case":"alternate", "type":"276" },{ "case":"command", "type":"277" },{ "case":"event", "type":"278" }] }

    It’s an object type

  • Introspect SchemaInfo{ "name":"203", "meta-type":"object",

    "members""members":[{ "name":"name""name", "type":"str" },{ "name":"meta-type""meta-type", "type":"271" }],

    "tag":"meta-type","variants":

    [{ "case":"builtin", "type":"272" },{ "case":"enum", "type":"273" },{ "case":"array", "type":"274" },{ "case":"object", "type":"275" },{ "case":"alternate", "type":"276" },{ "case":"command", "type":"277" },{ "case":"event", "type":"278" }] }

    It has a name and a meta-type (always)

  • Introspect SchemaInfo{ "name":"203", "meta-type":"object",

    "members":[{ "name":"name", "type":"str" },{ "name":"meta-type""meta-type", "type":"271" }],

    "tag":"meta-type""tag":"meta-type","variants""variants":

    [{ "case":"builtin", "type":"272" },{ "case":"enum", "type":"273" },{ "case":"array", "type":"274" },{ "case":"object", "type":"275" },{ "case":"alternate", "type":"276" },{ "case":"command", "type":"277" },{ "case":"event", "type":"278" }] }

    It has variants,and this is their tag

  • Introspect SchemaInfo{ "name":"203", "meta-type":"object",

    "members":[{ "name":"name", "type":"str" },{ "name":"meta-type", "type":"271""type":"271" }],

    "tag":"meta-type","variants":

    [{ "case":"builtin""builtin", "type":"272" },{ "case":"enum""enum", "type":"273" },{ "case":"array""array", "type":"274" },{ "case":"object""object", "type":"275" },{ "case":"alternate""alternate", "type":"276" },{ "case":"command""command", "type":"277" },{ "case":"event""event", "type":"278" }] }

    Each case applies to avalue of the tag’s type

  • Introspect SchemaInfo{ "name":"203", "meta-type":"object",

    "members":[{ "name":"name", "type":"str" },{ "name":"meta-type", "type":"271" }],

    "tag":"meta-type","variants":

    [{ "case":"builtin", "type":"272""type":"272" },{ "case":"enum", "type":"273""type":"273" },{ "case":"array", "type":"274""type":"274" },{ "case":"object", "type":"275""type":"275" },{ "case":"alternate", "type":"276""type":"276" },{ "case":"command", "type":"277""type":"277" },{ "case":"event", "type":"278""type":"278" }] }

    Variant members arejust another object type

  • The types of its name & tag

    { "name":"str""str","meta-type":"builtin""builtin","json-type":"string""string" }

    { "name":"271", "meta-type":"enum","values":

    ["builtin", "enum", "array", "object","alternate", "command", "event"] }

    The name’s type is “str”

    It’s a built-in type

    and on the wire it’s JSON string

  • The types of its name & tag

    { "name":"str","meta-type":"builtin","json-type":"string" }

    { "name":"271", "meta-type":"enum""enum","values":

    ["builtin", "enum", "array", "object","builtin", "enum", "array", "object","alternate", "command", "event""alternate", "command", "event"] }

    Tag’s type is an enumeration

    with these members

  • SchemaInfo’s enum variant

    { "name":"273","meta-type":"object""object","members":

    [{ "name":"values""values", "type":"270" }] },

    { "name":"270", "meta-type":"array","element-type":"str" }

    The case’s type is an object type

    It has just one member “values”

  • SchemaInfo’s enum variant

    { "name":"273","meta-type":"object","members":

    [{ "name":"values", "type":"270""270" }] },

    { "name":"270""270", "meta-type":"array""array","element-type":"str""str" }

    The type of “values” is array of str

  • Quick peek under the hood

    QAPI schema is compile time static so farSchemaInfo is generated from itGenerator is 160 SLOC of PythonThe necessary refactoring of core, however. . .Complete info is a bit over 70KiBShould probably support caching it(put hash in QMP greeting)Still work in progresshttp://repo.or.cz/qemu/armbru.gitqapi-introspect

    http://repo.or.cz/qemu/armbru.git

  • Part IVFuture work

  • QMP introspection limitations

    Known issues:Can see only qapified commands Can’t see device_addCan see only qapified arguments & resultsWe cheat for netdev_add. . . Can’t see most of netdev_add’s argumentsOnly as good as the qapificationadd_client takes arguments protocol, tlstls accepted only when protocol supports it Can’t see which protocols support TLS

  • Clean up qapification of netdev_add

    Need toqapify its type-specific arguments. . .without upsetting the QMP wire format

    Wire format matches QAPI/QMP’s flat union typePossible solution:

    Support unions as command argumentsCode up the matching flat union type

  • Qapify device_addWire format like netdev_add:

    common + driver-specific argumentsBut: drivers collected only at run time!

    QAPI schema fixed at compile time. . .Choices:

    Collect drivers at compile time? Hard. . .Make QAPI schema dynamic? Hard. . .Forgo driver-specific arguments in schema?Defeats introspection. . .

    No conclusion, yet

  • QAPI follow-up workOn the way to introspection, we

    got ourselves real test coveragereplaced our internal schema representationfixed many bugs, and marked more as FIXMEplugged many documentation holes

    Left to do:Fix the FIXMEsFinish transition to new internal representationClean up schema language and generated codeReview schema for imprecise qapifications

  • What about command line?Introspection needs the interface as dataGood: our command line definition is dataBad: not QAPI, less expressive, leaves more to codeChoices:

    Build non-QAPI command line introspection?Only as good as the data. . .Rebase command line onto QAPI? Hard. . .Use QMP introspection as witness instead?Assumes suitable witness exists. . .

    No conclusion, yet

  • Questions?

    What's the problem?Prior workQMP IntrospectionFuture work