Merge remote-tracking branch 'remotes/riku/linux-user-for-upstream' into staging

* remotes/riku/linux-user-for-upstream:
  linux-user: use TARGET_SA_ONSTACK in get_sigframe
  alloca one extra byte sockets
  linux-user: handle AF_PACKET sockaddrs in target_to_host_sockaddr
  qemu-user: Impl. setsockopt(SO_BINDTODEVICE)
  SIOCGIFINDEX: fix typo

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
diff --git a/block/linux-aio.c b/block/linux-aio.c
index 4867369..7ac7e8c 100644
--- a/block/linux-aio.c
+++ b/block/linux-aio.c
@@ -310,5 +310,10 @@
     struct qemu_laio_state *s = s_;
 
     event_notifier_cleanup(&s->e);
+
+    if (io_destroy(s->ctx) != 0) {
+        fprintf(stderr, "%s: destroy AIO context %p failed\n",
+                        __func__, &s->ctx);
+    }
     g_free(s);
 }
diff --git a/hw/block/dataplane/virtio-blk.c b/hw/block/dataplane/virtio-blk.c
index 227bb15..d6ba65c 100644
--- a/hw/block/dataplane/virtio-blk.c
+++ b/hw/block/dataplane/virtio-blk.c
@@ -34,6 +34,7 @@
     VirtIODevice *vdev;
     Vring vring;                    /* virtqueue vring */
     EventNotifier *guest_notifier;  /* irq */
+    QEMUBH *bh;                     /* bh for guest notification */
 
     /* Note that these EventNotifiers are assigned by value.  This is
      * fine as long as you do not call event_notifier_cleanup on them
@@ -61,13 +62,28 @@
     event_notifier_set(s->guest_notifier);
 }
 
+static void notify_guest_bh(void *opaque)
+{
+    VirtIOBlockDataPlane *s = opaque;
+
+    notify_guest(s);
+}
+
 static void complete_request_vring(VirtIOBlockReq *req, unsigned char status)
 {
+    VirtIOBlockDataPlane *s = req->dev->dataplane;
     stb_p(&req->in->status, status);
 
     vring_push(&req->dev->dataplane->vring, &req->elem,
                req->qiov.size + sizeof(*req->in));
-    notify_guest(req->dev->dataplane);
+
+    /* Suppress notification to guest by BH and its scheduled
+     * flag because requests are completed as a batch after io
+     * plug & unplug is introduced, and the BH can still be
+     * executed in dataplane aio context even after it is
+     * stopped, so needn't worry about notification loss with BH.
+     */
+    qemu_bh_schedule(s->bh);
 }
 
 static void handle_notify(EventNotifier *e)
@@ -125,7 +141,6 @@
                                   Error **errp)
 {
     VirtIOBlockDataPlane *s;
-    VirtIOBlock *vblk = VIRTIO_BLK(vdev);
     Error *local_err = NULL;
     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(vdev)));
     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
@@ -173,13 +188,12 @@
         s->iothread = &s->internal_iothread_obj;
     }
     s->ctx = iothread_get_aio_context(s->iothread);
+    s->bh = aio_bh_new(s->ctx, notify_guest_bh, s);
 
     error_setg(&s->blocker, "block device is in use by data plane");
     bdrv_op_block_all(blk->conf.bs, s->blocker);
 
     *dataplane = s;
-    s->saved_complete_request = vblk->complete_request;
-    vblk->complete_request = complete_request_vring;
 }
 
 /* Context: QEMU global mutex held */
@@ -193,6 +207,7 @@
     bdrv_op_unblock_all(s->blk->conf.bs, s->blocker);
     error_free(s->blocker);
     object_unref(OBJECT(s->iothread));
+    qemu_bh_delete(s->bh);
     g_free(s);
 }
 
@@ -201,6 +216,7 @@
 {
     BusState *qbus = BUS(qdev_get_parent_bus(DEVICE(s->vdev)));
     VirtioBusClass *k = VIRTIO_BUS_GET_CLASS(qbus);
+    VirtIOBlock *vblk = VIRTIO_BLK(s->vdev);
     VirtQueue *vq;
 
     if (s->started) {
@@ -234,6 +250,9 @@
     }
     s->host_notifier = *virtio_queue_get_host_notifier(vq);
 
+    s->saved_complete_request = vblk->complete_request;
+    vblk->complete_request = complete_request_vring;
+
     s->starting = false;
     s->started = true;
     trace_virtio_blk_data_plane_start(s);
diff --git a/hw/misc/vfio.c b/hw/misc/vfio.c
index aef4c9c..0b9eba0 100644
--- a/hw/misc/vfio.c
+++ b/hw/misc/vfio.c
@@ -2489,7 +2489,7 @@
         return;
     }
 
