]> git.proxmox.com Git - qemu.git/commitdiff
Merge remote-tracking branch 'mst/tags/for_anthony' into staging
authorAnthony Liguori <anthony@codemonkey.ws>
Mon, 30 Sep 2013 22:15:01 +0000 (17:15 -0500)
committerAnthony Liguori <anthony@codemonkey.ws>
Mon, 30 Sep 2013 22:15:01 +0000 (17:15 -0500)
pc,pci,virtio fixes and cleanups

This includes pc and pci cleanups and enhancements,
and a virtio-net bugfix related to softmac programming.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
# gpg: Signature made Sun 29 Sep 2013 01:51:16 AM CDT using RSA key ID D28D5469
# gpg: Can't check signature: public key not found

# By Michael S. Tsirkin (8) and others
# Via Michael S. Tsirkin
* mst/tags/for_anthony:
  smbios: Factor out smbios_maybe_add_str()
  smbios: Make multiple -smbios type= accumulate sanely
  smbios: Improve diagnostics for conflicting entries
  smbios: Convert to QemuOpts
  smbios: Normalize smbios_entry_add()'s error handling to exit(1)
  virtio-net: fix up HMP NIC info string on reset
  pci: remove explicit check to 64K ioport size
  piix4: disable io on reset
  piix: use 64 bit window programmed by guest
  q35: use 64 bit window programmed by guest
  pci: add helper to retrieve the 64-bit range
  range: add min/max operations on ranges
  range: add Range to typedefs
  q35: make pci window address/size match guest cfg

Message-id: 1380437951-21788-1-git-send-email-mst@redhat.com

14 files changed:
arch_init.c
hw/acpi/piix4.c
hw/i386/smbios.c
hw/net/virtio-net.c
hw/pci-host/piix.c
hw/pci-host/q35.c
hw/pci/pci.c
include/hw/i386/smbios.h
include/hw/pci/pci.h
include/qemu/range.h
include/qemu/typedefs.h
include/sysemu/arch_init.h
include/sysemu/sysemu.h
vl.c

index d14457da60784f006ef67234d1e6c13191f994a0..7545d96739ee7bf157494754ce3c46697c375a92 100644 (file)
@@ -1118,9 +1118,6 @@ int qemu_uuid_parse(const char *str, uint8_t *uuid)
     if (ret != 16) {
         return -1;
     }
-#ifdef TARGET_I386
-    smbios_add_field(1, offsetof(struct smbios_type_1, uuid), uuid, 16);
-#endif
     return 0;
 }
 
@@ -1139,12 +1136,10 @@ void do_acpitable_option(const QemuOpts *opts)
 #endif
 }
 
-void do_smbios_option(const char *optarg)
+void do_smbios_option(QemuOpts *opts)
 {
 #ifdef TARGET_I386
-    if (smbios_entry_add(optarg) < 0) {
-        exit(1);
-    }
+    smbios_entry_add(opts);
 #endif
 }
 
index 0b8d1d9da9c10b4559bf5d06a492a875bc3b018a..b46bd5ea6afec9ea4b41f047bd0c471fc1b006a2 100644 (file)
@@ -380,6 +380,7 @@ static void piix4_reset(void *opaque)
         /* Mark SMM as already inited (until KVM supports SMM). */
         pci_conf[0x5B] = 0x02;
     }
+    pm_io_space_update(s);
     piix4_update_hotplug(s);
 }
 
index e708cb8919c864415471366f9f4b8f12e4b18e86..d3f1ee65c624e9d8e72b8e8f4dfc7a5bd6f184ee 100644 (file)
@@ -2,9 +2,11 @@
  * SMBIOS Support
  *
  * Copyright (C) 2009 Hewlett-Packard Development Company, L.P.
+ * Copyright (C) 2013 Red Hat, Inc.
  *
  * Authors:
  *  Alex Williamson <alex.williamson@hp.com>
+ *  Markus Armbruster <armbru@redhat.com>
  *
  * This work is licensed under the terms of the GNU GPL, version 2.  See
  * the COPYING file in the top-level directory.
@@ -13,6 +15,7 @@
  * GNU GPL, version 2 or (at your option) any later version.
  */
 
+#include "qemu/config-file.h"
 #include "qemu/error-report.h"
 #include "sysemu/sysemu.h"
 #include "hw/i386/smbios.h"
