Commit 34c99d7b authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-2.7-20160527' into staging



ppc patch queue for 2016-05-27 (first pull for qemu-2.7)

I'm back from holidays now, and have re-collated the ppc patch queue.
This is a first pull request against the qemu-2.7 branch, mostly
consisting of patches which were posted before the 2.6 freeze, but
weren't suitable for late inclusion in the 2.6 branch.

 * Assorted bugfixes and cleanups
 * Some preliminary patches towards dynamic DMA windows and CPU hotplug
 * Significant performance impovement for the spapr-llan device
 * Added myself to MAINTAINERS for ppc (overdue)

# gpg: Signature made Fri 27 May 2016 04:04:15 BST using RSA key ID 20D9B392
# gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>"
# gpg:                 aka "David Gibson (Red Hat) <dgibson@redhat.com>"
# gpg:                 aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>"
# gpg: WARNING: This key is not certified with sufficiently trusted signatures!
# gpg:          It is not certain that the signature belongs to the owner.
# Primary key fingerprint: 75F4 6586 AE61 A66C C44E  87DC 6C38 CACA 20D9 B392

* remotes/dgibson/tags/ppc-for-2.7-20160527:
  MAINTAINERS: Add David Gibson as ppc maintainer
  spapr_iommu: Move table allocation to helpers
  spapr_iommu: Finish renaming vfio_accel to need_vfio
  spapr_pci: Use correct DMA LIOBN when composing the device tree
  spapr: ensure device trees are always associated with DRC
  PPC/KVM: early validation of vcpu id
  Added negative check for get_image_size()
  hw/net/spapr_llan: Provide counter with dropped rx frames to the guest
  hw/net/spapr_llan: Delay flushing of the RX queue while adding new RX buffers
  target-ppc: Cleanups to rldinm, rldnm, rldimi
  target-ppc: Use 32-bit rotate instead of deposit + 64-bit rotate
  target-ppc: Use movcond in isel
  target-ppc: Correct KVM synchronization for ppc_hash64_set_external_hpt()

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 84cfc756 b4daafbd
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -165,6 +165,7 @@ F: hw/openrisc/
F: tests/tcg/openrisc/

PowerPC
M: David Gibson <david@gibson.dropbear.id.au>
M: Alexander Graf <agraf@suse.de>
L: qemu-ppc@nongnu.org
S: Maintained
+42 −3
Original line number Diff line number Diff line
@@ -110,6 +110,7 @@ typedef struct VIOsPAPRVLANDevice {
    hwaddr buf_list;
    uint32_t add_buf_ptr, use_buf_ptr, rx_bufs;
    hwaddr rxq_ptr;
    QEMUTimer *rxp_timer;
    uint32_t compat_flags;             /* Compatability flags for migration */
    RxBufPool *rx_pool[RX_MAX_POOLS];  /* Receive buffer descriptor pools */
} VIOsPAPRVLANDevice;
@@ -121,6 +122,21 @@ static int spapr_vlan_can_receive(NetClientState *nc)
    return (dev->isopen && dev->rx_bufs > 0);
}

/**
 * The last 8 bytes of the receive buffer list page (that has been
 * supplied by the guest with the H_REGISTER_LOGICAL_LAN call) contain
 * a counter for frames that have been dropped because there was no
 * suitable receive buffer available. This function is used to increase
 * this counter by one.
 */
static void spapr_vlan_record_dropped_rx_frame(VIOsPAPRVLANDevice *dev)
{
    uint64_t cnt;

    cnt = vio_ldq(&dev->sdev, dev->buf_list + 4096 - 8);
    vio_stq(&dev->sdev, dev->buf_list + 4096 - 8, cnt + 1);
}

/**
 * Get buffer descriptor from one of our receive buffer pools
 */
