[libvirt] [PATCH] qemu: add ability to set PCI device "rombar" on or off

This patch was made in response to: https://bugzilla.redhat.com/show_bug.cgi?id=738095 In short, qemu's default for the rombar setting (which makes the firmware ROM of a PCI device visible/not on the guest) was previously 0 (not visible), but they recently changed the default to 1 (visible). Unfortunately, there are some PCI devices that fail in the guest when rombar is 1, so the setting must be exposed in libvirt to prevent a regression in behavior (it will still require explicitly setting <rom bar='off'/> in the guest XML). rombar is forced on/off by adding: <rom bar='on|off'/> inside a <hostdev> element that defines a PCI device. It is currently ignored for all other types of devices. At the moment there is no clean method to determine whether or not the rombar option is supported by QEMU - this patch uses the advice of a QEMU developer to assume support for qemu-0.12+. There is currently a patch in the works to put this information in the output of "qemu-kvm -device pci-assign,?", but of course if we switch to keying off that, we would lose support for setting rombar on all the versions of qemu between 0.12 and whatever version gets that patch. --- docs/formatdomain.html.in | 12 +++++++ docs/schemas/domaincommon.rng | 10 ++++++ src/conf/domain_conf.c | 32 ++++++++++++++++++++ src/conf/domain_conf.h | 10 ++++++ src/qemu/qemu_capabilities.c | 4 ++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 19 ++++++++++++ tests/qemuhelptest.c | 15 ++++++--- .../qemuxml2argv-hostdev-pci-rombar.args | 5 +++ .../qemuxml2argv-hostdev-pci-rombar.xml | 29 ++++++++++++++++++ 10 files changed, 132 insertions(+), 5 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 0a7abaf..7654abf 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1371,6 +1371,7 @@ <address bus='0x06' slot='0x02' function='0x0'/> </source> <boot order='1'/> + <rom bar='0'/> </hostdev> </devices> ...</pre> @@ -1402,6 +1403,17 @@ used together with general boot elements in <a href="#elementsOSBIOS">BIOS bootloader</a> section. <span class="since">Since 0.8.8</span></dd> + <dt><code>rom</code></dt> + <dd>The <code>rom</code> element is used to change how a PCI + device's ROM is presented to the guest. The <code>bar</code> + attribute can be set to "on" or "off", and determines whether + or not the devices ROM will be visible in the guest's memory + map. (in PCI documentation, this is described as being + controlled by the "rombar" setting). If no rom bar is + specified, the qemu default will be used (older versions of + qemu used a default of "off", while newer qemus have a default + of "on"). <span class="since">Since 0.9.6</span> + </dd> <dt><code>address</code></dt> <dd>The <code>address</code> element for USB devices has a <code>bus</code> and <code>device</code> attribute to specify the diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index d0da41c..0ba35ef 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2059,6 +2059,16 @@ <optional> <ref name="address"/> </optional> + <optional> + <element name="rom"> + <attribute name="bar"> + <choice> + <value>on</value> + <value>off</value> + </choice> + </attribute> + </element> + </optional> </element> </define> <define name="usbproduct"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 7476447..d067415 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -442,6 +442,12 @@ VIR_ENUM_IMPL(virDomainHostdevSubsys, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST, "usb", "pci") +VIR_ENUM_IMPL(virDomainPciRombarMode, + VIR_DOMAIN_PCI_ROMBAR_LAST, + "default", + "on", + "off") + VIR_ENUM_IMPL(virDomainHub, VIR_DOMAIN_HUB_TYPE_LAST, "usb") @@ -5485,6 +5491,20 @@ virDomainHostdevDefParseXML(const xmlNodePtr node, if (virDomainDeviceBootParseXML(cur, &def->bootIndex, bootMap)) goto error; + } else if (xmlStrEqual(cur->name, BAD_CAST "rom")) { + char *rombar = virXMLPropString(cur, "bar"); + if (!rombar) { + virDomainReportError(VIR_ERR_XML_ERROR, + "%s", _("missing rom bar attribute")); + goto error; + } + if ((def->rombar = virDomainPciRombarModeTypeFromString(rombar)) <= 0) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown rom bar value '%s'"), rombar); + VIR_FREE(rombar); + goto error; + } + VIR_FREE(rombar); } else { virDomainReportError(VIR_ERR_INTERNAL_ERROR, _("unknown node %s"), cur->name); @@ -10387,6 +10407,18 @@ virDomainHostdevDefFormat(virBufferPtr buf, if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) return -1; + if (def->rombar) { + const char *rombar + = virDomainPciRombarModeTypeToString(def->rombar); + if (!rombar) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected rom bar value %d"), + def->rombar); + return -1; + } + virBufferAsprintf(buf, " <rom bar='%s'/>\n", rombar); + } + virBufferAddLit(buf, " </hostdev>\n"); return 0; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 371f270..262c970 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -936,6 +936,14 @@ enum virDomainHostdevSubsysType { VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST }; +enum virDomainPciRombarMode { + VIR_DOMAIN_PCI_ROMBAR_DEFAULT = 0, + VIR_DOMAIN_PCI_ROMBAR_ON, + VIR_DOMAIN_PCI_ROMBAR_OFF, + + VIR_DOMAIN_PCI_ROMBAR_LAST +}; + typedef struct _virDomainHostdevDef virDomainHostdevDef; typedef virDomainHostdevDef *virDomainHostdevDefPtr; struct _virDomainHostdevDef { @@ -964,6 +972,7 @@ struct _virDomainHostdevDef { } source; int bootIndex; virDomainDeviceInfo info; /* Guest address */ + int rombar; /* rombar on/off/unspecified */ }; enum virDomainRedirdevBus { @@ -1855,6 +1864,7 @@ VIR_ENUM_DECL(virDomainWatchdogAction) VIR_ENUM_DECL(virDomainVideo) VIR_ENUM_DECL(virDomainHostdevMode) VIR_ENUM_DECL(virDomainHostdevSubsys) +VIR_ENUM_DECL(virDomainPciRombarMode) VIR_ENUM_DECL(virDomainHub) VIR_ENUM_DECL(virDomainRedirdevBus) VIR_ENUM_DECL(virDomainInput) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 36f47a9..1b9260a 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -136,6 +136,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST, "pci-ohci", "usb-redir", "usb-hub", + "rombar", ); struct qemu_feature_flags { @@ -1049,6 +1050,9 @@ qemuCapsComputeCmdFlags(const char *help, if (version >= 13000) qemuCapsSet(flags, QEMU_CAPS_PCI_MULTIFUNCTION); + + if (version >= 12000) + qemuCapsSet(flags, QEMU_CAPS_PCI_ROMBAR); } /* We parse the output of 'qemu -help' to get the QEMU diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 96b7a3b..3557bcb 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -110,6 +110,7 @@ enum qemuCapsFlags { QEMU_CAPS_PCI_OHCI = 71, /* -device pci-ohci */ QEMU_CAPS_USB_REDIR = 72, /* -device usb-redir */ QEMU_CAPS_USB_HUB = 73, /* -device usb-hub */ + QEMU_CAPS_PCI_ROMBAR = 74, /* -device rombar=0|1 */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index e8b1157..056927b 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2361,6 +2361,25 @@ qemuBuildPCIHostdevDevStr(virDomainHostdevDefPtr dev, const char *configfd, if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0) goto error; + if (dev->rombar) { + if (!qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_ROMBAR)) { + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("rombar not supported in this QEMU binary")); + goto error; + } + + switch (dev->rombar) { + case VIR_DOMAIN_PCI_ROMBAR_OFF: + virBufferAddLit(&buf, ",rombar=0"); + break; + case VIR_DOMAIN_PCI_ROMBAR_ON: + virBufferAddLit(&buf, ",rombar=1"); + break; + default: + break; + } + } + if (virBufferError(&buf)) { virReportOOMError(); goto error; diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index ffd30e2..17f160e 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -306,7 +306,8 @@ mymain(void) QEMU_CAPS_SMBIOS_TYPE, QEMU_CAPS_VGA_NONE, QEMU_CAPS_MIGRATE_QEMU_FD, - QEMU_CAPS_DRIVE_AIO); + QEMU_CAPS_DRIVE_AIO, + QEMU_CAPS_PCI_ROMBAR); DO_TEST("qemu-kvm-0.12.1.2-rhel60", 12001, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -350,7 +351,8 @@ mymain(void) QEMU_CAPS_DEVICE_SPICEVMC, QEMU_CAPS_PIIX3_USB_UHCI, QEMU_CAPS_PIIX4_USB_UHCI, - QEMU_CAPS_USB_HUB); + QEMU_CAPS_USB_HUB, + QEMU_CAPS_PCI_ROMBAR); DO_TEST("qemu-kvm-0.12.3", 12003, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -387,7 +389,8 @@ mymain(void) QEMU_CAPS_SMBIOS_TYPE, QEMU_CAPS_VGA_NONE, QEMU_CAPS_MIGRATE_QEMU_FD, - QEMU_CAPS_DRIVE_AIO); + QEMU_CAPS_DRIVE_AIO, + QEMU_CAPS_PCI_ROMBAR); DO_TEST("qemu-kvm-0.13.0", 13000, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -439,7 +442,8 @@ mymain(void) QEMU_CAPS_PIIX4_USB_UHCI, QEMU_CAPS_VT82C686B_USB_UHCI, QEMU_CAPS_PCI_OHCI, - QEMU_CAPS_USB_HUB); + QEMU_CAPS_USB_HUB, + QEMU_CAPS_PCI_ROMBAR); DO_TEST("qemu-kvm-0.12.1.2-rhel61", 12001, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -487,7 +491,8 @@ mymain(void) QEMU_CAPS_VIRTIO_IOEVENTFD, QEMU_CAPS_PIIX3_USB_UHCI, QEMU_CAPS_PIIX4_USB_UHCI, - QEMU_CAPS_USB_HUB); + QEMU_CAPS_USB_HUB, + QEMU_CAPS_PCI_ROMBAR); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.args new file mode 100644 index 0000000..1a8b14e --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.args @@ -0,0 +1,5 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ +unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \ +/dev/HostVG/QEMUGuest2 -usb -device pci-assign,host=06:12.5,id=hostdev0,\ +bus=pci.0,addr=0x3,rombar=0 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.xml new file mode 100644 index 0000000..bf17cc4 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.xml @@ -0,0 +1,29 @@ +<domain type='qemu'> + <name>QEMUGuest2</name> + <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid> + <memory>219100</memory> + <currentMemory>219100</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest2'/> + <target dev='hda' bus='ide'/> + </disk> + <hostdev mode='subsystem' type='pci' managed='yes'> + <source> + <address domain='0x0000' bus='0x06' slot='0x12' function='0x5'/> + </source> + <rom bar='off'/> + </hostdev> + <memballoon model='virtio'/> + </devices> +</domain> -- 1.7.3.4