-    if (iotlb->perm != IOMMU_NONE) {
+    if ((iotlb->perm & IOMMU_RW) != IOMMU_NONE) {
         vaddr = memory_region_get_ram_ptr(mr) + xlat;
 
         ret = vfio_dma_map(container, iotlb->iova,
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index bb2e75f..1a5b30d 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -701,8 +701,7 @@
     machine->ram_size = ram_size;
 
     /* Register Memory */
-    memory_region_init_ram(ram, NULL, "mpc8544ds.ram", ram_size);
-    vmstate_register_ram_global(ram);
+    memory_region_allocate_system_memory(ram, NULL, "mpc8544ds.ram", ram_size);
     memory_region_add_subregion(address_space_mem, 0, ram);
 
     dev = qdev_create(NULL, "e500-ccsr");
diff --git a/hw/ppc/mac_newworld.c b/hw/ppc/mac_newworld.c
index 89d3cad..7e97af4 100644
--- a/hw/ppc/mac_newworld.c
+++ b/hw/ppc/mac_newworld.c
@@ -200,13 +200,12 @@
     }
 
     /* allocate RAM */
-    memory_region_init_ram(ram, NULL, "ppc_core99.ram", ram_size);
-    vmstate_register_ram_global(ram);
+    memory_region_allocate_system_memory(ram, NULL, "ppc_core99.ram", ram_size);
     memory_region_add_subregion(get_system_memory(), 0, ram);
 
     /* allocate and load BIOS */
-    memory_region_init_ram(bios, NULL, "ppc_core99.bios", BIOS_SIZE);
-    vmstate_register_ram_global(bios);
+    memory_region_allocate_system_memory(bios, NULL, "ppc_core99.bios",
+                                         BIOS_SIZE);
     if (bios_name == NULL)
         bios_name = PROM_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
diff --git a/hw/ppc/mac_oldworld.c b/hw/ppc/mac_oldworld.c
index 4b5e905..afae825 100644
--- a/hw/ppc/mac_oldworld.c
+++ b/hw/ppc/mac_oldworld.c
@@ -130,13 +130,13 @@
         exit(1);
     }
 
-    memory_region_init_ram(ram, NULL, "ppc_heathrow.ram", ram_size);
-    vmstate_register_ram_global(ram);
+    memory_region_allocate_system_memory(ram, NULL, "ppc_heathrow.ram",
+                                         ram_size);
     memory_region_add_subregion(sysmem, 0, ram);
 
     /* allocate and load BIOS */
-    memory_region_init_ram(bios, NULL, "ppc_heathrow.bios", BIOS_SIZE);
-    vmstate_register_ram_global(bios);
+    memory_region_allocate_system_memory(bios, NULL, "ppc_heathrow.bios",
+                                         BIOS_SIZE);
     if (bios_name == NULL)
         bios_name = PROM_FILENAME;
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
diff --git a/hw/ppc/ppc405_boards.c b/hw/ppc/ppc405_boards.c
index 98ad2d7..6b566cd 100644
--- a/hw/ppc/ppc405_boards.c
+++ b/hw/ppc/ppc405_boards.c
@@ -199,8 +199,8 @@
     MemoryRegion *sysmem = get_system_memory();
 
     /* XXX: fix this */
-    memory_region_init_ram(&ram_memories[0], NULL, "ef405ep.ram", 0x08000000);
-    vmstate_register_ram_global(&ram_memories[0]);
+    memory_region_allocate_system_memory(&ram_memories[0], NULL, "ef405ep.ram",
+                                         0x08000000);
     ram_bases[0] = 0;
     ram_sizes[0] = 0x08000000;
     memory_region_init(&ram_memories[1], NULL, "ef405ep.ram1", 0);
@@ -214,8 +214,7 @@
                         33333333, &pic, kernel_filename == NULL ? 0 : 1);
     /* allocate SRAM */
     sram_size = 512 * 1024;
-    memory_region_init_ram(sram, NULL, "ef405ep.sram", sram_size);
-    vmstate_register_ram_global(sram);
+    memory_region_allocate_system_memory(sram, NULL, "ef405ep.sram", sram_size);
     memory_region_add_subregion(sysmem, 0xFFF00000, sram);
     /* allocate and load BIOS */
 #ifdef DEBUG_BOARD_INIT