@@ -41,10 +44,117 @@ struct smbios_table {
 #define SMBIOS_FIELD_ENTRY 0
 #define SMBIOS_TABLE_ENTRY 1
 
-
 static uint8_t *smbios_entries;
 static size_t smbios_entries_len;
 static int smbios_type4_count = 0;
+static bool smbios_immutable;
+
+static struct {
+    bool seen;
+    int headertype;
+    Location loc;
+} first_opt[2];
+
+static struct {
+    const char *vendor, *version, *date;
+    bool have_major_minor;
+    uint8_t major, minor;
+} type0;
+
+static struct {
+    const char *manufacturer, *product, *version, *serial, *sku, *family;
+    /* uuid is in qemu_uuid[] */
+} type1;
+
+static QemuOptsList qemu_smbios_opts = {
+    .name = "smbios",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_smbios_opts.head),
+    .desc = {
+        /*
+         * no elements => accept any params
+         * validation will happen later
+         */
+        { /* end of list */ }
+    }
+};
+
+static const QemuOptDesc qemu_smbios_file_opts[] = {
+    {
+        .name = "file",
+        .type = QEMU_OPT_STRING,
+        .help = "binary file containing an SMBIOS element",
+    },
+    { /* end of list */ }
+};
+
+static const QemuOptDesc qemu_smbios_type0_opts[] = {
+    {
+        .name = "type",
+        .type = QEMU_OPT_NUMBER,
+        .help = "SMBIOS element type",
+    },{
+        .name = "vendor",
+        .type = QEMU_OPT_STRING,
+        .help = "vendor name",
+    },{
+        .name = "version",
+        .type = QEMU_OPT_STRING,
+        .help = "version number",
+    },{
+        .name = "date",
+        .type = QEMU_OPT_STRING,
+        .help = "release date",
+    },{
+        .name = "release",
+        .type = QEMU_OPT_STRING,
+        .help = "revision number",
+    },
+    { /* end of list */ }
+};
+
+static const QemuOptDesc qemu_smbios_type1_opts[] = {
+    {
+        .name = "type",
+        .type = QEMU_OPT_NUMBER,
+        .help = "SMBIOS element type",
+    },{
+        .name = "manufacturer",
+        .type = QEMU_OPT_STRING,
+        .help = "manufacturer name",
+    },{
+        .name = "product",
+        .type = QEMU_OPT_STRING,
+        .help = "product name",
+    },{
+        .name = "version",
+        .type = QEMU_OPT_STRING,
+        .help = "version number",
+    },{
+        .name = "serial",
+        .type = QEMU_OPT_STRING,
+        .help = "serial number",
+    },{
+        .name = "uuid",
+        .type = QEMU_OPT_STRING,
+        .help = "UUID",
+    },{
+        .name = "sku",
+        .type = QEMU_OPT_STRING,
+        .help = "SKU number",
+    },{
+        .name = "family",
+        .type = QEMU_OPT_STRING,
+        .help = "family name",
+    },
+    { /* end of list */ }
+};
+
+static void smbios_register_config(void)
+{
+    qemu_add_opts(&qemu_smbios_opts);
+}
+
+machine_init(smbios_register_config);
 
 static void smbios_validate_table(void)
 {
@@ -54,57 +164,33 @@ static void smbios_validate_table(void)
     }
 }
 