@@ -206,7 +222,8 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
    }

    if (!dev->rx_bufs) {
        return -1;
        spapr_vlan_record_dropped_rx_frame(dev);
        return 0;
    }

    if (dev->compat_flags & SPAPRVLAN_FLAG_RX_BUF_POOLS) {
@@ -215,7 +232,8 @@ static ssize_t spapr_vlan_receive(NetClientState *nc, const uint8_t *buf,
        bd = spapr_vlan_get_rx_bd_from_page(dev, size);
    }
    if (!bd) {
        return -1;
        spapr_vlan_record_dropped_rx_frame(dev);
        return 0;
    }

    dev->rx_bufs--;
@@ -266,6 +284,13 @@ static NetClientInfo net_spapr_vlan_info = {
    .receive = spapr_vlan_receive,
};

static void spapr_vlan_flush_rx_queue(void *opaque)
{
    VIOsPAPRVLANDevice *dev = opaque;

    qemu_flush_queued_packets(qemu_get_queue(dev->nic));
}

static void spapr_vlan_reset_rx_pool(RxBufPool *rxp)
{
    /*
@@ -302,6 +327,9 @@ static void spapr_vlan_realize(VIOsPAPRDevice *sdev, Error **errp)
    dev->nic = qemu_new_nic(&net_spapr_vlan_info, &dev->nicconf,
                            object_get_typename(OBJECT(sdev)), sdev->qdev.id, dev);
    qemu_format_nic_info_str(qemu_get_queue(dev->nic), dev->nicconf.macaddr.a);

    dev->rxp_timer = timer_new_us(QEMU_CLOCK_VIRTUAL, spapr_vlan_flush_rx_queue,
                                  dev);
}

static void spapr_vlan_instance_init(Object *obj)
@@ -332,6 +360,11 @@ static void spapr_vlan_instance_finalize(Object *obj)
            dev->rx_pool[i] = NULL;
        }
    }

    if (dev->rxp_timer) {
        timer_del(dev->rxp_timer);
        timer_free(dev->rxp_timer);
    }
}

void spapr_vlan_create(VIOsPAPRBus *bus, NICInfo *nd)
@@ -629,7 +662,13 @@ static target_ulong h_add_logical_lan_buffer(PowerPCCPU *cpu,

    dev->rx_bufs++;

    qemu_flush_queued_packets(qemu_get_queue(dev->nic));
    /*
     * Give guest some more time to add additional RX buffers before we
     * flush the receive queue, so that e.g. fragmented IP packets can
     * be passed to the guest in one go later (instead of passing single
     * fragments if there is only one receive buffer available).
     */
    timer_mod(dev->rxp_timer, qemu_clock_get_us(QEMU_CLOCK_VIRTUAL) + 500);

    return H_SUCCESS;
}
+10 −10
Original line number Diff line number Diff line
@@ -1842,6 +1842,10 @@ static void ppc_spapr_init(MachineState *machine)
        exit(1);
    }
    spapr->rtas_size = get_image_size(filename);
    if (spapr->rtas_size < 0) {
        error_report("Could not get size of LPAR rtas '%s'", filename);
        exit(1);
    }
    spapr->rtas_blob = g_malloc(spapr->rtas_size);
    if (load_image_size(filename, spapr->rtas_blob, spapr->rtas_size) < 0) {
        error_report("Could not load LPAR rtas '%s'", filename);
@@ -2132,15 +2136,6 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size,
    int i, fdt_offset, fdt_size;
    void *fdt;

    /*
     * Check for DRC connectors and send hotplug notification to the
     * guest only in case of hotplugged memory. This allows cold plugged
     * memory to be specified at boot time.
     */
    if (!dev->hotplugged) {
        return;
    }

    for (i = 0; i < nr_lmbs; i++) {
        drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
                addr/SPAPR_MEMORY_BLOCK_SIZE);
@@ -2154,8 +2149,13 @@ static void spapr_add_lmbs(DeviceState *dev, uint64_t addr, uint64_t size,
        drck->attach(drc, dev, fdt, fdt_offset, !dev->hotplugged, errp);
        addr += SPAPR_MEMORY_BLOCK_SIZE;
    }
    /* send hotplug notification to the
     * guest only in case of hotplugged memory
     */
    if (dev->hotplugged) {
       spapr_hotplug_req_add_by_count(SPAPR_DR_CONNECTOR_TYPE_LMB, nr_lmbs);
    }
}

