diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in
index 3087d016e3..9c3c2e8313 100644
--- a/docs/formatdomain.html.in
+++ b/docs/formatdomain.html.in
@@ -1376,6 +1376,7 @@
<address bus='0x06' slot='0x02' function='0x0'/>
</source>
<boot order='1'/>
+ <rom bar='off'/>
</hostdev>
</devices>
...
@@ -1407,6 +1408,18 @@
used together with general boot elements in
BIOS bootloader section.
Since 0.8.8
+
rom
+
The rom element is used to change how a PCI
+ device's ROM is presented to the guest. The bar
+ 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"). Since
+ 0.9.7
+
address
The address element for USB devices has a
bus and device attribute to specify the
diff --git a/docs/schemas/domaincommon.rng b/docs/schemas/domaincommon.rng
index be98be03d6..4972fac0b2 100644
--- a/docs/schemas/domaincommon.rng
+++ b/docs/schemas/domaincommon.rng
@@ -2060,6 +2060,17 @@
+
+
+
+
+ on
+ off
+
+
+
+
+
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index a91867915a..c14198271b 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -443,6 +443,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")
@@ -5486,6 +5492,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);
@@ -10388,6 +10408,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, " \n", rombar);
+ }
+
virBufferAddLit(buf, " \n");
return 0;
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 86b4c799f7..0bc00426a4 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -937,6 +937,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 {
@@ -965,6 +973,7 @@ struct _virDomainHostdevDef {
} source;
int bootIndex;
virDomainDeviceInfo info; /* Guest address */
+ int rombar; /* enum virDomainPciRombarMode */
};
enum virDomainRedirdevBus {
@@ -1856,6 +1865,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 8235ea1276..c2a3fab277 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 4325f77101..a653243f34 100644
--- a/src/qemu/qemu_capabilities.c
+++ b/src/qemu/qemu_capabilities.c
@@ -139,6 +139,7 @@ VIR_ENUM_IMPL(qemuCaps, QEMU_CAPS_LAST,
"no-shutdown",
"cache-unsafe", /* 75 */
+ "rombar",
);
struct qemu_feature_flags {
@@ -1063,6 +1064,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 ae3de90ac9..062f239e72 100644
--- a/src/qemu/qemu_capabilities.h
+++ b/src/qemu/qemu_capabilities.h
@@ -113,6 +113,7 @@ enum qemuCapsFlags {
QEMU_CAPS_NO_SHUTDOWN = 74, /* usable -no-shutdown */
QEMU_CAPS_DRIVE_CACHE_UNSAFE = 75, /* Is cache=unsafe supported? */
+ QEMU_CAPS_PCI_ROMBAR = 76, /* -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 9174a5f4ef..a13ba71919 100644
--- a/src/qemu/qemu_command.c
+++ b/src/qemu/qemu_command.c
@@ -2369,6 +2369,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 0ff8236582..8a06568e53 100644
--- a/tests/qemuhelptest.c
+++ b/tests/qemuhelptest.c
@@ -314,7 +314,8 @@ mymain(void)
QEMU_CAPS_VGA_NONE,
QEMU_CAPS_MIGRATE_QEMU_FD,
QEMU_CAPS_DRIVE_AIO,
- QEMU_CAPS_NO_SHUTDOWN);
+ QEMU_CAPS_NO_SHUTDOWN,
+ QEMU_CAPS_PCI_ROMBAR);
DO_TEST("qemu-kvm-0.12.1.2-rhel60", 12001, 1, 0,
QEMU_CAPS_VNC_COLON,
QEMU_CAPS_NO_REBOOT,
@@ -359,7 +360,8 @@ mymain(void)
QEMU_CAPS_PIIX3_USB_UHCI,
QEMU_CAPS_PIIX4_USB_UHCI,
QEMU_CAPS_USB_HUB,
- QEMU_CAPS_NO_SHUTDOWN);
+ QEMU_CAPS_NO_SHUTDOWN,
+ QEMU_CAPS_PCI_ROMBAR);
DO_TEST("qemu-kvm-0.12.3", 12003, 1, 0,
QEMU_CAPS_VNC_COLON,
QEMU_CAPS_NO_REBOOT,
@@ -397,7 +399,8 @@ mymain(void)
QEMU_CAPS_VGA_NONE,
QEMU_CAPS_MIGRATE_QEMU_FD,
QEMU_CAPS_DRIVE_AIO,
- QEMU_CAPS_NO_SHUTDOWN);
+ QEMU_CAPS_NO_SHUTDOWN,
+ QEMU_CAPS_PCI_ROMBAR);
DO_TEST("qemu-kvm-0.13.0", 13000, 1, 0,
QEMU_CAPS_VNC_COLON,
QEMU_CAPS_NO_REBOOT,
@@ -451,7 +454,8 @@ mymain(void)
QEMU_CAPS_VT82C686B_USB_UHCI,
QEMU_CAPS_PCI_OHCI,
QEMU_CAPS_USB_HUB,
- QEMU_CAPS_NO_SHUTDOWN);
+ QEMU_CAPS_NO_SHUTDOWN,
+ QEMU_CAPS_PCI_ROMBAR);
DO_TEST("qemu-kvm-0.12.1.2-rhel61", 12001, 1, 0,
QEMU_CAPS_VNC_COLON,
QEMU_CAPS_NO_REBOOT,
@@ -501,7 +505,8 @@ mymain(void)
QEMU_CAPS_PIIX3_USB_UHCI,
QEMU_CAPS_PIIX4_USB_UHCI,
QEMU_CAPS_USB_HUB,
- QEMU_CAPS_NO_SHUTDOWN);
+ QEMU_CAPS_NO_SHUTDOWN,
+ 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 0000000000..1a8b14e83e
--- /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 0000000000..bf17cc49d0
--- /dev/null
+++ b/tests/qemuxml2argvdata/qemuxml2argv-hostdev-pci-rombar.xml
@@ -0,0 +1,29 @@
+
+ QEMUGuest2
+ c7a5fdbd-edaf-9466-926a-d65c16db1809
+ 219100
+ 219100
+ 1
+
+ hvm
+
+
+
+ destroy
+ restart
+ destroy
+
+ /usr/bin/qemu
+
+
+
+
+
+
+
+
+
+
+
+
+