On 09/21/2011 10:25 AM, Laine Stump wrote:
This patch was made in response to:
https://bugzilla.redhat.com/show_bug.cgi?id=738095
In short, qemu's default for the rombar setting (which makes the firmware ROM of a PCI device visible/not on the guest) was previously 0 (not visible), but they recently changed the default to 1 (visible). Unfortunately, there are some PCI devices that fail in the guest when rombar is 1, so the setting must be exposed in libvirt to prevent a regression in behavior (it will still require explicitly setting<rom bar='off'/> in the guest XML).
rombar is forced on/off by adding:
<rom bar='on|off'/>
inside a<hostdev> element that defines a PCI device. It is currently ignored for all other types of devices.
I'm leaning towards deferring this until after a quick 0.9.6 release that works around the qemu shutdown issue. That said, I'll still review the patch.
At the moment there is no clean method to determine whether or not the rombar option is supported by QEMU - this patch uses the advice of a QEMU developer to assume support for qemu-0.12+. There is currently a patch in the works to put this information in the output of "qemu-kvm -device pci-assign,?", but of course if we switch to keying off that, we would lose support for setting rombar on all the versions of qemu between 0.12 and whatever version gets that patch.
Hopefully the assumption is close enough to correct, and qemu will give us error messages if our request is inappropriate.
+<dt><code>rom</code></dt> +<dd>The<code>rom</code> element is used to change how a PCI + device's ROM is presented to the guest. The<code>bar</code> + attribute can be set to "on" or "off", and determines whether + or not the devices ROM will be visible in the guest's memory
s/devices/device's/
+ map. (in PCI documentation, this is described as being
s/in/In/
+ controlled by the "rombar" setting). If no rom bar is
Maybe mention what the BAR acronym expands to (am I correct that it means Base Address Register?), as in: (In PCI documentation, the "rombar" setting controls the presence of the Base Address Register for the ROM.)
+ specified, the qemu default will be used (older versions of + qemu used a default of "off", while newer qemus have a default + of "on").<span class="since">Since 0.9.6</span> +</dd> <dt><code>address</code></dt> <dd>The<code>address</code> element for USB devices has a <code>bus</code> and<code>device</code> attribute to specify the diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index d0da41c..0ba35ef 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2059,6 +2059,16 @@ <optional> <ref name="address"/> </optional> +<optional> +<element name="rom"> +<attribute name="bar">
I think you need another layer of <optional> around the <attribute>; that is, the user can do <rom/> which should be just as valid XML as: <rom bar="on"/> even if we never generate it ourselves.
+<choice> +<value>on</value> +<value>off</value> +</choice> +</attribute>
I think you need <empty/> here as well.
@@ -5485,6 +5491,20 @@ virDomainHostdevDefParseXML(const xmlNodePtr node, if (virDomainDeviceBootParseXML(cur,&def->bootIndex, bootMap)) goto error; + } else if (xmlStrEqual(cur->name, BAD_CAST "rom")) { + char *rombar = virXMLPropString(cur, "bar"); + if (!rombar) { + virDomainReportError(VIR_ERR_XML_ERROR, + "%s", _("missing rom bar attribute")); + goto error; + }
Oh, I guess you're making it a hard error if bar=... is not present, in which case my comment about another layer of <optional> can be disregarded.
@@ -1855,6 +1864,7 @@ VIR_ENUM_DECL(virDomainWatchdogAction) VIR_ENUM_DECL(virDomainVideo) VIR_ENUM_DECL(virDomainHostdevMode) VIR_ENUM_DECL(virDomainHostdevSubsys) +VIR_ENUM_DECL(virDomainPciRombarMode) VIR_ENUM_DECL(virDomainHub) VIR_ENUM_DECL(virDomainRedirdevBus) VIR_ENUM_DECL(virDomainInput)
Export the two new symbols (virDomainPciRombarModeType{To,From}String) in src/libvirt_private.syms.
@@ -1049,6 +1050,9 @@ qemuCapsComputeCmdFlags(const char *help,
if (version>= 13000) qemuCapsSet(flags, QEMU_CAPS_PCI_MULTIFUNCTION); + + if (version>= 12000) + qemuCapsSet(flags, QEMU_CAPS_PCI_ROMBAR);
Maybe add a comment why we use a version check rather than probing for pci-assign.rombar=uint32 in 'qemu -device pci-assign,?'. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

(This addresses Eric's comments in his review of V1. BTW, I'm a bit surprised nobody has commented about the choice of name/placement of the new attribute - speak now or forever hold your peace :-)) This patch was made in response to: https://bugzilla.redhat.com/show_bug.cgi?id=738095 In short, qemu's default for the rombar setting (which makes the firmware ROM of a PCI device visible/not on the guest) was previously 0 (not visible), but they recently changed the default to 1 (visible). Unfortunately, there are some PCI devices that fail in the guest when rombar is 1, so the setting must be exposed in libvirt to prevent a regression in behavior (it will still require explicitly setting <rom bar='off'/> in the guest XML). rombar is forced on/off by adding: <rom bar='on|off'/> inside a <hostdev> element that defines a PCI device. It is currently ignored for all other types of devices. At the moment there is no clean method to determine whether or not the rombar option is supported by QEMU - this patch uses the advice of a QEMU developer to assume support for qemu-0.12+. There is currently a patch in the works to put this information in the output of "qemu-kvm -device pci-assign,?", but of course if we switch to keying off that, we would lose support for setting rombar on all the versions of qemu between 0.12 and whatever version gets that patch. --- docs/formatdomain.html.in | 13 ++++++++ docs/schemas/domaincommon.rng | 11 +++++++ src/conf/domain_conf.c | 32 ++++++++++++++++++++ src/conf/domain_conf.h | 10 ++++++ src/libvirt_private.syms | 2 + src/qemu/qemu_capabilities.c | 14 ++++++++ src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 19 ++++++++++++ tests/qemuhelptest.c | 15 ++++++--- .../qemuxml2argv-hostdev-pci-rombar.args | 5 +++ .../qemuxml2argv-hostdev-pci-rombar.xml | 29 ++++++++++++++++++ 11 files changed, 146 insertions(+), 5 deletions(-) create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.args create mode 100644 tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.xml diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 0a7abaf..859073e 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -1371,6 +1371,7 @@ <address bus='0x06' slot='0x02' function='0x0'/> </source> <boot order='1'/> + <rom bar='0'/> </hostdev> </devices> ...</pre> @@ -1402,6 +1403,18 @@ used together with general boot elements in <a href="#elementsOSBIOS">BIOS bootloader</a> section. <span class="since">Since 0.8.8</span></dd> + <dt><code>rom</code></dt> + <dd>The <code>rom</code> element is used to change how a PCI + device's ROM is presented to the guest. The <code>bar</code> + attribute can be set to "on" or "off", and determines whether + or not the device's ROM will be visible in the guest's memory + map. (In PCI documentation, the "rombar" setting controls the + presence of the Base Address Register for the ROM). If no rom + bar is specified, the qemu default will be used (older + versions of qemu used a default of "off", while newer qemus + have a default of "on"). <span class="since">Since + 0.9.6</span> + </dd> <dt><code>address</code></dt> <dd>The <code>address</code> element for USB devices has a <code>bus</code> and <code>device</code> attribute to specify the diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng index d0da41c..87b7383 100644 --- a/docs/schemas/domaincommon.rng +++ b/docs/schemas/domaincommon.rng @@ -2059,6 +2059,17 @@ <optional> <ref name="address"/> </optional> + <optional> + <element name="rom"> + <attribute name="bar"> + <choice> + <value>on</value> + <value>off</value> + </choice> + </attribute> + <empty/> + </element> + </optional> </element> </define> <define name="usbproduct"> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index 7476447..d067415 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -442,6 +442,12 @@ VIR_ENUM_IMPL(virDomainHostdevSubsys, VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST, "usb", "pci") +VIR_ENUM_IMPL(virDomainPciRombarMode, + VIR_DOMAIN_PCI_ROMBAR_LAST, + "default", + "on", + "off") + VIR_ENUM_IMPL(virDomainHub, VIR_DOMAIN_HUB_TYPE_LAST, "usb") @@ -5485,6 +5491,20 @@ virDomainHostdevDefParseXML(const xmlNodePtr node, if (virDomainDeviceBootParseXML(cur, &def->bootIndex, bootMap)) goto error; + } else if (xmlStrEqual(cur->name, BAD_CAST "rom")) { + char *rombar = virXMLPropString(cur, "bar"); + if (!rombar) { + virDomainReportError(VIR_ERR_XML_ERROR, + "%s", _("missing rom bar attribute")); + goto error; + } + if ((def->rombar = virDomainPciRombarModeTypeFromString(rombar)) <= 0) { + virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("unknown rom bar value '%s'"), rombar); + VIR_FREE(rombar); + goto error; + } + VIR_FREE(rombar); } else { virDomainReportError(VIR_ERR_INTERNAL_ERROR, _("unknown node %s"), cur->name); @@ -10387,6 +10407,18 @@ virDomainHostdevDefFormat(virBufferPtr buf, if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) return -1; + if (def->rombar) { + const char *rombar + = virDomainPciRombarModeTypeToString(def->rombar); + if (!rombar) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected rom bar value %d"), + def->rombar); + return -1; + } + virBufferAsprintf(buf, " <rom bar='%s'/>\n", rombar); + } + virBufferAddLit(buf, " </hostdev>\n"); return 0; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 371f270..262c970 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -936,6 +936,14 @@ enum virDomainHostdevSubsysType { VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST }; +enum virDomainPciRombarMode { + VIR_DOMAIN_PCI_ROMBAR_DEFAULT = 0, + VIR_DOMAIN_PCI_ROMBAR_ON, + VIR_DOMAIN_PCI_ROMBAR_OFF, + + VIR_DOMAIN_PCI_ROMBAR_LAST +}; + typedef struct _virDomainHostdevDef virDomainHostdevDef; typedef virDomainHostdevDef *virDomainHostdevDefPtr; struct _virDomainHostdevDef { @@ -964,6 +972,7 @@ struct _virDomainHostdevDef { } source; int bootIndex; virDomainDeviceInfo info; /* Guest address */ + int rombar; /* rombar on/off/unspecified */ }; enum virDomainRedirdevBus { @@ -1855,6 +1864,7 @@ VIR_ENUM_DECL(virDomainWatchdogAction) VIR_ENUM_DECL(virDomainVideo) VIR_ENUM_DECL(virDomainHostdevMode) VIR_ENUM_DECL(virDomainHostdevSubsys) +VIR_ENUM_DECL(virDomainPciRombarMode) VIR_ENUM_DECL(virDomainHub) VIR_ENUM_DECL(virDomainRedirdevBus) VIR_ENUM_DECL(virDomainInput) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 8235ea1..c2a3fab 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -385,6 +385,8 @@ virDomainObjUnlock; virDomainObjUnref; virDomainPausedReasonTypeFromString; virDomainPausedReasonTypeToString; +virDomainPciRombarModeTypeFromString; +virDomainPciRombarModeTypeToString; virDomainRedirdevBusTypeFromString; virDomainRedirdevBusTypeToString; virDomainRemoveInactive; diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 36f47a9..24c60b6 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -136,6 +136,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST, "pci-ohci", "usb-redir", "usb-hub", + "rombar", ); struct qemu_feature_flags { @@ -1049,6 +1050,19 @@ qemuCapsComputeCmdFlags(const char *help, if (version >= 13000) qemuCapsSet(flags, QEMU_CAPS_PCI_MULTIFUNCTION); + + /* Although very new versions of qemu advertise the presence of + * the rombar option in the output of "qemu -device pci-assign,?", + * this advertisement was added to the code long after the option + * itself. According to qemu developers, though, rombar is + * available in all qemu binaries from release 0.12 onward. + * Setting the capability this way makes it available in more + * cases where it might be needed, and shouldn't cause any false + * positives (in the case that it did, qemu would produce an error + * log and refuse to start, so it would be immediately obvious). + */ + if (version >= 12000) + qemuCapsSet(flags, QEMU_CAPS_PCI_ROMBAR); } /* We parse the output of 'qemu -help' to get the QEMU diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index 96b7a3b..3557bcb 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -110,6 +110,7 @@ enum qemuCapsFlags { QEMU_CAPS_PCI_OHCI = 71, /* -device pci-ohci */ QEMU_CAPS_USB_REDIR = 72, /* -device usb-redir */ QEMU_CAPS_USB_HUB = 73, /* -device usb-hub */ + QEMU_CAPS_PCI_ROMBAR = 74, /* -device rombar=0|1 */ QEMU_CAPS_LAST, /* this must always be the last item */ }; diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index e8b1157..056927b 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -2361,6 +2361,25 @@ qemuBuildPCIHostdevDevStr(virDomainHostdevDefPtr dev, const char *configfd, if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCaps) < 0) goto error; + if (dev->rombar) { + if (!qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_ROMBAR)) { + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, + "%s", _("rombar not supported in this QEMU binary")); + goto error; + } + + switch (dev->rombar) { + case VIR_DOMAIN_PCI_ROMBAR_OFF: + virBufferAddLit(&buf, ",rombar=0"); + break; + case VIR_DOMAIN_PCI_ROMBAR_ON: + virBufferAddLit(&buf, ",rombar=1"); + break; + default: + break; + } + } + if (virBufferError(&buf)) { virReportOOMError(); goto error; diff --git a/tests/qemuhelptest.c b/tests/qemuhelptest.c index ffd30e2..17f160e 100644 --- a/tests/qemuhelptest.c +++ b/tests/qemuhelptest.c @@ -306,7 +306,8 @@ mymain(void) QEMU_CAPS_SMBIOS_TYPE, QEMU_CAPS_VGA_NONE, QEMU_CAPS_MIGRATE_QEMU_FD, - QEMU_CAPS_DRIVE_AIO); + QEMU_CAPS_DRIVE_AIO, + QEMU_CAPS_PCI_ROMBAR); DO_TEST("qemu-kvm-0.12.1.2-rhel60", 12001, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -350,7 +351,8 @@ mymain(void) QEMU_CAPS_DEVICE_SPICEVMC, QEMU_CAPS_PIIX3_USB_UHCI, QEMU_CAPS_PIIX4_USB_UHCI, - QEMU_CAPS_USB_HUB); + QEMU_CAPS_USB_HUB, + QEMU_CAPS_PCI_ROMBAR); DO_TEST("qemu-kvm-0.12.3", 12003, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -387,7 +389,8 @@ mymain(void) QEMU_CAPS_SMBIOS_TYPE, QEMU_CAPS_VGA_NONE, QEMU_CAPS_MIGRATE_QEMU_FD, - QEMU_CAPS_DRIVE_AIO); + QEMU_CAPS_DRIVE_AIO, + QEMU_CAPS_PCI_ROMBAR); DO_TEST("qemu-kvm-0.13.0", 13000, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -439,7 +442,8 @@ mymain(void) QEMU_CAPS_PIIX4_USB_UHCI, QEMU_CAPS_VT82C686B_USB_UHCI, QEMU_CAPS_PCI_OHCI, - QEMU_CAPS_USB_HUB); + QEMU_CAPS_USB_HUB, + QEMU_CAPS_PCI_ROMBAR); DO_TEST("qemu-kvm-0.12.1.2-rhel61", 12001, 1, 0, QEMU_CAPS_VNC_COLON, QEMU_CAPS_NO_REBOOT, @@ -487,7 +491,8 @@ mymain(void) QEMU_CAPS_VIRTIO_IOEVENTFD, QEMU_CAPS_PIIX3_USB_UHCI, QEMU_CAPS_PIIX4_USB_UHCI, - QEMU_CAPS_USB_HUB); + QEMU_CAPS_USB_HUB, + QEMU_CAPS_PCI_ROMBAR); return ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.args b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.args new file mode 100644 index 0000000..1a8b14e --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.args @@ -0,0 +1,5 @@ +LC_ALL=C PATH=/bin HOME=/home/test USER=test LOGNAME=test /usr/bin/qemu -S -M \ +pc -m 214 -smp 1 -nographic -nodefconfig -nodefaults -monitor \ +unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \ +/dev/HostVG/QEMUGuest2 -usb -device pci-assign,host=06:12.5,id=hostdev0,\ +bus=pci.0,addr=0x3,rombar=0 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x4 diff --git a/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.xml b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.xml new file mode 100644 index 0000000..bf17cc4 --- /dev/null +++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.xml @@ -0,0 +1,29 @@ +<domain type='qemu'> + <name>QEMUGuest2</name> + <uuid>c7a5fdbd-edaf-9466-926a-d65c16db1809</uuid> + <memory>219100</memory> + <currentMemory>219100</currentMemory> + <vcpu>1</vcpu> + <os> + <type arch='i686' machine='pc'>hvm</type> + <boot dev='hd'/> + </os> + <clock offset='utc'/> + <on_poweroff>destroy</on_poweroff> + <on_reboot>restart</on_reboot> + <on_crash>destroy</on_crash> + <devices> + <emulator>/usr/bin/qemu</emulator> + <disk type='block' device='disk'> + <source dev='/dev/HostVG/QEMUGuest2'/> + <target dev='hda' bus='ide'/> + </disk> + <hostdev mode='subsystem' type='pci' managed='yes'> + <source> + <address domain='0x0000' bus='0x06' slot='0x12' function='0x5'/> + </source> + <rom bar='off'/> + </hostdev> + <memballoon model='virtio'/> + </devices> +</domain> -- 1.7.3.4

On 09/22/2011 10:05 AM, Laine Stump wrote:
(This addresses Eric's comments in his review of V1. BTW, I'm a bit surprised nobody has commented about the choice of name/placement of the new attribute - speak now or forever hold your peace :-))
I was okay with the xml naming - but I agree that if anyone else has a better suggestion, now is the time to speak up :)
This patch was made in response to:
https://bugzilla.redhat.com/show_bug.cgi?id=738095
In short, qemu's default for the rombar setting (which makes the firmware ROM of a PCI device visible/not on the guest) was previously 0 (not visible), but they recently changed the default to 1 (visible). Unfortunately, there are some PCI devices that fail in the guest when rombar is 1, so the setting must be exposed in libvirt to prevent a regression in behavior (it will still require explicitly setting<rom bar='off'/> in the guest XML).
rombar is forced on/off by adding:
<rom bar='on|off'/>
inside a<hostdev> element that defines a PCI device. It is currently ignored for all other types of devices.
+++ b/docs/formatdomain.html.in @@ -1371,6 +1371,7 @@ <address bus='0x06' slot='0x02' function='0x0'/> </source> <boot order='1'/> +<rom bar='0'/>
s/0/off/
</hostdev> </devices> ...</pre> @@ -1402,6 +1403,18 @@ used together with general boot elements in <a href="#elementsOSBIOS">BIOS bootloader</a> section. <span class="since">Since 0.8.8</span></dd> +<dt><code>rom</code></dt> +<dd>The<code>rom</code> element is used to change how a PCI + device's ROM is presented to the guest. The<code>bar</code> + attribute can be set to "on" or "off", and determines whether + or not the device's ROM will be visible in the guest's memory + map. (In PCI documentation, the "rombar" setting controls the + presence of the Base Address Register for the ROM). If no rom + bar is specified, the qemu default will be used (older + versions of qemu used a default of "off", while newer qemus + have a default of "on").<span class="since">Since + 0.9.6</span>
looks much nicer, now that my v1 comments are incorporated, but still one nit: s/0.9.6/0.9.7/
@@ -10387,6 +10407,18 @@ virDomainHostdevDefFormat(virBufferPtr buf, if (virDomainDeviceInfoFormat(buf,&def->info, flags)< 0) return -1;
+ if (def->rombar) { + const char *rombar + = virDomainPciRombarModeTypeToString(def->rombar); + if (!rombar) { + virDomainReportError(VIR_ERR_INTERNAL_ERROR, + _("unexpected rom bar value %d"), + def->rombar); + return -1; + } + virBufferAsprintf(buf, "<rom bar='%s'/>\n", rombar);
Aargh - Thunderbird strikes me again. When will they EVER fix their horrible whitespace munging bug? This will conflict with my <snapshotdomain> reindentation patch series - so whoever applies first gets the easier side of the bargain :)
+ } + virBufferAddLit(buf, "</hostdev>\n");
return 0; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 371f270..262c970 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -936,6 +936,14 @@ enum virDomainHostdevSubsysType { VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_LAST };
+enum virDomainPciRombarMode { + VIR_DOMAIN_PCI_ROMBAR_DEFAULT = 0, + VIR_DOMAIN_PCI_ROMBAR_ON, + VIR_DOMAIN_PCI_ROMBAR_OFF, + + VIR_DOMAIN_PCI_ROMBAR_LAST +}; + typedef struct _virDomainHostdevDef virDomainHostdevDef; typedef virDomainHostdevDef *virDomainHostdevDefPtr; struct _virDomainHostdevDef { @@ -964,6 +972,7 @@ struct _virDomainHostdevDef { } source; int bootIndex; virDomainDeviceInfo info; /* Guest address */ + int rombar; /* rombar on/off/unspecified */
Your comment could go out of date if the enum grows. Lately, I've been listing fields like this as: int rombar; /* enum virDomainPciRombarMode */ which stays correct even if we later add new values to the enum.
+++ b/src/qemu/qemu_capabilities.h @@ -110,6 +110,7 @@ enum qemuCapsFlags { QEMU_CAPS_PCI_OHCI = 71, /* -device pci-ohci */ QEMU_CAPS_USB_REDIR = 72, /* -device usb-redir */ QEMU_CAPS_USB_HUB = 73, /* -device usb-hub */ + QEMU_CAPS_PCI_ROMBAR = 74, /* -device rombar=0|1 */
Needs an obvious rebase for NO_SHUTDOWN and DRIVE_CACHE_UNSAFE. ACK to the idea. I think my findings are small enough that I'm okay if you push with nits fixed rather than posting a v3 patch, although you may still want to wait for any other comments on the proposed xml spelling. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

On Fri, Sep 23, 2011 at 10:35:19AM -0600, Eric Blake wrote:
On 09/22/2011 10:05 AM, Laine Stump wrote:
(This addresses Eric's comments in his review of V1. BTW, I'm a bit surprised nobody has commented about the choice of name/placement of the new attribute - speak now or forever hold your peace :-))
I was okay with the xml naming - but I agree that if anyone else has a better suggestion, now is the time to speak up :)
This patch was made in response to:
https://bugzilla.redhat.com/show_bug.cgi?id=738095
In short, qemu's default for the rombar setting (which makes the firmware ROM of a PCI device visible/not on the guest) was previously 0 (not visible), but they recently changed the default to 1 (visible). Unfortunately, there are some PCI devices that fail in the guest when rombar is 1, so the setting must be exposed in libvirt to prevent a regression in behavior (it will still require explicitly setting<rom bar='off'/> in the guest XML).
rombar is forced on/off by adding:
<rom bar='on|off'/>
inside a<hostdev> element that defines a PCI device. It is currently ignored for all other types of devices.
Fine by me. The doc section explain that behaviour is unclear if not set (i.e. default to qemu's and that changed), so all fine IMHO Daniel -- Daniel Veillard | libxml Gnome XML XSLT toolkit http://xmlsoft.org/ daniel@veillard.com | Rpmfind RPM search engine http://rpmfind.net/ http://veillard.com/ | virtualization library http://libvirt.org/

On 09/27/2011 02:53 AM, Daniel Veillard wrote:
On Fri, Sep 23, 2011 at 10:35:19AM -0600, Eric Blake wrote:
On 09/22/2011 10:05 AM, Laine Stump wrote:
(This addresses Eric's comments in his review of V1. BTW, I'm a bit surprised nobody has commented about the choice of name/placement of the new attribute - speak now or forever hold your peace :-)) I was okay with the xml naming - but I agree that if anyone else has a better suggestion, now is the time to speak up :) This patch was made in response to:
https://bugzilla.redhat.com/show_bug.cgi?id=738095
In short, qemu's default for the rombar setting (which makes the firmware ROM of a PCI device visible/not on the guest) was previously 0 (not visible), but they recently changed the default to 1 (visible). Unfortunately, there are some PCI devices that fail in the guest when rombar is 1, so the setting must be exposed in libvirt to prevent a regression in behavior (it will still require explicitly setting<rom bar='off'/> in the guest XML).
rombar is forced on/off by adding:
<rom bar='on|off'/>
inside a<hostdev> element that defines a PCI device. It is currently ignored for all other types of devices. Fine by me. The doc section explain that behaviour is unclear if not set (i.e. default to qemu's and that changed), so all fine IMHO
Okay, I made the last few changed Eric noted and pushed. Thanks!
participants (3)
-
Daniel Veillard
-
Eric Blake
-
Laine Stump