static void spapr_memory_plug(HotplugHandler *hotplug_dev, DeviceState *dev,
                              uint32_t node, Error **errp)
+39 −19
Original line number Diff line number Diff line
@@ -76,6 +76,37 @@ static IOMMUAccessFlags spapr_tce_iommu_access_flags(uint64_t tce)
    }
}

static uint64_t *spapr_tce_alloc_table(uint32_t liobn,
                                       uint32_t page_shift,
                                       uint32_t nb_table,
                                       int *fd,
                                       bool need_vfio)
{
    uint64_t *table = NULL;
    uint64_t window_size = (uint64_t)nb_table << page_shift;

    if (kvm_enabled() && !(window_size >> 32)) {
        table = kvmppc_create_spapr_tce(liobn, window_size, fd, need_vfio);
    }

    if (!table) {
        *fd = -1;
        table = g_malloc0(nb_table * sizeof(uint64_t));
    }

    trace_spapr_iommu_new_table(liobn, table, *fd);

    return table;
}

static void spapr_tce_free_table(uint64_t *table, int fd, uint32_t nb_table)
{
    if (!kvm_enabled() ||
        (kvmppc_remove_spapr_tce(table, fd, nb_table) != 0)) {
        g_free(table);
    }
}

/* Called from RCU critical section */
static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
                                               bool is_write)
@@ -142,21 +173,13 @@ static MemoryRegionIOMMUOps spapr_iommu_ops = {
static int spapr_tce_table_realize(DeviceState *dev)
{
    sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
    uint64_t window_size = (uint64_t)tcet->nb_table << tcet->page_shift;

    if (kvm_enabled() && !(window_size >> 32)) {
        tcet->table = kvmppc_create_spapr_tce(tcet->liobn,
                                              window_size,
    tcet->fd = -1;
    tcet->table = spapr_tce_alloc_table(tcet->liobn,
                                        tcet->page_shift,
                                        tcet->nb_table,
                                        &tcet->fd,
                                        tcet->need_vfio);
    }

    if (!tcet->table) {
        size_t table_size = tcet->nb_table * sizeof(uint64_t);
        tcet->table = g_malloc0(table_size);
    }

    trace_spapr_iommu_new_table(tcet->liobn, tcet, tcet->table, tcet->fd);

    memory_region_init_iommu(&tcet->iommu, OBJECT(dev), &spapr_iommu_ops,
                             "iommu-spapr",
@@ -242,11 +265,8 @@ static void spapr_tce_table_unrealize(DeviceState *dev, Error **errp)

    QLIST_REMOVE(tcet, list);

    if (!kvm_enabled() ||
        (kvmppc_remove_spapr_tce(tcet->table, tcet->fd,
                                 tcet->nb_table) != 0)) {
        g_free(tcet->table);
    }
    spapr_tce_free_table(tcet->table, tcet->fd, tcet->nb_table);
    tcet->fd = -1;
}

MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet)
+6 −8
Original line number Diff line number Diff line
@@ -1093,14 +1093,12 @@ static void spapr_phb_add_pci_device(sPAPRDRConnector *drc,
        spapr_tce_set_need_vfio(tcet, true);
    }

    if (dev->hotplugged) {
    fdt = create_device_tree(&fdt_size);
    fdt_start_offset = spapr_create_pci_child_dt(phb, pdev, fdt, 0);
    if (!fdt_start_offset) {
        error_setg(errp, "Failed to create pci child device tree node");
        goto out;
    }
    }

    drck->attach(drc, DEVICE(pdev),
                 fdt, fdt_start_offset, !dev->hotplugged, errp);
@@ -1816,7 +1814,7 @@ int spapr_populate_pci_dt(sPAPRPHBState *phb,
    _FDT(fdt_setprop(fdt, bus_off, "interrupt-map", &interrupt_map,
                     sizeof(interrupt_map)));

    tcet = spapr_tce_find_by_liobn(SPAPR_PCI_LIOBN(phb->index, 0));
    tcet = spapr_tce_find_by_liobn(phb->dma_liobn);
    if (!tcet) {
        return -1;
    }
Loading