diff options
-rwxr-xr-x | configure | 14 | ||||
-rw-r--r-- | hw/net/e1000.c | 2 | ||||
-rw-r--r-- | hw/net/virtio-net.c | 4 | ||||
-rw-r--r-- | hw/pci/pci.c | 2 | ||||
-rw-r--r-- | hw/ppc/spapr.c | 4 | ||||
-rw-r--r-- | hw/ppc/spapr_drc.c | 20 | ||||
-rw-r--r-- | hw/virtio/vhost.c | 84 | ||||
-rw-r--r-- | include/hw/ppc/spapr_drc.h | 1 | ||||
-rw-r--r-- | include/hw/virtio/vhost.h | 11 | ||||
-rw-r--r-- | include/hw/virtio/virtio.h | 2 | ||||
-rw-r--r-- | slirp/ip6_icmp.c | 47 | ||||
-rw-r--r-- | slirp/slirp.c | 2 | ||||
-rw-r--r-- | target/i386/cpu.c | 32 | ||||
-rw-r--r-- | target/i386/cpu.h | 2 | ||||
-rw-r--r-- | tests/acpi-utils.h | 2 | ||||
-rw-r--r-- | util/event_notifier-posix.c | 2 | ||||
-rw-r--r-- | util/event_notifier-win32.c | 1 |
17 files changed, 165 insertions, 67 deletions
@@ -323,6 +323,7 @@ replication="yes" supported_cpu="no" supported_os="no" +bogus_os="no" # parse CC options first for opt do @@ -694,7 +695,10 @@ Linux) supported_os="yes" ;; *) - error_exit "Unsupported host OS $targetos" + # This is a fatal error, but don't report it yet, because we + # might be going to just print the --help text, or it might + # be the result of a missing compiler. + bogus_os="yes" ;; esac @@ -1460,6 +1464,14 @@ if ! compile_prog ; then error_exit "\"$cc\" cannot build an executable (is your linker broken?)" fi +if test "$bogus_os" = "yes"; then + # Now that we know that we're not printing the help and that + # the compiler works (so the results of the check_defines we used + # to identify the OS are reliable), if we didn't recognize the + # host OS we should stop now. + error_exit "Unrecognized host OS $targetos" +fi + # Check that the C++ compiler exists and works with the C compiler if has $cxx; then cat > $TMPC <<EOF diff --git a/hw/net/e1000.c b/hw/net/e1000.c index 93249497f4..f2e5072d27 100644 --- a/hw/net/e1000.c +++ b/hw/net/e1000.c @@ -40,7 +40,7 @@ static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -#define E1000_DEBUG +/* #define E1000_DEBUG */ #ifdef E1000_DEBUG enum { diff --git a/hw/net/virtio-net.c b/hw/net/virtio-net.c index c32168077a..7d091c9259 100644 --- a/hw/net/virtio-net.c +++ b/hw/net/virtio-net.c @@ -510,6 +510,10 @@ static int peer_attach(VirtIONet *n, int index) return 0; } + if (n->max_queues == 1) { + return 0; + } + return tap_enable(nc->peer); } diff --git a/hw/pci/pci.c b/hw/pci/pci.c index e6b08e1988..bd8043c460 100644 --- a/hw/pci/pci.c +++ b/hw/pci/pci.c @@ -869,6 +869,8 @@ static void do_pci_unregister_device(PCIDevice *pci_dev) pci_dev->bus->devices[pci_dev->devfn] = NULL; pci_config_free(pci_dev); + memory_region_del_subregion(&pci_dev->bus_master_container_region, + &pci_dev->bus_master_enable_region); address_space_destroy(&pci_dev->bus_master_as); } diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c index 8aecea3dd1..44c26e4be8 100644 --- a/hw/ppc/spapr.c +++ b/hw/ppc/spapr.c @@ -1524,16 +1524,16 @@ static void htab_save_first_pass(QEMUFile *f, sPAPRMachineState *spapr, /* Consume invalid HPTEs */ while ((index < htabslots) && !HPTE_VALID(HPTE(spapr->htab, index))) { - index++; CLEAN_HPTE(HPTE(spapr->htab, index)); + index++; } /* Consume valid HPTEs */ chunkstart = index; while ((index < htabslots) && (index - chunkstart < USHRT_MAX) && HPTE_VALID(HPTE(spapr->htab, index))) { - index++; CLEAN_HPTE(HPTE(spapr->htab, index)); + index++; } if (index > chunkstart) { diff --git a/hw/ppc/spapr_drc.c b/hw/ppc/spapr_drc.c index 150f6bf2c7..a1cdc875b1 100644 --- a/hw/ppc/spapr_drc.c +++ b/hw/ppc/spapr_drc.c @@ -135,6 +135,17 @@ static uint32_t set_allocation_state(sPAPRDRConnector *drc, if (!drc->dev) { return RTAS_OUT_NO_SUCH_INDICATOR; } + if (drc->awaiting_release && drc->awaiting_allocation) { + /* kernel is acknowledging a previous hotplug event + * while we are already removing it. + * it's safe to ignore awaiting_allocation here since we know the + * situation is predicated on the guest either already having done + * so (boot-time hotplug), or never being able to acquire in the + * first place (hotplug followed by immediate unplug). + */ + drc->awaiting_allocation_skippable = true; + return RTAS_OUT_NO_SUCH_INDICATOR; + } } if (drc->type != SPAPR_DR_CONNECTOR_TYPE_PCI) { @@ -436,9 +447,11 @@ static void detach(sPAPRDRConnector *drc, DeviceState *d, } if (drc->awaiting_allocation) { - drc->awaiting_release = true; - trace_spapr_drc_awaiting_allocation(get_index(drc)); - return; + if (!drc->awaiting_allocation_skippable) { + drc->awaiting_release = true; + trace_spapr_drc_awaiting_allocation(get_index(drc)); + return; + } } drc->indicator_state = SPAPR_DR_INDICATOR_STATE_INACTIVE; @@ -448,6 +461,7 @@ static void detach(sPAPRDRConnector *drc, DeviceState *d, } drc->awaiting_release = false; + drc->awaiting_allocation_skippable = false; g_free(drc->fdt); drc->fdt = NULL; drc->fdt_start_offset = 0; diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c index febe519bbd..613494dcc2 100644 --- a/hw/virtio/vhost.c +++ b/hw/virtio/vhost.c @@ -425,10 +425,8 @@ static inline void vhost_dev_log_resize(struct vhost_dev *dev, uint64_t size) static int vhost_dev_has_iommu(struct vhost_dev *dev) { VirtIODevice *vdev = dev->vdev; - AddressSpace *dma_as = vdev->dma_as; - return memory_region_is_iommu(dma_as->root) && - virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); + return virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM); } static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr, @@ -720,6 +718,63 @@ static void vhost_region_del(MemoryListener *listener, } } +static void vhost_iommu_unmap_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) +{ + struct vhost_iommu *iommu = container_of(n, struct vhost_iommu, n); + struct vhost_dev *hdev = iommu->hdev; + hwaddr iova = iotlb->iova + iommu->iommu_offset; + + if (hdev->vhost_ops->vhost_invalidate_device_iotlb(hdev, iova, + iotlb->addr_mask + 1)) { + error_report("Fail to invalidate device iotlb"); + } +} + +static void vhost_iommu_region_add(MemoryListener *listener, + MemoryRegionSection *section) +{ + struct vhost_dev *dev = container_of(listener, struct vhost_dev, + iommu_listener); + struct vhost_iommu *iommu; + + if (!memory_region_is_iommu(section->mr)) { + return; + } + + iommu = g_malloc0(sizeof(*iommu)); + iommu->n.notify = vhost_iommu_unmap_notify; + iommu->n.notifier_flags = IOMMU_NOTIFIER_UNMAP; + iommu->mr = section->mr; + iommu->iommu_offset = section->offset_within_address_space - + section->offset_within_region; + iommu->hdev = dev; + memory_region_register_iommu_notifier(section->mr, &iommu->n); + QLIST_INSERT_HEAD(&dev->iommu_list, iommu, iommu_next); + /* TODO: can replay help performance here? */ +} + +static void vhost_iommu_region_del(MemoryListener *listener, + MemoryRegionSection *section) +{ + struct vhost_dev *dev = container_of(listener, struct vhost_dev, + iommu_listener); + struct vhost_iommu *iommu; + + if (!memory_region_is_iommu(section->mr)) { + return; + } + + QLIST_FOREACH(iommu, &dev->iommu_list, iommu_next) { + if (iommu->mr == section->mr) { + memory_region_unregister_iommu_notifier(iommu->mr, + &iommu->n); + QLIST_REMOVE(iommu, iommu_next); + g_free(iommu); + break; + } + } +} + static void vhost_region_nop(MemoryListener *listener, MemoryRegionSection *section) { @@ -1161,17 +1216,6 @@ static void vhost_virtqueue_cleanup(struct vhost_virtqueue *vq) event_notifier_cleanup(&vq->masked_notifier); } -static void vhost_iommu_unmap_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb) -{ - struct vhost_dev *hdev = container_of(n, struct vhost_dev, n); - - if (hdev->vhost_ops->vhost_invalidate_device_iotlb(hdev, - iotlb->iova, - iotlb->addr_mask + 1)) { - error_report("Fail to invalidate device iotlb"); - } -} - int vhost_dev_init(struct vhost_dev *hdev, void *opaque, VhostBackendType backend_type, uint32_t busyloop_timeout) { @@ -1244,8 +1288,10 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque, .priority = 10 }; - hdev->n.notify = vhost_iommu_unmap_notify; - hdev->n.notifier_flags = IOMMU_NOTIFIER_UNMAP; + hdev->iommu_listener = (MemoryListener) { + .region_add = vhost_iommu_region_add, + .region_del = vhost_iommu_region_del, + }; if (hdev->migration_blocker == NULL) { if (!(hdev->features & (0x1ULL << VHOST_F_LOG_ALL))) { @@ -1455,8 +1501,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev) } if (vhost_dev_has_iommu(hdev)) { - memory_region_register_iommu_notifier(vdev->dma_as->root, - &hdev->n); + memory_listener_register(&hdev->iommu_listener, vdev->dma_as); } r = hdev->vhost_ops->vhost_set_mem_table(hdev, hdev->mem); @@ -1538,8 +1583,7 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev) if (vhost_dev_has_iommu(hdev)) { hdev->vhost_ops->vhost_set_iotlb_callback(hdev, false); - memory_region_unregister_iommu_notifier(vdev->dma_as->root, - &hdev->n); + memory_listener_unregister(&hdev->iommu_listener); } vhost_log_put(hdev, true); hdev->started = false; diff --git a/include/hw/ppc/spapr_drc.h b/include/hw/ppc/spapr_drc.h index fa531d5c26..5524247cdc 100644 --- a/include/hw/ppc/spapr_drc.h +++ b/include/hw/ppc/spapr_drc.h @@ -154,6 +154,7 @@ typedef struct sPAPRDRConnector { bool awaiting_release; bool signalled; bool awaiting_allocation; + bool awaiting_allocation_skippable; /* device pointer, via link property */ DeviceState *dev; diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h index 52f633ec89..a45032163d 100644 --- a/include/hw/virtio/vhost.h +++ b/include/hw/virtio/vhost.h @@ -37,10 +37,20 @@ struct vhost_log { vhost_log_chunk_t *log; }; +struct vhost_dev; +struct vhost_iommu { + struct vhost_dev *hdev; + MemoryRegion *mr; + hwaddr iommu_offset; + IOMMUNotifier n; + QLIST_ENTRY(vhost_iommu) iommu_next; +}; + struct vhost_memory; struct vhost_dev { VirtIODevice *vdev; MemoryListener memory_listener; + MemoryListener iommu_listener; struct vhost_memory *mem; int n_mem_sections; MemoryRegionSection *mem_sections; @@ -64,6 +74,7 @@ struct vhost_dev { void *opaque; struct vhost_log *log; QLIST_ENTRY(vhost_dev) entry; + QLIST_HEAD(, vhost_iommu) iommu_list; IOMMUNotifier n; }; diff --git a/include/hw/virtio/virtio.h b/include/hw/virtio/virtio.h index 15efcf2057..7b6edbafd7 100644 --- a/include/hw/virtio/virtio.h +++ b/include/hw/virtio/virtio.h @@ -34,7 +34,7 @@ struct VirtQueue; static inline hwaddr vring_align(hwaddr addr, unsigned long align) { - return (addr + align - 1) & ~(align - 1); + return QEMU_ALIGN_UP(addr, align); } typedef struct VirtQueue VirtQueue; diff --git a/slirp/ip6_icmp.c b/slirp/ip6_icmp.c index 298a48dd25..777eb574be 100644 --- a/slirp/ip6_icmp.c +++ b/slirp/ip6_icmp.c @@ -143,17 +143,13 @@ void ndp_send_ra(Slirp *slirp) /* Build IPv6 packet */ struct mbuf *t = m_get(slirp); struct ip6 *rip = mtod(t, struct ip6 *); + size_t pl_size = 0; + struct in6_addr addr; + uint32_t scope_id; + rip->ip_src = (struct in6_addr)LINKLOCAL_ADDR; rip->ip_dst = (struct in6_addr)ALLNODES_MULTICAST; rip->ip_nh = IPPROTO_ICMPV6; - rip->ip_pl = htons(ICMP6_NDP_RA_MINLEN - + NDPOPT_LINKLAYER_LEN - + NDPOPT_PREFIXINFO_LEN -#ifndef _WIN32 - + NDPOPT_RDNSS_LEN -#endif - ); - t->m_len = sizeof(struct ip6) + ntohs(rip->ip_pl); /* Build ICMPv6 packet */ t->m_data += sizeof(struct ip6); @@ -171,6 +167,7 @@ void ndp_send_ra(Slirp *slirp) ricmp->icmp6_nra.reach_time = htonl(NDP_AdvReachableTime); ricmp->icmp6_nra.retrans_time = htonl(NDP_AdvRetransTime); t->m_data += ICMP6_NDP_RA_MINLEN; + pl_size += ICMP6_NDP_RA_MINLEN; /* Source link-layer address (NDP option) */ struct ndpopt *opt = mtod(t, struct ndpopt *); @@ -178,6 +175,7 @@ void ndp_send_ra(Slirp *slirp) opt->ndpopt_len = NDPOPT_LINKLAYER_LEN / 8; in6_compute_ethaddr(rip->ip_src, opt->ndpopt_linklayer); t->m_data += NDPOPT_LINKLAYER_LEN; + pl_size += NDPOPT_LINKLAYER_LEN; /* Prefix information (NDP option) */ struct ndpopt *opt2 = mtod(t, struct ndpopt *); @@ -192,27 +190,26 @@ void ndp_send_ra(Slirp *slirp) opt2->ndpopt_prefixinfo.reserved2 = 0; opt2->ndpopt_prefixinfo.prefix = slirp->vprefix_addr6; t->m_data += NDPOPT_PREFIXINFO_LEN; + pl_size += NDPOPT_PREFIXINFO_LEN; -#ifndef _WIN32 /* Prefix information (NDP option) */ - /* disabled for windows for now, until get_dns6_addr is implemented */ - struct ndpopt *opt3 = mtod(t, struct ndpopt *); - opt3->ndpopt_type = NDPOPT_RDNSS; - opt3->ndpopt_len = NDPOPT_RDNSS_LEN / 8; - opt3->ndpopt_rdnss.reserved = 0; - opt3->ndpopt_rdnss.lifetime = htonl(2 * NDP_MaxRtrAdvInterval); - opt3->ndpopt_rdnss.addr = slirp->vnameserver_addr6; - t->m_data += NDPOPT_RDNSS_LEN; -#endif + if (get_dns6_addr(&addr, &scope_id) >= 0) { + /* Host system does have an IPv6 DNS server, announce our proxy. */ + struct ndpopt *opt3 = mtod(t, struct ndpopt *); + opt3->ndpopt_type = NDPOPT_RDNSS; + opt3->ndpopt_len = NDPOPT_RDNSS_LEN / 8; + opt3->ndpopt_rdnss.reserved = 0; + opt3->ndpopt_rdnss.lifetime = htonl(2 * NDP_MaxRtrAdvInterval); + opt3->ndpopt_rdnss.addr = slirp->vnameserver_addr6; + t->m_data += NDPOPT_RDNSS_LEN; + pl_size += NDPOPT_RDNSS_LEN; + } + + rip->ip_pl = htons(pl_size); + t->m_data -= sizeof(struct ip6) + pl_size; + t->m_len = sizeof(struct ip6) + pl_size; /* ICMPv6 Checksum */ -#ifndef _WIN32 - t->m_data -= NDPOPT_RDNSS_LEN; -#endif - t->m_data -= NDPOPT_PREFIXINFO_LEN; - t->m_data -= NDPOPT_LINKLAYER_LEN; - t->m_data -= ICMP6_NDP_RA_MINLEN; - t->m_data -= sizeof(struct ip6); ricmp->icmp6_cksum = ip6_cksum(t); ip6_output(NULL, t, 0); diff --git a/slirp/slirp.c b/slirp/slirp.c index 60539de7a3..5a94b06f5e 100644 --- a/slirp/slirp.c +++ b/slirp/slirp.c @@ -198,7 +198,7 @@ static int get_dns_addr_resolv_conf(int af, void *pdns_addr, void *cached_addr, #ifdef DEBUG else { char s[INET6_ADDRSTRLEN]; - char *res = inet_ntop(af, tmp_addr, s, sizeof(s)); + const char *res = inet_ntop(af, tmp_addr, s, sizeof(s)); if (!res) { res = "(string conversion error)"; } diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 7aa762245a..13c0985f11 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -3373,15 +3373,19 @@ static void x86_cpu_expand_features(X86CPU *cpu, Error **errp) GList *l; Error *local_err = NULL; - /*TODO: cpu->max_features incorrectly overwrites features - * set using "feat=on|off". Once we fix this, we can convert + /*TODO: Now cpu->max_features doesn't overwrite features + * set using QOM properties, and we can convert * plus_features & minus_features to global properties * inside x86_cpu_parse_featurestr() too. */ if (cpu->max_features) { for (w = 0; w < FEATURE_WORDS; w++) { - env->features[w] = - x86_cpu_get_supported_feature_word(w, cpu->migratable); + /* Override only features that weren't set explicitly + * by the user. + */ + env->features[w] |= + x86_cpu_get_supported_feature_word(w, cpu->migratable) & + ~env->user_features[w]; } } @@ -3692,15 +3696,17 @@ static void x86_cpu_unrealizefn(DeviceState *dev, Error **errp) } typedef struct BitProperty { - uint32_t *ptr; + FeatureWord w; uint32_t mask; } BitProperty; static void x86_cpu_get_bit_prop(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { + X86CPU *cpu = X86_CPU(obj); BitProperty *fp = opaque; - bool value = (*fp->ptr & fp->mask) == fp->mask; + uint32_t f = cpu->env.features[fp->w]; + bool value = (f & fp->mask) == fp->mask; visit_type_bool(v, name, &value, errp); } @@ -3708,6 +3714,7 @@ static void x86_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { DeviceState *dev = DEVICE(obj); + X86CPU *cpu = X86_CPU(obj); BitProperty *fp = opaque; Error *local_err = NULL; bool value; @@ -3724,10 +3731,11 @@ static void x86_cpu_set_bit_prop(Object *obj, Visitor *v, const char *name, } if (value) { - *fp->ptr |= fp->mask; + cpu->env.features[fp->w] |= fp->mask; } else { - *fp->ptr &= ~fp->mask; + cpu->env.features[fp->w] &= ~fp->mask; } + cpu->env.user_features[fp->w] |= fp->mask; } static void x86_cpu_release_bit_prop(Object *obj, const char *name, @@ -3745,7 +3753,7 @@ static void x86_cpu_release_bit_prop(Object *obj, const char *name, */ static void x86_cpu_register_bit_prop(X86CPU *cpu, const char *prop_name, - uint32_t *field, + FeatureWord w, int bitnr) { BitProperty *fp; @@ -3755,11 +3763,11 @@ static void x86_cpu_register_bit_prop(X86CPU *cpu, op = object_property_find(OBJECT(cpu), prop_name, NULL); if (op) { fp = op->opaque; - assert(fp->ptr == field); + assert(fp->w == w); fp->mask |= mask; } else { fp = g_new0(BitProperty, 1); - fp->ptr = field; + fp->w = w; fp->mask = mask; object_property_add(OBJECT(cpu), prop_name, "bool", x86_cpu_get_bit_prop, @@ -3787,7 +3795,7 @@ static void x86_cpu_register_feature_bit_props(X86CPU *cpu, /* aliases don't use "|" delimiters anymore, they are registered * manually using object_property_add_alias() */ assert(!strchr(name, '|')); - x86_cpu_register_bit_prop(cpu, name, &cpu->env.features[w], bitnr); + x86_cpu_register_bit_prop(cpu, name, w, bitnr); } static GuestPanicInformation *x86_cpu_get_crash_info(CPUState *cs) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 07401ad9fe..c4602ca80d 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1147,6 +1147,8 @@ typedef struct CPUX86State { uint32_t cpuid_vendor3; uint32_t cpuid_version; FeatureWordArray features; + /* Features that were explicitly enabled/disabled */ + FeatureWordArray user_features; uint32_t cpuid_model[12]; /* MTRRs */ diff --git a/tests/acpi-utils.h b/tests/acpi-utils.h index 9f9a2d532c..348e4d7931 100644 --- a/tests/acpi-utils.h +++ b/tests/acpi-utils.h @@ -26,7 +26,7 @@ typedef struct { gsize asl_len; gchar *asl_file; bool tmp_files_retain; /* do not delete the temp asl/aml */ -} QEMU_PACKED AcpiSdtTable; +} AcpiSdtTable; #define ACPI_READ_FIELD(field, addr) \ do { \ diff --git a/util/event_notifier-posix.c b/util/event_notifier-posix.c index 7e40252ade..acdbe3b483 100644 --- a/util/event_notifier-posix.c +++ b/util/event_notifier-posix.c @@ -81,8 +81,10 @@ void event_notifier_cleanup(EventNotifier *e) { if (e->rfd != e->wfd) { close(e->rfd); + e->rfd = -1; } close(e->wfd); + e->wfd = -1; } int event_notifier_get_fd(const EventNotifier *e) diff --git a/util/event_notifier-win32.c b/util/event_notifier-win32.c index 519fb59123..62c53b0a99 100644 --- a/util/event_notifier-win32.c +++ b/util/event_notifier-win32.c @@ -25,6 +25,7 @@ int event_notifier_init(EventNotifier *e, int active) void event_notifier_cleanup(EventNotifier *e) { CloseHandle(e->event); + e->event = NULL; } HANDLE event_notifier_get_handle(EventNotifier *e) |