]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
qemu: add "romfile" support to specify device boot ROM
authorLaine Stump <laine@laine.org>
Wed, 25 Jan 2012 16:20:49 +0000 (11:20 -0500)
committerLaine Stump <laine@laine.org>
Mon, 30 Jan 2012 17:30:35 +0000 (12:30 -0500)
This patch addresses: https://bugzilla.redhat.com/show_bug.cgi?id=781562

Along with the "rombar" option that controls whether or not a boot rom
is made visible to the guest, qemu also has a "romfile" option that
allows specifying a binary file to present as the ROM BIOS of any
emulated or passthrough PCI device. This patch adds support for
specifying romfile to both passthrough PCI devices, and emulated
network devices that attach to the guest's PCI bus (just about
everything other than ne2k_isa).

One example of the usefulness of this option is described in the
bugzilla report: 82576 sriov network adapters don't provide a ROM BIOS
for the cards virtual functions (VF), but an image of such a ROM is
available, and with this ROM visible to the guest, it can PXE boot.

In libvirt's xml, the new option is configured like this:

   <hostdev>
     ...
     <rom file='/etc/fake/boot.bin'/>
     ...
   </hostdev

(similarly for <interface>).

docs/formatdomain.html.in
docs/schemas/domaincommon.rng
src/conf/domain_conf.c
src/conf/domain_conf.h
src/qemu/qemu_command.c
tests/qemuxml2argvdata/qemuxml2argv-pci-rom.args
tests/qemuxml2argvdata/qemuxml2argv-pci-rom.xml

index e90e99f569f606fc32fcb9fd74ba89b1b8acb515..ab84730b8f9da545c70d52fc38841735fe8a32c9 100644 (file)
         &lt;address bus='0x06' slot='0x02' function='0x0'/&gt;
       &lt;/source&gt;
       &lt;boot order='1'/&gt;
-      &lt;rom bar='off'/&gt;
+      &lt;rom bar='on' file='/etc/fake/boot.bin'/&gt;
     &lt;/hostdev&gt;
   &lt;/devices&gt;
   ...</pre>
       <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>
+        device's ROM is presented to the guest. The optional <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
         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.7</span>
+        0.9.7 (QEMU and KVM only)</span>. The optional
+        <code>file</code> attribute is used to point to a binary file
+        to be presented to the guest as the device's ROM BIOS. This
+        can be useful, for example, to provide a PXE boot ROM for a
+        virtual function of an sr-iov capable ethernet device (which
+        has no boot ROMs for the VFs).
+        <span class="since">Since 0.9.10 (QEMU and KVM only)</span>.
       </dd>
       <dt><code>address</code></dt>
       <dd>The <code>address</code> element for USB devices has a
@@ -2492,7 +2498,7 @@ qemu-kvm -net nic,model=? /dev/null
     &lt;interface type='network'&gt;
       &lt;source network='default'/&gt;
       &lt;target dev='vnet1'/&gt;
-      <b>&lt;rom bar='off'/&gt;</b>
+      <b>&lt;rom bar='on' file='/etc/fake/boot.bin'/&gt;</b>
     &lt;/interface&gt;
   &lt;/devices&gt;
   ...</pre>
@@ -2506,8 +2512,12 @@ qemu-kvm -net nic,model=? /dev/null
       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.10 (QEMU and KVM only)</span>
+      have a default of "on").
+      The optional <code>file</code> attribute is used to point to a
+      binary file to be presented to the guest as the device's ROM
+      BIOS. This can be useful to provide an alternative boot ROM for a
+      network device.
+      <span class="since">Since 0.9.10 (QEMU and KVM only)</span>.
     </p>
 
     <h5><a name="elementQoS">Quality of service</a></h5>
index 7557641438ddc5d6df8ca7f07d51257b89424781..ee4270ab561d17bc3b5f592988d5b38ba68e26ea 100644 (file)
 
   <define name="rom">
     <element name="rom">
-      <attribute name="bar">
-        <choice>
-          <value>on</value>
-          <value>off</value>
-        </choice>
-      </attribute>
+      <optional>
+        <attribute name="bar">
+          <choice>
+            <value>on</value>
+            <value>off</value>
+          </choice>
+        </attribute>
+      </optional>
+      <optional>
+        <attribute name="file">
+          <ref name="absFilePath"/>
+        </attribute>
+      </optional>
       <empty/>
     </element>
   </define>
index b7f6913fe6de5cce775013083969b2efd3770ca9..4803cdf33fcae30e3d4956d83fa91652d4f1c64d 100644 (file)
@@ -1812,6 +1812,7 @@ void virDomainDeviceInfoClear(virDomainDeviceInfoPtr info)
     }
     memset(&info->addr, 0, sizeof(info->addr));
     info->type = VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE;
+    VIR_FREE(info->romfile);
 }
 
 
@@ -1924,16 +1925,25 @@ virDomainDeviceInfoFormat(virBufferPtr buf,
                           info->master.usb.startport);
     }
 
