[libvirt] [PATCH 0/2] Support booting from hostdev devices

These are a follow-up patches for per-device boot which extend current support for booting from disks and NICs to assigned host devices. Jiri Denemark (2): Support booting from hostdev devices qemu: Support booting from hostdev PCI devices docs/formatdomain.html.in | 14 ++++++++++++-- docs/schemas/domain.rng | 3 +++ src/conf/domain_conf.c | 18 +++++++++++++++--- src/conf/domain_conf.h | 1 + src/qemu/qemu_capabilities.c | 5 ++++- src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 17 +++++++++++++++++ 7 files changed, 53 insertions(+), 6 deletions(-) -- 1.7.4

--- docs/formatdomain.html.in | 14 ++++++++++++-- docs/schemas/domain.rng | 3 +++ src/conf/domain_conf.c | 18 +++++++++++++++--- src/conf/domain_conf.h | 1 + 4 files changed, 31 insertions(+), 5 deletions(-) diff --git a/docs/formatdomain.html.in b/docs/formatdomain.html.in index 48f82ae..db0b762 100644 --- a/docs/formatdomain.html.in +++ b/docs/formatdomain.html.in @@ -109,8 +109,9 @@ to consider. The <code>boot</code> element can be repeated multiple times to setup a priority list of boot devices to try in turn. The <code>boot</code> element cannot be used if per-device boot elements - are used (see <a href="#elementsDisks">disks</a> and - <a href="#elementsNICS">network interfaces</a> sections below. + are used (see <a href="#elementsDisks">disks</a>, + <a href="#elementsNICS">network interfaces</a>, and + <a href="#elementsUSB">USB and PCI devices</a> sections below). <span class="since">Since 0.1.3, per-device boot since 0.8.8</span> </dd> <dt><code>bootmenu</code></dt> @@ -929,6 +930,7 @@ <vendor id='0x1234'/> <product id='0xbeef'/> </source> + <boot order='2'/> </hostdev> </devices> ...</pre> @@ -942,6 +944,7 @@ <source> <address bus='0x06' slot='0x02' function='0x0'/> </source> + <boot order='1'/> </hostdev> </devices> ...</pre> @@ -964,6 +967,13 @@ <code>id</code> attribute that specifies the USB vendor and product id. The ids can be given in decimal, hexadecimal (starting with 0x) or octal (starting with 0) form.</dd> + <dt><code>boot</code></dt> + <dd>Specifies that the device is bootable. The <code>order</code> + attribute determines the order in which devices will be tried during + boot sequence. The per-device <code>boot</code> elements cannot be + 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>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/domain.rng b/docs/schemas/domain.rng index e4e7423..8a2e7c7 100644 --- a/docs/schemas/domain.rng +++ b/docs/schemas/domain.rng @@ -1693,6 +1693,9 @@ </element> </group> <optional> + <ref name="deviceBoot"/> + </optional> + <optional> <ref name="address"/> </optional> </element> diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c index b1cc6c8..aba4223 100644 --- a/src/conf/domain_conf.c +++ b/src/conf/domain_conf.c @@ -4247,7 +4247,9 @@ out: static virDomainHostdevDefPtr virDomainHostdevDefParseXML(const xmlNodePtr node, - int flags) { + virBitmapPtr bootMap, + int flags) +{ xmlNodePtr cur; virDomainHostdevDefPtr def; @@ -4308,6 +4310,10 @@ virDomainHostdevDefParseXML(const xmlNodePtr node, /* address is parsed as part of virDomainDeviceInfoParseXML */ } else if (xmlStrEqual(cur->name, BAD_CAST "alias")) { /* alias is parsed as part of virDomainDeviceInfoParseXML */ + } else if (xmlStrEqual(cur->name, BAD_CAST "boot")) { + if (virDomainDeviceBootParseXML(cur, &def->bootIndex, + bootMap)) + goto error; } else { virDomainReportError(VIR_ERR_INTERNAL_ERROR, _("unknown node %s"), cur->name); @@ -4507,7 +4513,8 @@ virDomainDeviceDefPtr virDomainDeviceDefParse(virCapsPtr caps, goto error; } else if (xmlStrEqual(node->name, BAD_CAST "hostdev")) { dev->type = VIR_DOMAIN_DEVICE_HOSTDEV; - if (!(dev->data.hostdev = virDomainHostdevDefParseXML(node, flags))) + if (!(dev->data.hostdev = virDomainHostdevDefParseXML(node, NULL, + flags))) goto error; } else if (xmlStrEqual(node->name, BAD_CAST "controller")) { dev->type = VIR_DOMAIN_DEVICE_CONTROLLER; @@ -4767,7 +4774,8 @@ virDomainDefParseBootXML(xmlXPathContextPtr ctxt, unsigned long deviceBoot; if (virXPathULong("count(./devices/disk[boot]" - "|./devices/interface[boot])", ctxt, &deviceBoot) < 0) { + "|./devices/interface[boot]" + "|./devices/hostdev[boot])", ctxt, &deviceBoot) < 0) { virDomainReportError(VIR_ERR_INTERNAL_ERROR, "%s", _("cannot count boot devices")); goto cleanup; @@ -5506,6 +5514,7 @@ static virDomainDefPtr virDomainDefParseXML(virCapsPtr caps, goto no_memory; for (i = 0 ; i < n ; i++) { virDomainHostdevDefPtr hostdev = virDomainHostdevDefParseXML(nodes[i], + bootMap, flags); if (!hostdev) goto error; @@ -7280,6 +7289,9 @@ virDomainHostdevDefFormat(virBufferPtr buf, virBufferAddLit(buf, " </source>\n"); + if (def->bootIndex) + virBufferVSprintf(buf, " <boot order='%d'/>\n", def->bootIndex); + if (virDomainDeviceInfoFormat(buf, &def->info, flags) < 0) return -1; diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h index 871fa9a..feae203 100644 --- a/src/conf/domain_conf.h +++ b/src/conf/domain_conf.h @@ -678,6 +678,7 @@ struct _virDomainHostdevDef { } caps; } source; char* target; + int bootIndex; virDomainDeviceInfo info; /* Guest address */ }; -- 1.7.4

On 02/03/2011 07:13 AM, Jiri Denemark wrote:
--- docs/formatdomain.html.in | 14 ++++++++++++-- docs/schemas/domain.rng | 3 +++ src/conf/domain_conf.c | 18 +++++++++++++++--- src/conf/domain_conf.h | 1 + 4 files changed, 31 insertions(+), 5 deletions(-)
Yeah - docs on the first submission! We're making progress at drilling this into everyone's heads (including mine).
static virDomainHostdevDefPtr virDomainHostdevDefParseXML(const xmlNodePtr node, - int flags) { + virBitmapPtr bootMap, + int flags) +{
Don't you love sneaking in little style patches, like moving the function open {, while touching that line for other reasons? :) Wow, this patch was pretty easy to follow; it's a sign of good factorization in your first patch for both disk and nic, when it was trivial to copy those two patterns to extend it to a third client. ACK. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

--- src/qemu/qemu_capabilities.c | 5 ++++- src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletions(-) diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 37a97aa..fd46557 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -1088,8 +1088,11 @@ qemuCapsParseDeviceStr(const char *str, unsigned long long *flags) /* Features of given devices. */ if (strstr(str, "pci-assign.configfd")) *flags |= QEMUD_CMD_FLAG_PCI_CONFIGFD; - if (strstr(str, "virtio-blk-pci.bootindex")) + if (strstr(str, "virtio-blk-pci.bootindex")) { *flags |= QEMUD_CMD_FLAG_BOOTINDEX; + if (strstr(str, "pci-assign.bootindex")) + *flags |= QEMUD_CMD_FLAG_PCI_BOOTINDEX; + } return 0; } diff --git a/src/qemu/qemu_capabilities.h b/src/qemu/qemu_capabilities.h index e04f6a8..c2d09ca 100644 --- a/src/qemu/qemu_capabilities.h +++ b/src/qemu/qemu_capabilities.h @@ -87,6 +87,7 @@ enum qemuCapsFlags { QEMUD_CMD_FLAG_HDA_DUPLEX = (1LL << 50), /* -device hda-duplex */ QEMUD_CMD_FLAG_DRIVE_AIO = (1LL << 51), /* -drive aio= supported */ QEMUD_CMD_FLAG_PCI_MULTIBUS = (1LL << 52), /* bus=pci.0 vs bus=pci */ + QEMUD_CMD_FLAG_PCI_BOOTINDEX = (1LL << 53), /* pci-assign.bootindex */ }; virCapsPtr qemuCapsInit(virCapsPtr old_caps); diff --git a/src/qemu/qemu_command.c b/src/qemu/qemu_command.c index ffbe276..f57c937 100644 --- a/src/qemu/qemu_command.c +++ b/src/qemu/qemu_command.c @@ -1917,6 +1917,8 @@ qemuBuildPCIHostdevDevStr(virDomainHostdevDefPtr dev, const char *configfd, virBufferVSprintf(&buf, ",id=%s", dev->info.alias); if (configfd && *configfd) virBufferVSprintf(&buf, ",configfd=%s", configfd); + if (dev->bootIndex) + virBufferVSprintf(&buf, ",bootindex=%d", dev->bootIndex); if (qemuBuildDeviceAddressStr(&buf, &dev->info, qemuCmdFlags) < 0) goto error; @@ -3980,6 +3982,21 @@ qemuBuildCommandLine(virConnectPtr conn, virDomainHostdevDefPtr hostdev = def->hostdevs[i]; char *devstr; + if (hostdev->bootIndex) { + if (hostdev->mode != VIR_DOMAIN_HOSTDEV_MODE_SUBSYS || + hostdev->source.subsys.type != VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_PCI) { + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("booting from assigned devices is only" + " supported for PCI devices")); + goto error; + } else if (!(qemuCmdFlags & QEMUD_CMD_FLAG_PCI_BOOTINDEX)) { + qemuReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("booting from assigned PCI devices is not" + " supported with this version of qemu")); + goto error; + } + } + /* USB */ if (hostdev->mode == VIR_DOMAIN_HOSTDEV_MODE_SUBSYS && hostdev->source.subsys.type == VIR_DOMAIN_HOSTDEV_SUBSYS_TYPE_USB) { -- 1.7.4

On 02/03/2011 07:13 AM, Jiri Denemark wrote:
--- src/qemu/qemu_capabilities.c | 5 ++++- src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 17 +++++++++++++++++ 3 files changed, 22 insertions(+), 1 deletions(-)
diff --git a/src/qemu/qemu_capabilities.c b/src/qemu/qemu_capabilities.c index 37a97aa..fd46557 100644 --- a/src/qemu/qemu_capabilities.c +++ b/src/qemu/qemu_capabilities.c @@ -1088,8 +1088,11 @@ qemuCapsParseDeviceStr(const char *str, unsigned long long *flags) /* Features of given devices. */ if (strstr(str, "pci-assign.configfd")) *flags |= QEMUD_CMD_FLAG_PCI_CONFIGFD; - if (strstr(str, "virtio-blk-pci.bootindex")) + if (strstr(str, "virtio-blk-pci.bootindex")) { *flags |= QEMUD_CMD_FLAG_BOOTINDEX; + if (strstr(str, "pci-assign.bootindex")) + *flags |= QEMUD_CMD_FLAG_PCI_BOOTINDEX; + }
Nice that you avoid the strstr() if you can't even use per-device boot ordering, and also nice that qemu lets us query both pci-assign and virtio-blk-pci in one invocation.
+++ b/src/qemu/qemu_capabilities.h @@ -87,6 +87,7 @@ enum qemuCapsFlags { QEMUD_CMD_FLAG_HDA_DUPLEX = (1LL << 50), /* -device hda-duplex */ QEMUD_CMD_FLAG_DRIVE_AIO = (1LL << 51), /* -drive aio= supported */ QEMUD_CMD_FLAG_PCI_MULTIBUS = (1LL << 52), /* bus=pci.0 vs bus=pci */ + QEMUD_CMD_FLAG_PCI_BOOTINDEX = (1LL << 53), /* pci-assign.bootindex */
Boy, this file has been hot lately! (note to self, I get to rebase this line for smartcard yet again). ACK. -- Eric Blake eblake@redhat.com +1-801-349-2682 Libvirt virtualization library http://libvirt.org

+++ b/src/qemu/qemu_capabilities.h @@ -87,6 +87,7 @@ enum qemuCapsFlags { QEMUD_CMD_FLAG_HDA_DUPLEX = (1LL << 50), /* -device hda-duplex */ QEMUD_CMD_FLAG_DRIVE_AIO = (1LL << 51), /* -drive aio= supported */ QEMUD_CMD_FLAG_PCI_MULTIBUS = (1LL << 52), /* bus=pci.0 vs bus=pci */ + QEMUD_CMD_FLAG_PCI_BOOTINDEX = (1LL << 53), /* pci-assign.bootindex */
Boy, this file has been hot lately! (note to self, I get to rebase this line for smartcard yet again).
Yeah. I'm planning to convert this into virBitmap soon before we reach 64th flag. Jirka

On Thu, Feb 03, 2011 at 15:13:33 +0100, Jiri Denemark wrote:
These are a follow-up patches for per-device boot which extend current support for booting from disks and NICs to assigned host devices.
Jiri Denemark (2): Support booting from hostdev devices qemu: Support booting from hostdev PCI devices
docs/formatdomain.html.in | 14 ++++++++++++-- docs/schemas/domain.rng | 3 +++ src/conf/domain_conf.c | 18 +++++++++++++++--- src/conf/domain_conf.h | 1 + src/qemu/qemu_capabilities.c | 5 ++++- src/qemu/qemu_capabilities.h | 1 + src/qemu/qemu_command.c | 17 +++++++++++++++++ 7 files changed, 53 insertions(+), 6 deletions(-)
I pushed these patches. Thanks for the review, Eric. Jirka
participants (2)
-
Eric Blake
-
Jiri Denemark