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