-    if ((flags & VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM) && info->rombar) {
-        const char *rombar
-            = virDomainPciRombarModeTypeToString(info->rombar);
-        if (!rombar) {
-            virDomainReportError(VIR_ERR_INTERNAL_ERROR,
-                                 _("unexpected rom bar value %d"),
-                                 info->rombar);
-            return -1;
+    if ((flags & VIR_DOMAIN_XML_INTERNAL_ALLOW_ROM) &&
+        (info->rombar || info->romfile)) {
+
+        virBufferAddLit(buf, "      <rom");
+        if (info->rombar) {
+
+            const char *rombar = virDomainPciRombarModeTypeToString(info->rombar);
+
+            if (!rombar) {
+                virDomainReportError(VIR_ERR_INTERNAL_ERROR,
+                                     _("unexpected rom bar value %d"),
+                                     info->rombar);
+                return -1;
+            }
+            virBufferAsprintf(buf, " bar='%s'", rombar);
         }
-        virBufferAsprintf(buf, "      <rom bar='%s'/>\n", rombar);
+        if (info->romfile)
+            virBufferAsprintf(buf, " file='%s'", info->romfile);
+        virBufferAddLit(buf, "/>\n");
     }
 
     if (info->type == VIR_DOMAIN_DEVICE_ADDRESS_TYPE_NONE)
@@ -2390,18 +2400,15 @@ virDomainDeviceInfoParseXML(xmlNodePtr node,
 
     if (rom) {
         char *rombar = virXMLPropString(rom, "bar");
-        if (!rombar) {
-            virDomainReportError(VIR_ERR_XML_ERROR,
-                                 "%s", _("missing rom bar attribute"));
-            goto cleanup;
-        }
-        if ((info->rombar = virDomainPciRombarModeTypeFromString(rombar)) <= 0) {
+        if (rombar &&
+            ((info->rombar = virDomainPciRombarModeTypeFromString(rombar)) <= 0)) {
             virDomainReportError(VIR_ERR_CONFIG_UNSUPPORTED,
                                  _("unknown rom bar value '%s'"), rombar);
             VIR_FREE(rombar);
             goto cleanup;
         }
         VIR_FREE(rombar);
+        info->romfile = virXMLPropString(rom, "file");
     }
 
     if (!address)
index 6419618b76d2b8a71170888c037aae4cae4cadcc..9a036853c93465714910ca4560ad58c99ebe354a 100644 (file)
@@ -170,6 +170,7 @@ struct _virDomainDeviceInfo {
     /* rombar is only used for pci hostdev devices, and bootIndex only
      * for disk, network interface, and hostdev devices */
     int rombar;         /* enum virDomainPciRombarMode */
+    char *romfile;
     int bootIndex;
 };
 
index 3f60691b58dd1ee63954fd292e29a3a86c0ce79e..0e26df1ccc4c18a0e308da336c5d8eefa68ec993 100644 (file)
@@ -1519,15 +1519,15 @@ qemuBuildRomStr(virBufferPtr buf,
                 virDomainDeviceInfoPtr info,
                 virBitmapPtr qemuCaps)
 {
-    if (info->rombar) {
+    if (info->rombar || info->romfile) {
         if (info->type != VIR_DOMAIN_DEVICE_ADDRESS_TYPE_PCI) {
             qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                            "%s", _("rombar is supported only for PCI devices"));
+                            "%s", _("rombar and romfile are supported only for PCI devices"));
             return -1;
         }
         if (!qemuCapsGet(qemuCaps, QEMU_CAPS_PCI_ROMBAR)) {
             qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED,
-                            "%s", _("rombar not supported in this QEMU binary"));
+                            "%s", _("rombar and romfile not supported in this QEMU binary"));
             return -1;
         }
 
@@ -1541,6 +1541,8 @@ qemuBuildRomStr(virBufferPtr buf,
         default:
             break;
         }
+        if (info->romfile)
+           virBufferAsprintf(buf, ",romfile=%s", info->romfile);
     }
     return 0;
 }
index 1a46aa3c0e12b56cf142d190d707cb7f16225071..11e0f0f8e870ffa88b608d545ea556db24d3ea90 100644 (file)
@@ -4,8 +4,9 @@ unix:/tmp/test-monitor,server,nowait -no-acpi -boot c -hda \
 /dev/HostVG/QEMUGuest2 \
 -device virtio-net-pci,vlan=0,id=net0,mac=52:54:00:24:a5:9f,bus=pci.0,addr=0x3,rombar=1 \
 -net user,vlan=0,name=hostnet0 \
--device virtio-net-pci,vlan=1,id=net1,mac=52:54:00:24:a5:9e,bus=pci.0,addr=0x4 \
--net user,vlan=1,name=hostnet1 \
+-device virtio-net-pci,vlan=1,id=net1,mac=52:54:00:24:a5:9e,bus=pci.0,addr=0x4,\
+romfile=/etc/fake/bootrom.bin -net user,vlan=1,name=hostnet1 \
 -usb -device pci-assign,host=06:12.5,id=hostdev0,bus=pci.0,addr=0x5,rombar=0 \
--device pci-assign,host=06:12.6,id=hostdev1,bus=pci.0,addr=0x6,rombar=1 \
+-device pci-assign,host=06:12.6,id=hostdev1,bus=pci.0,addr=0x6,rombar=1,\
+romfile=/etc/fake/bootrom.bin \
 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x7
index 3f6b8deaf2155322b9ffeff9f45a440d0ce2f4ab..731a69db7fb77105b56a99fdb4f54526e0d34505 100644 (file)
@@ -28,6 +28,7 @@
     <interface type='user'>
       <mac address='52:54:00:24:a5:9e'/>
       <model type='virtio'/>
+      <rom file='/etc/fake/bootrom.bin'/>
     </interface>
     <hostdev mode='subsystem' type='pci' managed='yes'>
       <source>
@@ -39,7 +40,7 @@
       <source>
         <address domain='0x0000' bus='0x06' slot='0x12' function='0x6'/>
       </source>
-      <rom bar='on'/>
+      <rom bar='on' file='/etc/fake/bootrom.bin'/>
     </hostdev>
     <memballoon model='virtio'/>
   </devices>