@@ -246,8 +245,8 @@
         printf("Load BIOS from file\n");
 #endif
         bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, NULL, "ef405ep.bios", BIOS_SIZE);
-        vmstate_register_ram_global(bios);
+        memory_region_allocate_system_memory(bios, NULL, "ef405ep.bios",
+                                             BIOS_SIZE);
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
@@ -518,14 +517,12 @@
     DriveInfo *dinfo;
 
     /* RAM is soldered to the board so the size cannot be changed */
-    memory_region_init_ram(&ram_memories[0], NULL,
+    memory_region_allocate_system_memory(&ram_memories[0], NULL,
                            "taihu_405ep.ram-0", 0x04000000);
-    vmstate_register_ram_global(&ram_memories[0]);
     ram_bases[0] = 0;
     ram_sizes[0] = 0x04000000;
-    memory_region_init_ram(&ram_memories[1], NULL,
+    memory_region_allocate_system_memory(&ram_memories[1], NULL,
                            "taihu_405ep.ram-1", 0x04000000);
-    vmstate_register_ram_global(&ram_memories[1]);
     ram_bases[1] = 0x04000000;
     ram_sizes[1] = 0x04000000;
     ram_size = 0x08000000;
@@ -567,8 +564,8 @@
         if (bios_name == NULL)
             bios_name = BIOS_FILENAME;
         bios = g_new(MemoryRegion, 1);
-        memory_region_init_ram(bios, NULL, "taihu_405ep.bios", BIOS_SIZE);
-        vmstate_register_ram_global(bios);
+        memory_region_allocate_system_memory(bios, NULL, "taihu_405ep.bios",
+                                             BIOS_SIZE);
         filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
         if (filename) {
             bios_size = load_image(filename, memory_region_get_ram_ptr(bios));
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index 54ba59e..fcd5f2d 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -23,6 +23,7 @@
  */
 #include "hw/hw.h"
 #include "hw/ppc/ppc.h"
+#include "hw/boards.h"
 #include "ppc405.h"
 #include "hw/char/serial.h"
 #include "qemu/timer.h"
@@ -973,8 +974,8 @@
 
     ocm = g_malloc0(sizeof(ppc405_ocm_t));
     /* XXX: Size is 4096 or 0x04000000 */
-    memory_region_init_ram(&ocm->isarc_ram, NULL, "ppc405.ocm", 4096);
-    vmstate_register_ram_global(&ocm->isarc_ram);
+    memory_region_allocate_system_memory(&ocm->isarc_ram, NULL, "ppc405.ocm",
+                                         4096);
     memory_region_init_alias(&ocm->dsarc_ram, NULL, "ppc405.dsarc", &ocm->isarc_ram,
                              0, 4096);
     qemu_register_reset(&ocm_reset, ocm);
diff --git a/hw/ppc/ppc4xx_devs.c b/hw/ppc/ppc4xx_devs.c
index 8a43111..07f9d00 100644
--- a/hw/ppc/ppc4xx_devs.c
+++ b/hw/ppc/ppc4xx_devs.c
@@ -24,6 +24,7 @@
 #include "hw/hw.h"
 #include "hw/ppc/ppc.h"
 #include "hw/ppc/ppc4xx.h"
+#include "hw/boards.h"
 #include "qemu/log.h"
 #include "exec/address-spaces.h"
 
@@ -694,8 +695,8 @@
             if (bank_size <= size_left) {
                 char name[32];
                 snprintf(name, sizeof(name), "ppc4xx.sdram%d", i);
-                memory_region_init_ram(&ram_memories[i], NULL, name, bank_size);
-                vmstate_register_ram_global(&ram_memories[i]);
+                memory_region_allocate_system_memory(&ram_memories[i], NULL,
+                                                     name, bank_size);
                 ram_bases[i] = base;
                 ram_sizes[i] = bank_size;
                 base += bank_size;
diff --git a/hw/ppc/prep.c b/hw/ppc/prep.c
index aa8717d..f0ef1af 100644
--- a/hw/ppc/prep.c
+++ b/hw/ppc/prep.c
@@ -417,8 +417,7 @@
     }
 
     /* allocate RAM */
-    memory_region_init_ram(ram, NULL, "ppc_prep.ram", ram_size);
-    vmstate_register_ram_global(ram);
+    memory_region_allocate_system_memory(ram, NULL, "ppc_prep.ram", ram_size);
     memory_region_add_subregion(sysmem, 0, ram);
 
     if (linux_boot) {
diff --git a/hw/ppc/spapr.c b/hw/ppc/spapr.c
index a23c0f0..d01978f 100644
--- a/hw/ppc/spapr.c
+++ b/hw/ppc/spapr.c
@@ -1223,6 +1223,8 @@
     int i;
     MemoryRegion *sysmem = get_system_memory();
     MemoryRegion *ram = g_new(MemoryRegion, 1);
+    MemoryRegion *rma_region;
+    void *rma = NULL;
     hwaddr rma_alloc_size;
     hwaddr node0_size = (nb_numa_nodes > 1) ? numa_info[0].node_mem : ram_size;
     uint32_t initrd_base = 0;
@@ -1239,7 +1241,7 @@
     cpu_ppc_hypercall = emulate_spapr_hypercall;
 
     /* Allocate RMA if necessary */
-    rma_alloc_size = kvmppc_alloc_rma("ppc_spapr.rma", sysmem);
+    rma_alloc_size = kvmppc_alloc_rma(&rma);
 
     if (rma_alloc_size == -1) {
         hw_error("qemu: Unable to create RMA\n");
@@ -1333,13 +1335,16 @@
 
     /* allocate RAM */
     spapr->ram_limit = ram_size;
-    if (spapr->ram_limit > rma_alloc_size) {
-        ram_addr_t nonrma_base = rma_alloc_size;
-        ram_addr_t nonrma_size = spapr->ram_limit - rma_alloc_size;
+    memory_region_allocate_system_memory(ram, NULL, "ppc_spapr.ram",
+                                         spapr->ram_limit);
+    memory_region_add_subregion(sysmem, 0, ram);
 
-        memory_region_init_ram(ram, NULL, "ppc_spapr.ram", nonrma_size);
-        vmstate_register_ram_global(ram);
-        memory_region_add_subregion(sysmem, nonrma_base, ram);
+    if (rma_alloc_size && rma) {
+        rma_region = g_new(MemoryRegion, 1);
+        memory_region_init_ram_ptr(rma_region, NULL, "ppc_spapr.rma",
+                                   rma_alloc_size, rma);
+        vmstate_register_ram_global(rma_region);
+        memory_region_add_subregion(sysmem, 0, rma_region);
     }
 
     filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "spapr-rtas.bin");
diff --git a/hw/ppc/spapr_iommu.c b/hw/ppc/spapr_iommu.c
index 698ae60..f6e32a4 100644
--- a/hw/ppc/spapr_iommu.c
+++ b/hw/ppc/spapr_iommu.c
@@ -81,7 +81,7 @@
         ret.iova = addr & page_mask;
         ret.translated_addr = tce & page_mask;
         ret.addr_mask = ~page_mask;
-        ret.perm = tce;
+        ret.perm = tce & IOMMU_RW;
     }
     trace_spapr_iommu_xlate(tcet->liobn, addr, ret.iova, ret.perm,
                             ret.addr_mask);
@@ -223,7 +223,7 @@
     entry.iova = ioba & page_mask;
     entry.translated_addr = tce & page_mask;
     entry.addr_mask = ~page_mask;
-    entry.perm = tce;
+    entry.perm = tce & IOMMU_RW;
     memory_region_notify_iommu(&tcet->iommu, entry);
 
     return H_SUCCESS;
diff --git a/hw/ppc/virtex_ml507.c b/hw/ppc/virtex_ml507.c
index 02b4f82..0de5148 100644
--- a/hw/ppc/virtex_ml507.c
+++ b/hw/ppc/virtex_ml507.c
@@ -222,8 +222,7 @@
     env = &cpu->env;
     qemu_register_reset(main_cpu_reset, cpu);
 
-    memory_region_init_ram(phys_ram, NULL, "ram", ram_size);
-    vmstate_register_ram_global(phys_ram);
+    memory_region_allocate_system_memory(phys_ram, NULL, "ram", ram_size);
     memory_region_add_subregion(address_space_mem, ram_base, phys_ram);
 
     dinfo = drive_get(IF_PFLASH, 0, 0);
diff --git a/target-ppc/kvm.c b/target-ppc/kvm.c
index 2d87108..42718f7 100644
--- a/target-ppc/kvm.c
+++ b/target-ppc/kvm.c
@@ -1580,13 +1580,11 @@
 }
 
 #ifdef TARGET_PPC64
-off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
+off_t kvmppc_alloc_rma(void **rma)
 {
-    void *rma;
     off_t size;
     int fd;
     struct kvm_allocate_rma ret;
-    MemoryRegion *rma_region;
 
     /* If cap_ppc_rma == 0, contiguous RMA allocation is not supported
      * if cap_ppc_rma == 1, contiguous RMA allocation is supported, but
@@ -1609,17 +1607,12 @@
 
     size = MIN(ret.rma_size, 256ul << 20);
 
-    rma = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
-    if (rma == MAP_FAILED) {
+    *rma = mmap(NULL, size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+    if (*rma == MAP_FAILED) {
         fprintf(stderr, "KVM: Error mapping RMA: %s\n", strerror(errno));
         return -1;
     };
 
-    rma_region = g_new(MemoryRegion, 1);
-    memory_region_init_ram_ptr(rma_region, NULL, name, size, rma);
-    vmstate_register_ram_global(rma_region);
-    memory_region_add_subregion(sysmem, 0, rma_region);
-
     return size;
 }
 
diff --git a/target-ppc/kvm_ppc.h b/target-ppc/kvm_ppc.h
index 1118122..d9516e7 100644
--- a/target-ppc/kvm_ppc.h
+++ b/target-ppc/kvm_ppc.h
@@ -31,7 +31,7 @@
 int kvmppc_set_tcr(PowerPCCPU *cpu);
 int kvmppc_booke_watchdog_enable(PowerPCCPU *cpu);
 #ifndef CONFIG_USER_ONLY
-off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem);
+off_t kvmppc_alloc_rma(void **rma);
 bool kvmppc_spapr_use_multitce(void);
 void *kvmppc_create_spapr_tce(uint32_t liobn, uint32_t window_size, int *pfd,
                               bool vfio_accel);
@@ -134,7 +134,7 @@
 }
 
 #ifndef CONFIG_USER_ONLY
-static inline off_t kvmppc_alloc_rma(const char *name, MemoryRegion *sysmem)
+static inline off_t kvmppc_alloc_rma(void **rma)
 {
     return 0;
 }
diff --git a/target-ppc/translate_init.c b/target-ppc/translate_init.c
index 5eacd46..48177ed 100644
--- a/target-ppc/translate_init.c
+++ b/target-ppc/translate_init.c
@@ -9098,29 +9098,21 @@
 
 int ppc_get_compat_smt_threads(PowerPCCPU *cpu)
 {
-    int ret = smp_threads;
-    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
+    int ret = MIN(smp_threads, kvmppc_smt_threads());
 
     switch (cpu->cpu_version) {
     case CPU_POWERPC_LOGICAL_2_05:
-        ret = 2;
+        ret = MIN(ret, 2);
         break;
     case CPU_POWERPC_LOGICAL_2_06:
-        ret = 4;
+        ret = MIN(ret, 4);
         break;
     case CPU_POWERPC_LOGICAL_2_07:
-        ret = 8;
-        break;
-    default:
-        if (pcc->pcr_mask & PCR_COMPAT_2_06) {
-            ret = 4;
-        } else if (pcc->pcr_mask & PCR_COMPAT_2_05) {
-            ret = 2;
-        }
+        ret = MIN(ret, 8);
         break;
     }
 
-    return MIN(ret, smp_threads);
+    return ret;
 }
 
 int ppc_set_compat(PowerPCCPU *cpu, uint32_t cpu_version)
diff --git a/tests/libqos/pci-pc.c b/tests/libqos/pci-pc.c
index bf741a4..4adf400 100644
--- a/tests/libqos/pci-pc.c
+++ b/tests/libqos/pci-pc.c
@@ -41,7 +41,7 @@
     if (port < 0x10000) {
         value = inb(port);
     } else {
-        memread(port, &value, sizeof(value));
+        value = readb(port);
     }
 
     return value;
@@ -55,7 +55,7 @@
     if (port < 0x10000) {
         value = inw(port);
     } else {
-        memread(port, &value, sizeof(value));
+        value = readw(port);
     }
 
     return value;
@@ -69,7 +69,7 @@
     if (port < 0x10000) {
         value = inl(port);
     } else {
-        memread(port, &value, sizeof(value));
+        value = readl(port);
     }
 
     return value;
@@ -82,7 +82,7 @@
     if (port < 0x10000) {
         outb(port, value);
     } else {
-        memwrite(port, &value, sizeof(value));
+        writeb(port, value);
     }
 }
 
@@ -93,7 +93,7 @@
     if (port < 0x10000) {
         outw(port, value);
     } else {
-        memwrite(port, &value, sizeof(value));
+        writew(port, value);
     }
 }
 
@@ -104,7 +104,7 @@
     if (port < 0x10000) {
         outl(port, value);
     } else {
-        memwrite(port, &value, sizeof(value));
+        writel(port, value);
     }
 }