-uint8_t *smbios_get_table(size_t *length)
-{
-    smbios_validate_table();
-    *length = smbios_entries_len;
-    return smbios_entries;
-}
-
 /*
  * To avoid unresolvable overlaps in data, don't allow both
  * tables and fields for the same smbios type.
  */
 static void smbios_check_collision(int type, int entry)
 {
-    uint16_t *num_entries = (uint16_t *)smbios_entries;
-    struct smbios_header *header;
-    char *p;
-    int i;
-
-    if (!num_entries)
-        return;
-
-    p = (char *)(num_entries + 1);
-
-    for (i = 0; i < *num_entries; i++) {
-        header = (struct smbios_header *)p;
-        if (entry == SMBIOS_TABLE_ENTRY && header->type == SMBIOS_FIELD_ENTRY) {
-            struct smbios_field *field = (void *)header;
-            if (type == field->type) {
-                error_report("SMBIOS type %d field already defined, "
-                             "cannot add table", type);
-                exit(1);
-            }
-        } else if (entry == SMBIOS_FIELD_ENTRY &&
-                   header->type == SMBIOS_TABLE_ENTRY) {
-            struct smbios_structure_header *table = (void *)(header + 1);
-            if (type == table->type) {
-                error_report("SMBIOS type %d table already defined, "
-                             "cannot add field", type);
+    if (type < ARRAY_SIZE(first_opt)) {
+        if (first_opt[type].seen) {
+            if (first_opt[type].headertype != entry) {
+                error_report("Can't mix file= and type= for same type");
+                loc_push_restore(&first_opt[type].loc);
+                error_report("This is the conflicting setting");
+                loc_pop(&first_opt[type].loc);
                 exit(1);
             }
+        } else {
+            first_opt[type].seen = true;
+            first_opt[type].headertype = entry;
+            loc_save(&first_opt[type].loc);
         }
-        p += le16_to_cpu(header->length);
     }
 }
 
-void smbios_add_field(int type, int offset, const void *data, size_t len)
+static void smbios_add_field(int type, int offset, const void *data, size_t len)
 {
     struct smbios_field *field;
 
-    smbios_check_collision(type, SMBIOS_FIELD_ENTRY);
-
     if (!smbios_entries) {
         smbios_entries_len = sizeof(uint16_t);
         smbios_entries = g_malloc0(smbios_entries_len);
@@ -124,76 +210,94 @@ void smbios_add_field(int type, int offset, const void *data, size_t len)
             cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
 }
 
-static void smbios_build_type_0_fields(const char *t)
+static void smbios_maybe_add_str(int type, int offset, const char *data)
 {
-    char buf[1024];
-    unsigned char major, minor;
-
-    if (get_param_value(buf, sizeof(buf), "vendor", t))
-        smbios_add_field(0, offsetof(struct smbios_type_0, vendor_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "version", t))
-        smbios_add_field(0, offsetof(struct smbios_type_0, bios_version_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "date", t))
-        smbios_add_field(0, offsetof(struct smbios_type_0,
+    if (data) {
+        smbios_add_field(type, offset, data, strlen(data) + 1);
+    }
+}
+
+static void smbios_build_type_0_fields(void)
+{
+    smbios_maybe_add_str(0, offsetof(struct smbios_type_0, vendor_str),
+                         type0.vendor);
+    smbios_maybe_add_str(0, offsetof(struct smbios_type_0, bios_version_str),
+                         type0.version);
+    smbios_maybe_add_str(0, offsetof(struct smbios_type_0,
                                      bios_release_date_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "release", t)) {
-        if (sscanf(buf, "%hhu.%hhu", &major, &minor) != 2) {
-            error_report("Invalid release");
-            exit(1);
-        }
+                         type0.date);
+    if (type0.have_major_minor) {
         smbios_add_field(0, offsetof(struct smbios_type_0,
                                      system_bios_major_release),
-                         &major, 1);
+                         &type0.major, 1);
         smbios_add_field(0, offsetof(struct smbios_type_0,
                                      system_bios_minor_release),
-                         &minor, 1);
+                         &type0.minor, 1);
     }
 }
 
-static void smbios_build_type_1_fields(const char *t)
+static void smbios_build_type_1_fields(void)
 {
-    char buf[1024];
-
-    if (get_param_value(buf, sizeof(buf), "manufacturer", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, manufacturer_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "product", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, product_name_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "version", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, version_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "serial", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, serial_number_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "uuid", t)) {
-        if (qemu_uuid_parse(buf, qemu_uuid) != 0) {
-            error_report("Invalid UUID");
-            exit(1);
-        }
+    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, manufacturer_str),
+                         type1.manufacturer);
+    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, product_name_str),
+                         type1.product);
+    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, version_str),
+                         type1.version);
+    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, serial_number_str),
+                         type1.serial);
+    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, sku_number_str),
+                         type1.sku);
+    smbios_maybe_add_str(1, offsetof(struct smbios_type_1, family_str),
+                         type1.family);
+    if (qemu_uuid_set) {
+        smbios_add_field(1, offsetof(struct smbios_type_1, uuid),
+                         qemu_uuid, 16);
+    }
+}
+
+uint8_t *smbios_get_table(size_t *length)
+{
+    if (!smbios_immutable) {
+        smbios_build_type_0_fields();
+        smbios_build_type_1_fields();
+        smbios_validate_table();
+        smbios_immutable = true;
+    }
+    *length = smbios_entries_len;
+    return smbios_entries;
+}
+
+static void save_opt(const char **dest, QemuOpts *opts, const char *name)
+{
+    const char *val = qemu_opt_get(opts, name);
+
+    if (val) {
+        *dest = val;
     }
-    if (get_param_value(buf, sizeof(buf), "sku", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, sku_number_str),
-                         buf, strlen(buf) + 1);
-    if (get_param_value(buf, sizeof(buf), "family", t))
-        smbios_add_field(1, offsetof(struct smbios_type_1, family_str),
-                         buf, strlen(buf) + 1);
 }
 
