Commit 0601d6a4 authored by Peter Maydell's avatar Peter Maydell
Browse files

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



ppc patch queue for 2016-05-31

Latest patch queue for ppc.  Several significant things in here:
  * A bunch of patches from BenH fixing things in TCG
     - This should fix several regressions introduced by recent
       patches for better HV mode support
     - It also fixes some other bugs discovered along the way
  * Some fixes and cleanups for Mac machine types from Marc
    Cave-Ayland
  * Preliminary patches towards dynamic DMA window support from Alexey
    Kardashevskiy
      - This includes a patch to migration code code
  * Increase number of hotpluggable memory slots
      - Includes a change to KVM generic code, ACKed by Paolo
  * Another TCG fix for an SPE instruction

# gpg: Signature made Tue 07 Jun 2016 11:46:57 BST
# gpg:                using RSA key 0x6C38CACA20D9B392
# 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-20160607: (26 commits)
  ppc: Do not take exceptions on unknown SPRs in privileged mode
  ppc: Add missing slbfee. instruction on ppc64 BookS processors
  ppc: Fix slbia decode
  ppc: Fix mtmsr decoding
  ppc: POWER7 has lq/stq instructions and stq need to check ISA
  ppc: POWER7 had ACOP and PID registers
  ppc: Batch TLB flushes on 32-bit 6xx/7xx/7xxx in hash mode
  ppc: Fix tlb invalidations on 6xx/7xx/7xxx 32-bit processors
  ppc: Properly tag the translation cache based on MMU mode
  dbdma: use DMA memory interface for memory accesses
  macio: use DMA memory interface for non-block ATAPI transfers
  target-ppc: fixup bitrot in mmu_helper.c debug statements
  spapr_pci: Drop cannot_instantiate_with_device_add_yet=false
  ppc: fix hrfid, tlbia and slbia privilege
  ppc: Fix hreg_store_msr() so that non-HV mode cannot alter MSR:HV
  ppc: Better figure out if processor has HV mode
  spapr: Introduce pseries-2.7 machine type
  spapr: Increase hotpluggable memory slots to 256
  spapr_pci: Add and export DMA resetting helper
  spapr_pci: Reset DMA config on PHB reset
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 76462405 4d6a0680
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -271,7 +271,8 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
    if (s->lba == -1) {
        /* Non-block ATAPI transfer - just copy to RAM */
        s->io_buffer_size = MIN(s->io_buffer_size, io->len);
        cpu_physical_memory_write(io->addr, s->io_buffer, s->io_buffer_size);
        dma_memory_write(&address_space_memory, io->addr, s->io_buffer,
                         s->io_buffer_size);
        ide_atapi_cmd_ok(s);
        m->dma_active = false;
        goto done;
+7 −6
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@
#include "hw/ppc/mac_dbdma.h"
#include "qemu/main-loop.h"
#include "qemu/log.h"
#include "sysemu/dma.h"

/* debug DBDMA */
//#define DEBUG_DBDMA
@@ -81,7 +82,7 @@ static void dbdma_cmdptr_load(DBDMA_channel *ch)
{
    DBDMA_DPRINTF("dbdma_cmdptr_load 0x%08x\n",
                  ch->regs[DBDMA_CMDPTR_LO]);
    cpu_physical_memory_read(ch->regs[DBDMA_CMDPTR_LO],
    dma_memory_read(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO],
                    &ch->current, sizeof(dbdma_cmd));
}

@@ -92,7 +93,7 @@ static void dbdma_cmdptr_save(DBDMA_channel *ch)
    DBDMA_DPRINTF("xfer_status 0x%08x res_count 0x%04x\n",
                  le16_to_cpu(ch->current.xfer_status),
                  le16_to_cpu(ch->current.res_count));
    cpu_physical_memory_write(ch->regs[DBDMA_CMDPTR_LO],
    dma_memory_write(&address_space_memory, ch->regs[DBDMA_CMDPTR_LO],
                     &ch->current, sizeof(dbdma_cmd));
}

@@ -353,7 +354,7 @@ static void load_word(DBDMA_channel *ch, int key, uint32_t addr,
        return;
    }

    cpu_physical_memory_read(addr, &val, len);
    dma_memory_read(&address_space_memory, addr, &val, len);

    if (len == 2)
        val = (val << 16) | (current->cmd_dep & 0x0000ffff);
@@ -398,7 +399,7 @@ static void store_word(DBDMA_channel *ch, int key, uint32_t addr,
    else if (len == 1)
        val >>= 24;

    cpu_physical_memory_write(addr, &val, len);
    dma_memory_write(&address_space_memory, addr, &val, len);

    if (conditional_wait(ch))
        goto wait;
+32 −4
Original line number Diff line number Diff line
@@ -1816,11 +1816,21 @@ static void ppc_spapr_init(MachineState *machine)
    /* initialize hotplug memory address space */
    if (machine->ram_size < machine->maxram_size) {
        ram_addr_t hotplug_mem_size = machine->maxram_size - machine->ram_size;
        /*
         * Limit the number of hotpluggable memory slots to half the number
         * slots that KVM supports, leaving the other half for PCI and other
         * devices. However ensure that number of slots doesn't drop below 32.
         */
        int max_memslots = kvm_enabled() ? kvm_get_max_memslots() / 2 :
                           SPAPR_MAX_RAM_SLOTS;

        if (machine->ram_slots > SPAPR_MAX_RAM_SLOTS) {
        if (max_memslots < SPAPR_MAX_RAM_SLOTS) {
            max_memslots = SPAPR_MAX_RAM_SLOTS;
        }
        if (machine->ram_slots > max_memslots) {
            error_report("Specified number of memory slots %"
                         PRIu64" exceeds max supported %d",
                         machine->ram_slots, SPAPR_MAX_RAM_SLOTS);
                         machine->ram_slots, max_memslots);
            exit(1);
        }

@@ -2343,19 +2353,37 @@ static const TypeInfo spapr_machine_info = {
    }                                                                \
    type_init(spapr_machine_register_##suffix)

/*
 * pseries-2.7
 */
static void spapr_machine_2_7_instance_options(MachineState *machine)
{
}

static void spapr_machine_2_7_class_options(MachineClass *mc)
{
    /* Defaults for the latest behaviour inherited from the base class */
}

DEFINE_SPAPR_MACHINE(2_7, "2.7", true);

/*
 * pseries-2.6
 */
#define SPAPR_COMPAT_2_6 \
    HW_COMPAT_2_6

static void spapr_machine_2_6_instance_options(MachineState *machine)
{
}

static void spapr_machine_2_6_class_options(MachineClass *mc)
{
    /* Defaults for the latest behaviour inherited from the base class */
    spapr_machine_2_7_class_options(mc);
    SET_MACHINE_COMPAT(mc, SPAPR_COMPAT_2_6);
}

DEFINE_SPAPR_MACHINE(2_6, "2.6", true);
DEFINE_SPAPR_MACHINE(2_6, "2.6", false);

/*
 * pseries-2.5
+113 −27
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 */
#include "qemu/osdep.h"
#include "qemu/error-report.h"
#include "hw/hw.h"
#include "qemu/log.h"
#include "sysemu/kvm.h"
@@ -137,33 +138,92 @@ static IOMMUTLBEntry spapr_tce_translate_iommu(MemoryRegion *iommu, hwaddr addr,
    return ret;
}

static void spapr_tce_table_pre_save(void *opaque)
{
    sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque);

    tcet->mig_table = tcet->table;
    tcet->mig_nb_table = tcet->nb_table;

    trace_spapr_iommu_pre_save(tcet->liobn, tcet->mig_nb_table,
                               tcet->bus_offset, tcet->page_shift);
}

static int spapr_tce_table_post_load(void *opaque, int version_id)
{
    sPAPRTCETable *tcet = SPAPR_TCE_TABLE(opaque);
    uint32_t old_nb_table = tcet->nb_table;
    uint64_t old_bus_offset = tcet->bus_offset;
    uint32_t old_page_shift = tcet->page_shift;

    if (tcet->vdev) {
        spapr_vio_set_bypass(tcet->vdev, tcet->bypass);
    }

    if (tcet->mig_nb_table != tcet->nb_table) {
        spapr_tce_table_disable(tcet);
    }

    if (tcet->mig_nb_table) {
        if (!tcet->nb_table) {
            spapr_tce_table_enable(tcet, old_page_shift, old_bus_offset,
                                   tcet->mig_nb_table);
        }

        memcpy(tcet->table, tcet->mig_table,
               tcet->nb_table * sizeof(tcet->table[0]));

        free(tcet->mig_table);
        tcet->mig_table = NULL;
    }

    trace_spapr_iommu_post_load(tcet->liobn, old_nb_table, tcet->nb_table,
                                tcet->bus_offset, tcet->page_shift);

    return 0;
}

static bool spapr_tce_table_ex_needed(void *opaque)
{
    sPAPRTCETable *tcet = opaque;

    return tcet->bus_offset || tcet->page_shift != 0xC;
}

static const VMStateDescription vmstate_spapr_tce_table_ex = {
    .name = "spapr_iommu_ex",
    .version_id = 1,
    .minimum_version_id = 1,
    .needed = spapr_tce_table_ex_needed,
    .fields = (VMStateField[]) {
        VMSTATE_UINT64(bus_offset, sPAPRTCETable),
        VMSTATE_UINT32(page_shift, sPAPRTCETable),
        VMSTATE_END_OF_LIST()
    },
};

static const VMStateDescription vmstate_spapr_tce_table = {
    .name = "spapr_iommu",
    .version_id = 2,
    .minimum_version_id = 2,
    .pre_save = spapr_tce_table_pre_save,
    .post_load = spapr_tce_table_post_load,
    .fields      = (VMStateField []) {
        /* Sanity check */
        VMSTATE_UINT32_EQUAL(liobn, sPAPRTCETable),
        VMSTATE_UINT32_EQUAL(nb_table, sPAPRTCETable),

        /* IOMMU state */
        VMSTATE_UINT32(mig_nb_table, sPAPRTCETable),
        VMSTATE_BOOL(bypass, sPAPRTCETable),
        VMSTATE_VARRAY_UINT32(table, sPAPRTCETable, nb_table, 0, vmstate_info_uint64, uint64_t),
        VMSTATE_VARRAY_UINT32_ALLOC(mig_table, sPAPRTCETable, mig_nb_table, 0,
                                    vmstate_info_uint64, uint64_t),

        VMSTATE_END_OF_LIST()
    },
    .subsections = (const VMStateDescription*[]) {
        &vmstate_spapr_tce_table_ex,
        NULL
    }
};

static MemoryRegionIOMMUOps spapr_iommu_ops = {
@@ -173,17 +233,16 @@ static MemoryRegionIOMMUOps spapr_iommu_ops = {
static int spapr_tce_table_realize(DeviceState *dev)
{
    sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);
    Object *tcetobj = OBJECT(tcet);
    char tmp[32];

    tcet->fd = -1;
    tcet->table = spapr_tce_alloc_table(tcet->liobn,
                                        tcet->page_shift,
                                        tcet->nb_table,
                                        &tcet->fd,
                                        tcet->need_vfio);
    tcet->need_vfio = false;
    snprintf(tmp, sizeof(tmp), "tce-root-%x", tcet->liobn);
    memory_region_init(&tcet->root, tcetobj, tmp, UINT64_MAX);

    memory_region_init_iommu(&tcet->iommu, OBJECT(dev), &spapr_iommu_ops,
                             "iommu-spapr",
                             (uint64_t)tcet->nb_table << tcet->page_shift);
    snprintf(tmp, sizeof(tmp), "tce-iommu-%x", tcet->liobn);
    memory_region_init_iommu(&tcet->iommu, tcetobj, &spapr_iommu_ops, tmp, 0);

    QLIST_INSERT_HEAD(&spapr_tce_tables, tcet, list);

@@ -225,14 +284,10 @@ void spapr_tce_set_need_vfio(sPAPRTCETable *tcet, bool need_vfio)
    tcet->table = newtable;
}

sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
                                   uint64_t bus_offset,
                                   uint32_t page_shift,
                                   uint32_t nb_table,
                                   bool need_vfio)
sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn)
{
    sPAPRTCETable *tcet;
    char tmp[64];
    char tmp[32];

    if (spapr_tce_find_by_liobn(liobn)) {
        fprintf(stderr, "Attempted to create TCE table with duplicate"
@@ -240,16 +295,8 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
        return NULL;
    }

    if (!nb_table) {
        return NULL;
    }

    tcet = SPAPR_TCE_TABLE(object_new(TYPE_SPAPR_TCE_TABLE));
    tcet->liobn = liobn;
    tcet->bus_offset = bus_offset;
    tcet->page_shift = page_shift;
    tcet->nb_table = nb_table;
    tcet->need_vfio = need_vfio;

    snprintf(tmp, sizeof(tmp), "tce-table-%x", liobn);
    object_property_add_child(OBJECT(owner), tmp, OBJECT(tcet), NULL);
@@ -259,19 +306,58 @@ sPAPRTCETable *spapr_tce_new_table(DeviceState *owner, uint32_t liobn,
    return tcet;
}

void spapr_tce_table_enable(sPAPRTCETable *tcet,
                            uint32_t page_shift, uint64_t bus_offset,
                            uint32_t nb_table)
{
    if (tcet->nb_table) {
        error_report("Warning: trying to enable already enabled TCE table");
        return;
    }

    tcet->bus_offset = bus_offset;
    tcet->page_shift = page_shift;
    tcet->nb_table = nb_table;
    tcet->table = spapr_tce_alloc_table(tcet->liobn,
                                        tcet->page_shift,
                                        tcet->nb_table,
                                        &tcet->fd,
                                        tcet->need_vfio);

    memory_region_set_size(&tcet->iommu,
                           (uint64_t)tcet->nb_table << tcet->page_shift);
    memory_region_add_subregion(&tcet->root, tcet->bus_offset, &tcet->iommu);
}

void spapr_tce_table_disable(sPAPRTCETable *tcet)
{
    if (!tcet->nb_table) {
        return;
    }

    memory_region_del_subregion(&tcet->root, &tcet->iommu);
    memory_region_set_size(&tcet->iommu, 0);

    spapr_tce_free_table(tcet->table, tcet->fd, tcet->nb_table);
    tcet->fd = -1;
    tcet->table = NULL;
    tcet->bus_offset = 0;
    tcet->page_shift = 0;
    tcet->nb_table = 0;
}

static void spapr_tce_table_unrealize(DeviceState *dev, Error **errp)
{
    sPAPRTCETable *tcet = SPAPR_TCE_TABLE(dev);

    QLIST_REMOVE(tcet, list);

    spapr_tce_free_table(tcet->table, tcet->fd, tcet->nb_table);
    tcet->fd = -1;
    spapr_tce_table_disable(tcet);
}

MemoryRegion *spapr_tce_get_iommu(sPAPRTCETable *tcet)
{
    return &tcet->iommu;
    return &tcet->root;
}

static void spapr_tce_reset(DeviceState *dev)
+20 −8
Original line number Diff line number Diff line
@@ -1310,7 +1310,6 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
    PCIBus *bus;
    uint64_t msi_window_size = 4096;
    sPAPRTCETable *tcet;
    uint32_t nb_table;

    if (sphb->index != (uint32_t)-1) {
        hwaddr windows_base;
@@ -1462,18 +1461,15 @@ static void spapr_phb_realize(DeviceState *dev, Error **errp)
        }
    }

    nb_table = sphb->dma_win_size >> SPAPR_TCE_PAGE_SHIFT;
    tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn,
                               0, SPAPR_TCE_PAGE_SHIFT, nb_table, false);
    tcet = spapr_tce_new_table(DEVICE(sphb), sphb->dma_liobn);
    if (!tcet) {
        error_setg(errp, "Unable to create TCE table for %s",
                   sphb->dtbusname);
        return;
    }

    /* Register default 32bit DMA window */
    memory_region_add_subregion(&sphb->iommu_root, sphb->dma_win_addr,
                                spapr_tce_get_iommu(tcet));
    memory_region_add_subregion_overlap(&sphb->iommu_root, 0,
                                        spapr_tce_get_iommu(tcet), 0);

    sphb->msi = g_hash_table_new_full(g_int_hash, g_int_equal, g_free, g_free);
}
@@ -1489,8 +1485,25 @@ static int spapr_phb_children_reset(Object *child, void *opaque)
    return 0;
}

