From patchwork Tue Sep 14 15:46:55 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bernhard Kohl X-Patchwork-Id: 64722 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [199.232.76.165]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 03BCBB70A6 for ; Wed, 15 Sep 2010 01:55:22 +1000 (EST) Received: from localhost ([127.0.0.1]:55263 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OvXqb-0002yx-0H for incoming@patchwork.ozlabs.org; Tue, 14 Sep 2010 11:55:05 -0400 Received: from [140.186.70.92] (port=54360 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1OvXj2-0007Fh-6M for qemu-devel@nongnu.org; Tue, 14 Sep 2010 11:47:17 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.69) (envelope-from ) id 1OvXiv-0004Ci-Lo for qemu-devel@nongnu.org; Tue, 14 Sep 2010 11:47:15 -0400 Received: from demumfd002.nsn-inter.net ([93.183.12.31]:10808) by eggs.gnu.org with esmtp (Exim 4.69) (envelope-from ) id 1OvXiv-0004C6-6I for qemu-devel@nongnu.org; Tue, 14 Sep 2010 11:47:09 -0400 Received: from demuprx017.emea.nsn-intra.net ([10.150.129.56]) by demumfd002.nsn-inter.net (8.12.11.20060308/8.12.11) with ESMTP id o8EFl6nF016389 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 14 Sep 2010 17:47:06 +0200 Received: from localhost6.localdomain6 ([10.148.23.89]) by demuprx017.emea.nsn-intra.net (8.12.11.20060308/8.12.11) with ESMTP id o8EFl5hF020503; Tue, 14 Sep 2010 17:47:05 +0200 From: Bernhard Kohl To: qemu-devel@nongnu.org Date: Tue, 14 Sep 2010 17:46:55 +0200 Message-Id: <1284479215-24679-1-git-send-email-bernhard.kohl@nsn.com> X-Mailer: git-send-email 1.7.2.2 X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.4-2.6 Cc: Bernhard Kohl , Thomas Ostler , mst@redhat.com Subject: [Qemu-devel] [PATCH] new parameter boot=on|off for "-net nic" and "-device" NIC devices X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org This patch was motivated by the following use case: In our system the VMs usually have 4 NICs, any combination of virtio-net-pci and pci-assign NIC devices. The VMs boot via gPXE preferably over the pci-assign devices. There is no way to make this working with a combination of the current options -net -pcidevice -device -optionrom -boot. With the parameter boot=off it is possible to avoid loading and using gPXE option ROMs either for old style "-net nic" or for "-device" NIC devices. So we can select which NIC is used for booting. A side effect of the boot=off parameter is that unneeded ROMs which might waste memory are not longer loaded. E.g. if you have 2 virtio-net-pci and 2 pci-assign NICs in sum 4 option ROMs are loaded and the virtio ROMs take precedence over the pci-assign ROMs. The BIOS uses the first gPXE ROM which it finds and only needs one of them even if there are more NICs of the same type. Without using the boot=on|off parameter the current behaviour does not change. Signed-off-by: Thomas Ostler Signed-off-by: Bernhard Kohl --- hw/pci.c | 8 +++++++- hw/pci.h | 1 + hw/qdev.c | 6 ++++++ hw/qdev.h | 1 + net.c | 8 ++++++++ net.h | 1 + qemu-options.hx | 8 ++++++-- vl.c | 27 +++++++++++++++++++++++++++ 8 files changed, 57 insertions(+), 3 deletions(-) diff --git a/hw/pci.c b/hw/pci.c index a98d6f3..055a2be 100644 --- a/hw/pci.c +++ b/hw/pci.c @@ -71,6 +71,7 @@ static struct BusInfo pci_bus_info = { DEFINE_PROP_UINT32("rombar", PCIDevice, rom_bar, 1), DEFINE_PROP_BIT("multifunction", PCIDevice, cap_present, QEMU_PCI_CAP_MULTIFUNCTION_BITNR, false), + DEFINE_PROP_STRING("boot", PCIDevice, boot), DEFINE_PROP_END_OF_LIST() } }; @@ -1513,6 +1514,10 @@ PCIDevice *pci_nic_init(NICInfo *nd, const char *default_model, pci_dev = pci_create(bus, devfn, pci_nic_names[i]); dev = &pci_dev->qdev; + if (nd->name) + dev->id = qemu_strdup(nd->name); + if (nd->no_boot) + dev->no_boot = 1; qdev_set_nic_properties(dev, nd); if (qdev_init(dev) < 0) return NULL; @@ -1693,7 +1698,8 @@ static int pci_qdev_init(DeviceState *qdev, DeviceInfo *base) /* rom loading */ if (pci_dev->romfile == NULL && info->romfile != NULL) pci_dev->romfile = qemu_strdup(info->romfile); - pci_add_option_rom(pci_dev); + if (!qdev->no_boot) + pci_add_option_rom(pci_dev); if (qdev->hotplugged) { rc = bus->hotplug(bus->hotplug_qdev, pci_dev, 1); diff --git a/hw/pci.h b/hw/pci.h index 1eab7e7..20aa038 100644 --- a/hw/pci.h +++ b/hw/pci.h @@ -172,6 +172,7 @@ struct PCIDevice { char *romfile; ram_addr_t rom_offset; uint32_t rom_bar; + char *boot; }; PCIDevice *pci_register_device(PCIBus *bus, const char *name, diff --git a/hw/qdev.c b/hw/qdev.c index 35858cb..8445bc9 100644 --- a/hw/qdev.c +++ b/hw/qdev.c @@ -249,6 +249,10 @@ DeviceState *qdev_device_add(QemuOpts *opts) qdev_free(qdev); return NULL; } + if (qemu_opt_get(opts, "boot")) { + if (!strcmp("off", qemu_strdup(qemu_opt_get(opts, "boot")))) + qdev->no_boot = 1; + } if (qdev_init(qdev) < 0) { qerror_report(QERR_DEVICE_INIT_FAILED, driver); return NULL; @@ -421,6 +425,8 @@ void qdev_set_nic_properties(DeviceState *dev, NICInfo *nd) qdev_prop_exists(dev, "vectors")) { qdev_prop_set_uint32(dev, "vectors", nd->nvectors); } + if (nd->no_boot) + qdev_prop_parse(dev, "boot", "off"); } static int next_block_unit[IF_COUNT]; diff --git a/hw/qdev.h b/hw/qdev.h index 579328a..e7df371 100644 --- a/hw/qdev.h +++ b/hw/qdev.h @@ -45,6 +45,7 @@ struct DeviceState { QLIST_ENTRY(DeviceState) sibling; int instance_id_alias; int alias_required_for_version; + int no_boot; }; typedef void (*bus_dev_printfn)(Monitor *mon, DeviceState *dev, int indent); diff --git a/net.c b/net.c index 3d0fde7..2370aca 100644 --- a/net.c +++ b/net.c @@ -792,6 +792,10 @@ static int net_init_nic(QemuOpts *opts, if (qemu_opt_get(opts, "addr")) { nd->devaddr = qemu_strdup(qemu_opt_get(opts, "addr")); } + if (qemu_opt_get(opts, "boot")) { + if (!strcmp("off", qemu_strdup(qemu_opt_get(opts, "boot")))) + nd->no_boot = 1; + } nd->macaddr[0] = 0x52; nd->macaddr[1] = 0x54; @@ -877,6 +881,10 @@ static const struct { .type = QEMU_OPT_STRING, .help = "PCI device address", }, { + .name = "boot", + .type = QEMU_OPT_STRING, + .help = "gPXE boot (on (default), off)", + }, { .name = "vectors", .type = QEMU_OPT_NUMBER, .help = "number of MSI-x vectors, 0 to disable MSI-X", diff --git a/net.h b/net.h index 518cf9c..288059b 100644 --- a/net.h +++ b/net.h @@ -132,6 +132,7 @@ struct NICInfo { VLANClientState *netdev; int used; int nvectors; + int no_boot; }; extern int nb_nics; diff --git a/qemu-options.hx b/qemu-options.hx index a0b5ae9..6084aa9 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -959,8 +959,10 @@ DEF("smb", HAS_ARG, QEMU_OPTION_smb, "", QEMU_ARCH_ALL) #endif DEF("net", HAS_ARG, QEMU_OPTION_net, - "-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v]\n" + "-net nic[,vlan=n][,macaddr=mac][,model=type][,name=str][,addr=str][,vectors=v][,boot=on|off]\n" " create a new Network Interface Card and connect it to VLAN 'n'\n" + " use 'boot=on|off' to enable/disable loading of an option rom;\n" + " loading enabled is the default\n" #ifdef CONFIG_SLIRP "-net user[,vlan=n][,name=str][,net=addr[/mask]][,host=addr][,restrict=y|n]\n" " [,hostname=host][,dhcpstart=addr][,dns=addr][,tftp=dir][,bootfile=f]\n" @@ -1014,13 +1016,15 @@ DEF("netdev", HAS_ARG, QEMU_OPTION_netdev, #endif "socket],id=str[,option][,option][,...]\n", QEMU_ARCH_ALL) STEXI -@item -net nic[,vlan=@var{n}][,macaddr=@var{mac}][,model=@var{type}] [,name=@var{name}][,addr=@var{addr}][,vectors=@var{v}] +@item -net nic[,vlan=@var{n}][,macaddr=@var{mac}][,model=@var{type}] [,name=@var{name}][,addr=@var{addr}][,vectors=@var{v}][,boot=on|off] @findex -net Create a new Network Interface Card and connect it to VLAN @var{n} (@var{n} = 0 is the default). The NIC is an e1000 by default on the PC target. Optionally, the MAC address can be changed to @var{mac}, the device address set to @var{addr} (PCI cards only), and a @var{name} can be assigned for use in monitor commands. +Optionally, with @option{boot=on|off}, you can enable/disable the loading of an option +rom; by default, loading is enabled. Optionally, for PCI cards, you can specify the number @var{v} of MSI-X vectors that the card should have; this option currently only affects virtio cards; set @var{v} = 0 to disable MSI-X. If no @option{-net} option is specified, a single diff --git a/vl.c b/vl.c index 3f45aa9..2aad6b1 100644 --- a/vl.c +++ b/vl.c @@ -2459,6 +2459,33 @@ int main(int argc, char **argv, char **envp) if (!qemu_opts_parse(qemu_find_opts("device"), optarg, 1)) { exit(1); } + + /* check whether option "boot" is present in the cmd string */ + /* for this a modified string is created that does not */ + /* contain the driver */ + /* if "boot" is present and set to "on", the relevant */ + /* variables are set in a way that net boot is possible and */ + /* that a present "romfile" is loaded for the given device */ + /* note that "default_net" is set to zero in order to avoid */ + /* creation of a default device if option "-net" is not */ + /* present in the complete command line */ + { + char mod_optarg[128]; + char *mod_optarg_p; + + if ((mod_optarg_p = strchr(optarg, ','))) + strcpy(mod_optarg, ++mod_optarg_p); + else + strcpy(mod_optarg, optarg); + + if (get_param_value(mod_optarg, 128, "boot", mod_optarg) != 0) { + if (!strcmp("on", mod_optarg)) { + char buf[8]="n"; + pstrcpy(boot_devices, sizeof(boot_devices), buf); + default_net = 0; + } + } + } break; case QEMU_OPTION_smp: smp_parse(optarg);