-int smbios_entry_add(const char *t)
+void smbios_entry_add(QemuOpts *opts)
 {
-    char buf[1024];
+    Error *local_err = NULL;
+    const char *val;
 
-    if (get_param_value(buf, sizeof(buf), "file", t)) {
+    assert(!smbios_immutable);
+    val = qemu_opt_get(opts, "file");
+    if (val) {
         struct smbios_structure_header *header;
         struct smbios_table *table;
-        int size = get_image_size(buf);
+        int size;
 
+        qemu_opts_validate(opts, qemu_smbios_file_opts, &local_err);
+        if (local_err) {
+            error_report("%s", error_get_pretty(local_err));
+            exit(1);
+        }
+
+        size = get_image_size(val);
         if (size == -1 || size < sizeof(struct smbios_structure_header)) {
-            error_report("Cannot read SMBIOS file %s", buf);
+            error_report("Cannot read SMBIOS file %s", val);
             exit(1);
         }
 
@@ -208,8 +312,8 @@ int smbios_entry_add(const char *t)
         table->header.type = SMBIOS_TABLE_ENTRY;
         table->header.length = cpu_to_le16(sizeof(*table) + size);
 
-        if (load_image(buf, table->data) != size) {
-            error_report("Failed to load SMBIOS file %s", buf);
+        if (load_image(val, table->data) != size) {
+            error_report("Failed to load SMBIOS file %s", val);
             exit(1);
         }
 
@@ -222,18 +326,57 @@ int smbios_entry_add(const char *t)
         smbios_entries_len += sizeof(*table) + size;
         (*(uint16_t *)smbios_entries) =
                 cpu_to_le16(le16_to_cpu(*(uint16_t *)smbios_entries) + 1);
-        return 0;
+        return;
     }
 
-    if (get_param_value(buf, sizeof(buf), "type", t)) {
-        unsigned long type = strtoul(buf, NULL, 0);
+    val = qemu_opt_get(opts, "type");
+    if (val) {
+        unsigned long type = strtoul(val, NULL, 0);
+
+        smbios_check_collision(type, SMBIOS_FIELD_ENTRY);
+
         switch (type) {
         case 0:
-            smbios_build_type_0_fields(t);
-            return 0;
+            qemu_opts_validate(opts, qemu_smbios_type0_opts, &local_err);
+            if (local_err) {
+                error_report("%s", error_get_pretty(local_err));
+                exit(1);
+            }
+            save_opt(&type0.vendor, opts, "vendor");
+            save_opt(&type0.version, opts, "version");
+            save_opt(&type0.date, opts, "date");
+
+            val = qemu_opt_get(opts, "release");
+            if (val) {
+                if (sscanf(val, "%hhu.%hhu", &type0.major, &type0.minor) != 2) {
+                    error_report("Invalid release");
+                    exit(1);
+                }
+                type0.have_major_minor = true;
+            }
+            return;
         case 1:
-            smbios_build_type_1_fields(t);
-            return 0;
+            qemu_opts_validate(opts, qemu_smbios_type1_opts, &local_err);
+            if (local_err) {
+                error_report("%s", error_get_pretty(local_err));
+                exit(1);
+            }
+            save_opt(&type1.manufacturer, opts, "manufacturer");
+            save_opt(&type1.product, opts, "product");
+            save_opt(&type1.version, opts, "version");
+            save_opt(&type1.serial, opts, "serial");
+            save_opt(&type1.sku, opts, "sku");
+            save_opt(&type1.family, opts, "family");
+
+            val = qemu_opt_get(opts, "uuid");
+            if (val) {
+                if (qemu_uuid_parse(val, qemu_uuid) != 0) {
+                    error_report("Invalid UUID");
+                    exit(1);
+                }
+                qemu_uuid_set = true;
+            }
+            return;
         default:
             error_report("Don't know how to build fields for SMBIOS type %ld",
                          type);
@@ -242,5 +385,5 @@ int smbios_entry_add(const char *t)
     }
 
     error_report("Must specify type= or file=");
-    return -1;
+    exit(1);
 }
index dd41008fb0e7b812b7ab255cbed2bde91ac2c097..22dbd053d494feac98a6f580e8809002e1bb750c 100644 (file)
@@ -314,6 +314,7 @@ static void virtio_net_reset(VirtIODevice *vdev)
     n->mac_table.uni_overflow = 0;
     memset(n->mac_table.macs, 0, MAC_TABLE_ENTRIES * ETH_ALEN);
     memcpy(&n->mac[0], &n->nic->conf->macaddr, sizeof(n->mac));
+    qemu_format_nic_info_str(qemu_get_queue(n->nic), n->mac);
     memset(n->vlans, 0, MAX_VLAN >> 3);
 }
 
index 221d82b637e25f3cf93d9d0c9ab7e84aae52c5b3..c04114932049db3d80c7b308b3a8ac531b944676 100644 (file)
@@ -235,18 +235,24 @@ static void i440fx_pcihost_get_pci_hole64_start(Object *obj, Visitor *v,
                                                 void *opaque, const char *name,
                                                 Error **errp)
 {
-    I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
+    PCIHostState *h = PCI_HOST_BRIDGE(obj);
+    Range w64;
+
+    pci_bus_get_w64_range(h->bus, &w64);
 
-    visit_type_uint64(v, &s->pci_info.w64.begin, name, errp);
+    visit_type_uint64(v, &w64.begin, name, errp);
 }
 
 static void i440fx_pcihost_get_pci_hole64_end(Object *obj, Visitor *v,
                                               void *opaque, const char *name,
                                               Error **errp)
 {
-    I440FXState *s = I440FX_PCI_HOST_BRIDGE(obj);
+    PCIHostState *h = PCI_HOST_BRIDGE(obj);
+    Range w64;
+
+    pci_bus_get_w64_range(h->bus, &w64);
 
-    visit_type_uint64(v, &s->pci_info.w64.end, name, errp);
+    visit_type_uint64(v, &w64.end, name, errp);
 }
 
 static void i440fx_pcihost_initfn(Object *obj)
index 0cb652d7f0ab35fe328f6a3a45bc2effb85ef664..ad703a4bf788fceaab5e5f2a49afd2d098689d0d 100644 (file)
@@ -89,18 +89,24 @@ static void q35_host_get_pci_hole64_start(Object *obj, Visitor *v,
                                           void *opaque, const char *name,
                                           Error **errp)
 {
-    Q35PCIHost *s = Q35_HOST_DEVICE(obj);
+    PCIHostState *h = PCI_HOST_BRIDGE(obj);
+    Range w64;
+
+    pci_bus_get_w64_range(h->bus, &w64);
 
-    visit_type_uint64(v, &s->mch.pci_info.w64.begin, name, errp);
+    visit_type_uint64(v, &w64.begin, name, errp);
 }
 
 static void q35_host_get_pci_hole64_end(Object *obj, Visitor *v,
                                         void *opaque, const char *name,
                                         Error **errp)
 {
-    Q35PCIHost *s = Q35_HOST_DEVICE(obj);
+    PCIHostState *h = PCI_HOST_BRIDGE(obj);
+    Range w64;
 
-    visit_type_uint64(v, &s->mch.pci_info.w64.end, name, errp);
+    pci_bus_get_w64_range(h->bus, &w64);
+
+    visit_type_uint64(v, &w64.end, name, errp);
 }
 
 static Property mch_props[] = {
@@ -214,6 +220,16 @@ static void mch_update_pciexbar(MCHPCIState *mch)
     }
     addr = pciexbar & addr_mask;
     pcie_host_mmcfg_update(pehb, enable, addr, length);
+    /* Leave enough space for the MCFG BAR */
+    /*
+     * TODO: this matches current bios behaviour, but it's not a power of two,
+     * which means an MTRR can't cover it exactly.
+     */
+    if (enable) {
+        mch->pci_info.w32.begin = addr + length;
+    } else {
+        mch->pci_info.w32.begin = MCH_HOST_BRIDGE_PCIEXBAR_DEFAULT;
+    }
 }
 
 /* PAM */
index ad1c1ca91e45f5cc721fe76e68c9c4241455c2b1..00554a05acce0a0d3503a145ad720a5adc681634 100644 (file)
@@ -1028,8 +1028,10 @@ static pcibus_t pci_bar_address(PCIDevice *d,
         }
         new_addr = pci_get_long(d->config + bar) & ~(size - 1);
         last_addr = new_addr + size - 1;
-        /* NOTE: we have only 64K ioports on PC */
-        if (last_addr <= new_addr || new_addr == 0 || last_addr > UINT16_MAX) {
+        /* Check if 32 bit BAR wraps around explicitly.
+         * TODO: make priorities correct and remove this work around.
+         */
+        if (last_addr <= new_addr || new_addr == 0 || last_addr >= UINT32_MAX) {
             return PCI_BAR_UNMAPPED;
         }
         return new_addr;
@@ -2257,6 +2259,56 @@ void pci_setup_iommu(PCIBus *bus, PCIIOMMUFunc fn, void *opaque)
     bus->iommu_opaque = opaque;
 }
 
+static void pci_dev_get_w64(PCIBus *b, PCIDevice *dev, void *opaque)
+{
+    Range *range = opaque;
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
+    uint16_t cmd = pci_get_word(dev->config + PCI_COMMAND);
+    int r;
+
+    if (!(cmd & PCI_COMMAND_MEMORY)) {
+        return;
+    }
+
+    if (pc->is_bridge) {
+        pcibus_t base = pci_bridge_get_base(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
+        pcibus_t limit = pci_bridge_get_limit(dev, PCI_BASE_ADDRESS_MEM_PREFETCH);
+
+        base = MAX(base, 0x1ULL << 32);
+
+        if (limit >= base) {
+            Range pref_range;
+            pref_range.begin = base;
+            pref_range.end = limit + 1;
+            range_extend(range, &pref_range);
+        }
+    }
+    for (r = 0; r < PCI_NUM_REGIONS; ++r) {
+        PCIIORegion *region = &dev->io_regions[r];
+        Range region_range;
+
+        if (!region->size ||
+            (region->type & PCI_BASE_ADDRESS_SPACE_IO) ||
+            !(region->type & PCI_BASE_ADDRESS_MEM_TYPE_64)) {
+            continue;
+        }
+        region_range.begin = pci_get_quad(dev->config + pci_bar(dev, r));
+        region_range.end = region_range.begin + region->size;
+
+        region_range.begin = MAX(region_range.begin, 0x1ULL << 32);
+
+        if (region_range.end - 1 >= region_range.begin) {
+            range_extend(range, &region_range);
+        }
+    }
+}
+
+void pci_bus_get_w64_range(PCIBus *bus, Range *range)
+{
+    range->begin = range->end = 0;
+    pci_for_each_device_under_bus(bus, pci_dev_get_w64, range);
+}
+
 static const TypeInfo pci_device_type_info = {
     .name = TYPE_PCI_DEVICE,
     .parent = TYPE_DEVICE,
index 9babeaf2700f13a53560d2a58c42641dd7a3552f..b08ec713f29a80a15b08026b1f7bca7043360670 100644 (file)
@@ -13,8 +13,9 @@
  *
  */
 
-int smbios_entry_add(const char *t);
-void smbios_add_field(int type, int offset, const void *data, size_t len);
+#include "qemu/option.h"
+
+void smbios_entry_add(QemuOpts *opts);
 uint8_t *smbios_get_table(size_t *length);
 
 /*
index 37979aa723725727ae04842225588a1846aa4844..4b90e5d00b26d04947fa422a038f21c2cd3ccfdd 100644 (file)
@@ -397,6 +397,7 @@ const char *pci_root_bus_path(PCIDevice *dev);
 PCIDevice *pci_find_device(PCIBus *bus, int bus_num, uint8_t devfn);
 int pci_qdev_find_device(const char *id, PCIDevice **pdev);
 PCIBus *pci_get_bus_devfn(int *devfnp, PCIBus *root, const char *devaddr);
+void pci_bus_get_w64_range(PCIBus *bus, Range *range);
 
 int pci_parse_devaddr(const char *addr, int *domp, int *busp,
                       unsigned int *slotp, unsigned int *funcp);
index b76cc0df0933fb1fd6a2d788aa65b6d74c14076f..aae972016162dc84973dba051920326a1ce50b72 100644 (file)
@@ -2,6 +2,7 @@
 #define QEMU_RANGE_H
 
 #include <inttypes.h>
+#include <qemu/typedefs.h>
 
 /*
  * Operations on 64 bit address ranges.
@@ -15,7 +16,24 @@ struct Range {
     uint64_t begin; /* First byte of the range, or 0 if empty. */
     uint64_t end;   /* 1 + the last byte. 0 if range empty or ends at ~0x0LL. */
 };
-typedef struct Range Range;
+
+static inline void range_extend(Range *range, Range *extend_by)
+{
+    if (!extend_by->begin && !extend_by->end) {
+        return;
+    }
+    if (!range->begin && !range->end) {
+        *range = *extend_by;
+        return;
+    }
+    if (range->begin > extend_by->begin) {
+        range->begin = extend_by->begin;
+    }
+    /* Compare last byte in case region ends at ~0x0LL */
+    if (range->end - 1 < extend_by->end - 1) {
+        range->end = extend_by->end;
+    }
+}
 
 /* Get last byte of a range from offset + length.
  * Undefined for ranges that wrap around 0. */
index 320554005957549825ff6ab020ddd548381efb55..a4c1b84d69879e54ffacad0e64204d998f8ca2dc 100644 (file)
@@ -68,5 +68,6 @@ typedef struct QEMUSGList QEMUSGList;
 typedef struct SHPCDevice SHPCDevice;
 typedef struct FWCfgState FWCfgState;
 typedef struct PcGuestInfo PcGuestInfo;
+typedef struct Range Range;
 
 #endif /* QEMU_TYPEDEFS_H */
index dece913e7bc28d54639c11eb55c8a4d8028a0599..be71bcac2d6b3941ba4a82d14a8045472f023c27 100644 (file)
@@ -28,7 +28,7 @@ extern const uint32_t arch_type;
 
 void select_soundhw(const char *optarg);
 void do_acpitable_option(const QemuOpts *opts);
-void do_smbios_option(const char *optarg);
+void do_smbios_option(QemuOpts *opts);
 void cpudef_init(void);
 void audio_init(void);
 int tcg_available(void);
index ffc53aa848afdf1d2d46e602cd193e5d43f4d0fc..cd5791eb74df05f296df4fb479d0c873dc69a70b 100644 (file)
@@ -16,6 +16,7 @@ extern const char *bios_name;
 
 extern const char *qemu_name;
 extern uint8_t qemu_uuid[];
+extern bool qemu_uuid_set;
 int qemu_uuid_parse(const char *str, uint8_t *uuid);
 
 #define UUID_FMT "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx"
diff --git a/vl.c b/vl.c
index e4113efbaa8724785df65ffc1bd71e1f3ced9f52..983cdc6eaaf6f8ec2a045fedd18cada514858812 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -254,6 +254,7 @@ uint64_t node_mem[MAX_NODES];
 unsigned long *node_cpumask[MAX_NODES];
 
 uint8_t qemu_uuid[16];
+bool qemu_uuid_set;
 
 static QEMUBootSetHandler *boot_set_handler;
 static void *boot_set_opaque;
@@ -3490,7 +3491,8 @@ int main(int argc, char **argv, char **envp)
                 do_acpitable_option(opts);
                 break;
             case QEMU_OPTION_smbios:
-                do_smbios_option(optarg);
+                opts = qemu_opts_parse(qemu_find_opts("smbios"), optarg, 0);
+                do_smbios_option(opts);
                 break;
             case QEMU_OPTION_enable_kvm:
                 olist = qemu_find_opts("machine");
@@ -3586,6 +3588,7 @@ int main(int argc, char **argv, char **envp)
                             " Wrong format.\n");
                     exit(1);
                 }
+                qemu_uuid_set = true;
                 break;
            case QEMU_OPTION_option_rom:
                if (nb_option_roms >= MAX_OPTION_ROMS) {