void spapr_phb_dma_reset(sPAPRPHBState *sphb)
{
    sPAPRTCETable *tcet = spapr_tce_find_by_liobn(sphb->dma_liobn);

    if (tcet && tcet->nb_table) {
        spapr_tce_table_disable(tcet);
    }

    /* Register default 32bit DMA window */
    spapr_tce_table_enable(tcet, SPAPR_TCE_PAGE_SHIFT, sphb->dma_win_addr,
                           sphb->dma_win_size >> SPAPR_TCE_PAGE_SHIFT);
}

static void spapr_phb_reset(DeviceState *qdev)
{
    sPAPRPHBState *sphb = SPAPR_PCI_HOST_BRIDGE(qdev);

    spapr_phb_dma_reset(sphb);

    /* Reset the IOMMU state */
    object_child_foreach(OBJECT(qdev), spapr_phb_children_reset, NULL);

@@ -1624,7 +1637,6 @@ static void spapr_phb_class_init(ObjectClass *klass, void *data)
    dc->reset = spapr_phb_reset;
    dc->vmsd = &vmstate_spapr_pci;
    set_bit(DEVICE_CATEGORY_BRIDGE, dc->categories);
    dc->cannot_instantiate_with_device_add_yet = false;
    hp->plug = spapr_phb_hot_plug_child;
    hp->unplug = spapr_phb_hot_unplug_child;
}
Loading