Commit a28aae04 authored by Peter Maydell's avatar Peter Maydell
Browse files

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



ppc patch queue for 2016-06-14

Latest patch queue for ppc.
    * Allow qemu to support a generic architecture 2.07 (POWER8-era)
      compatibility mode.  This is useful for guests which are POWER8
      aware, but don't know about the specific POWER8 variant that
      qemu (and/or KVM) is emulating. (Thomas Huth)
    * Fix a bug where macio wasn't removing DMA mappings (Mark Cave-Ayland)
    * Add a workaround for Linux guest's miscalculation of maximum
      memory address (including hotplugged memory), which could break
      when hotplug memory was combined with VFIO.  The previous
      approach was technically correct by spec, but differed from
      PowerVM's behaviour enough to trip a guest kernel bug.  This
      works around the bug, while remaining correct-to-spec. (Bharata Rao)

# gpg: Signature made Tue 14 Jun 2016 06:53:58 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-20160614:
  spapr: Ensure all LMBs are represented in ibm,dynamic-memory
  macio: call dma_memory_unmap() at the end of each DMA transfer
  Add PowerPC AT_HWCAP2 definitions
  ppc: Add PowerISA 2.07 compatibility mode
  ppc: Improve PCR bit selection in ppc_set_compat()
  ppc: Provide function to get CPU class of the host CPU
  ppc: Split pcr_mask settings into supported bits and the register mask
  ppc/spapr: Refactor h_client_architecture_support() CPU parsing code

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents 2c96c379 d0e5a8f2
Loading
Loading
Loading
Loading
+26 −20
Original line number Diff line number Diff line
@@ -66,8 +66,7 @@ static void pmac_dma_read(BlockBackend *blk,
    DBDMA_io *io = opaque;
    MACIOIDEState *m = io->opaque;
    IDEState *s = idebus_active_if(&m->bus);
    dma_addr_t dma_addr, dma_len;
    void *mem;
    dma_addr_t dma_addr;
    int64_t sector_num;
    int nsector;
    uint64_t align = BDRV_SECTOR_SIZE;
@@ -84,9 +83,10 @@ static void pmac_dma_read(BlockBackend *blk,
                  sector_num, nsector);

    dma_addr = io->addr;
    dma_len = io->len;
    mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len,
                         DMA_DIRECTION_FROM_DEVICE);
    io->dir = DMA_DIRECTION_FROM_DEVICE;
    io->dma_len = io->len;
    io->dma_mem = dma_memory_map(&address_space_memory, dma_addr, &io->dma_len,
                                 io->dir);

    if (offset & (align - 1)) {
        head_bytes = offset & (align - 1);
@@ -100,7 +100,7 @@ static void pmac_dma_read(BlockBackend *blk,
        offset = offset & ~(align - 1);
    }

    qemu_iovec_add(&io->iov, mem, io->len);
    qemu_iovec_add(&io->iov, io->dma_mem, io->len);

    if ((offset + bytes) & (align - 1)) {
        tail_bytes = (offset + bytes) & (align - 1);
@@ -130,8 +130,7 @@ static void pmac_dma_write(BlockBackend *blk,
    DBDMA_io *io = opaque;
    MACIOIDEState *m = io->opaque;
    IDEState *s = idebus_active_if(&m->bus);
    dma_addr_t dma_addr, dma_len;
    void *mem;
    dma_addr_t dma_addr;
    int64_t sector_num;
    int nsector;
    uint64_t align = BDRV_SECTOR_SIZE;
@@ -149,9 +148,10 @@ static void pmac_dma_write(BlockBackend *blk,
                  sector_num, nsector);

    dma_addr = io->addr;
    dma_len = io->len;
    mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len,
                         DMA_DIRECTION_TO_DEVICE);
    io->dir = DMA_DIRECTION_TO_DEVICE;
    io->dma_len = io->len;
    io->dma_mem = dma_memory_map(&address_space_memory, dma_addr, &io->dma_len,
                                 io->dir);

    if (offset & (align - 1)) {
        head_bytes = offset & (align - 1);
@@ -163,7 +163,7 @@ static void pmac_dma_write(BlockBackend *blk,
        blk_pread(s->blk, (sector_num << 9), &io->head_remainder, align);

        qemu_iovec_add(&io->iov, &io->head_remainder, head_bytes);
        qemu_iovec_add(&io->iov, mem, io->len);
        qemu_iovec_add(&io->iov, io->dma_mem, io->len);

        bytes += offset & (align - 1);
        offset = offset & ~(align - 1);
@@ -181,7 +181,7 @@ static void pmac_dma_write(BlockBackend *blk,
        blk_pread(s->blk, (sector_num << 9), &io->tail_remainder, align);

        if (!unaligned_head) {
            qemu_iovec_add(&io->iov, mem, io->len);
            qemu_iovec_add(&io->iov, io->dma_mem, io->len);
        }

        qemu_iovec_add(&io->iov, &io->tail_remainder + tail_bytes,
@@ -193,7 +193,7 @@ static void pmac_dma_write(BlockBackend *blk,
    }

    if (!unaligned_head && !unaligned_tail) {
        qemu_iovec_add(&io->iov, mem, io->len);
        qemu_iovec_add(&io->iov, io->dma_mem, io->len);
    }

    s->io_buffer_size -= io->len;
@@ -214,18 +214,18 @@ static void pmac_dma_trim(BlockBackend *blk,
    DBDMA_io *io = opaque;
    MACIOIDEState *m = io->opaque;
    IDEState *s = idebus_active_if(&m->bus);
    dma_addr_t dma_addr, dma_len;
    void *mem;
    dma_addr_t dma_addr;

    qemu_iovec_destroy(&io->iov);
    qemu_iovec_init(&io->iov, io->len / MACIO_PAGE_SIZE + 1);

    dma_addr = io->addr;
    dma_len = io->len;
    mem = dma_memory_map(&address_space_memory, dma_addr, &dma_len,
                         DMA_DIRECTION_TO_DEVICE);
    io->dir = DMA_DIRECTION_TO_DEVICE;
    io->dma_len = io->len;
    io->dma_mem = dma_memory_map(&address_space_memory, dma_addr, &io->dma_len,
                                 io->dir);

    qemu_iovec_add(&io->iov, mem, io->len);
    qemu_iovec_add(&io->iov, io->dma_mem, io->len);
    s->io_buffer_size -= io->len;
    s->io_buffer_index += io->len;
    io->len = 0;
@@ -285,6 +285,9 @@ static void pmac_ide_atapi_transfer_cb(void *opaque, int ret)
    return;

done:
    dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len,
                     io->dir, io->dma_len);

    if (ret < 0) {
        block_acct_failed(blk_get_stats(s->blk), &s->acct);
    } else {
@@ -351,6 +354,9 @@ static void pmac_ide_transfer_cb(void *opaque, int ret)
    return;

done:
    dma_memory_unmap(&address_space_memory, io->dma_mem, io->dma_len,
                     io->dir, io->dma_len);

    if (s->dma_cmd == IDE_DMA_READ || s->dma_cmd == IDE_DMA_WRITE) {
        if (ret < 0) {
            block_acct_failed(blk_get_stats(s->blk), &s->acct);
+37 −20
Original line number Diff line number Diff line
@@ -762,14 +762,17 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
    int ret, i, offset;
    uint64_t lmb_size = SPAPR_MEMORY_BLOCK_SIZE;
    uint32_t prop_lmb_size[] = {0, cpu_to_be32(lmb_size)};
    uint32_t nr_lmbs = (machine->maxram_size - machine->ram_size)/lmb_size;
    uint32_t hotplug_lmb_start = spapr->hotplug_memory.base / lmb_size;
    uint32_t nr_lmbs = (spapr->hotplug_memory.base +
                       memory_region_size(&spapr->hotplug_memory.mr)) /
                       lmb_size;
    uint32_t *int_buf, *cur_index, buf_len;
    int nr_nodes = nb_numa_nodes ? nb_numa_nodes : 1;

    /*
     * Don't create the node if there are no DR LMBs.
     * Don't create the node if there is no hotpluggable memory
     */
    if (!nr_lmbs) {
    if (machine->ram_size == machine->maxram_size) {
        return 0;
    }

@@ -803,13 +806,14 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
    int_buf[0] = cpu_to_be32(nr_lmbs);
    cur_index++;
    for (i = 0; i < nr_lmbs; i++) {
        uint64_t addr = i * lmb_size;
        uint32_t *dynamic_memory = cur_index;

        if (i >= hotplug_lmb_start) {
            sPAPRDRConnector *drc;
            sPAPRDRConnectorClass *drck;
        uint64_t addr = i * lmb_size + spapr->hotplug_memory.base;;
        uint32_t *dynamic_memory = cur_index;

        drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB,
                                       addr/lmb_size);
            drc = spapr_dr_connector_by_id(SPAPR_DR_CONNECTOR_TYPE_LMB, i);
            g_assert(drc);
            drck = SPAPR_DR_CONNECTOR_GET_CLASS(drc);

@@ -818,12 +822,25 @@ static int spapr_populate_drconf_memory(sPAPRMachineState *spapr, void *fdt)
            dynamic_memory[2] = cpu_to_be32(drck->get_index(drc));
            dynamic_memory[3] = cpu_to_be32(0); /* reserved */
            dynamic_memory[4] = cpu_to_be32(numa_get_node(addr, NULL));
        if (addr < machine->ram_size ||
                    memory_region_present(get_system_memory(), addr)) {
            if (memory_region_present(get_system_memory(), addr)) {
                dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_ASSIGNED);
            } else {
                dynamic_memory[5] = cpu_to_be32(0);
            }
        } else {
            /*
             * LMB information for RMA, boot time RAM and gap b/n RAM and
             * hotplug memory region -- all these are marked as reserved
             * and as having no valid DRC.
             */
            dynamic_memory[0] = cpu_to_be32(addr >> 32);
            dynamic_memory[1] = cpu_to_be32(addr & 0xffffffff);
            dynamic_memory[2] = cpu_to_be32(0);
            dynamic_memory[3] = cpu_to_be32(0); /* reserved */
            dynamic_memory[4] = cpu_to_be32(-1);
            dynamic_memory[5] = cpu_to_be32(SPAPR_LMB_FLAGS_RESERVED |
                                            SPAPR_LMB_FLAGS_DRC_INVALID);
        }

        cur_index += SPAPR_DR_LMB_LIST_ENTRY_SIZE;
    }
+38 −25
Original line number Diff line number Diff line
@@ -922,6 +922,41 @@ static void do_set_compat(void *arg)
    ((cpuver) == CPU_POWERPC_LOGICAL_2_06_PLUS) ? 2061 : \
    ((cpuver) == CPU_POWERPC_LOGICAL_2_07) ? 2070 : 0)

static void cas_handle_compat_cpu(PowerPCCPUClass *pcc, uint32_t pvr,
                                  unsigned max_lvl, unsigned *compat_lvl,
                                  unsigned *cpu_version)
{
    unsigned lvl = get_compat_level(pvr);
    bool is205, is206, is207;

    if (!lvl) {
        return;
    }

    /* If it is a logical PVR, try to determine the highest level */
    is205 = (pcc->pcr_supported & PCR_COMPAT_2_05) &&
            (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05));
    is206 = (pcc->pcr_supported & PCR_COMPAT_2_06) &&
            ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) ||
             (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS)));
    is207 = (pcc->pcr_supported & PCR_COMPAT_2_07) &&
            (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_07));

    if (is205 || is206 || is207) {
        if (!max_lvl) {
            /* User did not set the level, choose the highest */
            if (*compat_lvl <= lvl) {
                *compat_lvl = lvl;
                *cpu_version = pvr;
            }
        } else if (max_lvl >= lvl) {
            /* User chose the level, don't set higher than this */
            *compat_lvl = lvl;
            *cpu_version = pvr;
        }
    }
}

#define OV5_DRCONF_MEMORY 0x20

static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
@@ -931,7 +966,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
{
    target_ulong list = ppc64_phys_to_real(args[0]);
    target_ulong ov_table, ov5;
    PowerPCCPUClass *pcc_ = POWERPC_CPU_GET_CLASS(cpu_);
    PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu_);
    CPUState *cs;
    bool cpu_match = false, cpu_update = true, memory_update = false;
    unsigned old_cpu_version = cpu_->cpu_version;
@@ -958,29 +993,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,
            cpu_match = true;
            cpu_version = cpu_->cpu_version;
        } else if (!cpu_match) {
            /* If it is a logical PVR, try to determine the highest level */
            unsigned lvl = get_compat_level(pvr);
            if (lvl) {
                bool is205 = (pcc_->pcr_mask & PCR_COMPAT_2_05) &&
                     (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_05));
                bool is206 = (pcc_->pcr_mask & PCR_COMPAT_2_06) &&
                    ((lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06)) ||
                    (lvl == get_compat_level(CPU_POWERPC_LOGICAL_2_06_PLUS)));

                if (is205 || is206) {
                    if (!max_lvl) {
                        /* User did not set the level, choose the highest */
                        if (compat_lvl <= lvl) {
                            compat_lvl = lvl;
                            cpu_version = pvr;
                        }
                    } else if (max_lvl >= lvl) {
                        /* User chose the level, don't set higher than this */
                        compat_lvl = lvl;
                        cpu_version = pvr;
                    }
                }
            }
            cas_handle_compat_cpu(pcc, pvr, max_lvl, &compat_lvl, &cpu_version);
        }
        /* Terminator record */
        if (~pvr_mask & pvr) {
@@ -990,7 +1003,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu_,

    /* Parsing finished */
    trace_spapr_cas_pvr(cpu_->cpu_version, cpu_match,
                        cpu_version, pcc_->pcr_mask);
                        cpu_version, pcc->pcr_mask);

    /* Update CPUs */
    if (old_cpu_version != cpu_version) {
+13 −0
Original line number Diff line number Diff line
@@ -477,6 +477,19 @@ typedef struct {
#define PPC_FEATURE_TRUE_LE             0x00000002
#define PPC_FEATURE_PPC_LE              0x00000001

/* Bits present in AT_HWCAP2 for PowerPC.  */

#define PPC_FEATURE2_ARCH_2_07          0x80000000
#define PPC_FEATURE2_HAS_HTM            0x40000000
#define PPC_FEATURE2_HAS_DSCR           0x20000000
#define PPC_FEATURE2_HAS_EBB            0x10000000
#define PPC_FEATURE2_HAS_ISEL           0x08000000
#define PPC_FEATURE2_HAS_TAR            0x04000000
#define PPC_FEATURE2_HAS_VEC_CRYPTO     0x02000000
#define PPC_FEATURE2_HTM_NOSC           0x01000000
#define PPC_FEATURE2_ARCH_3_00          0x00800000
#define PPC_FEATURE2_HAS_IEEE128        0x00400000

/* Bits present in AT_HWCAP for Sparc.  */

#define HWCAP_SPARC_FLUSH               0x00000001
+5 −0
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@

#include "exec/memory.h"
#include "qemu/iov.h"
#include "sysemu/dma.h"

typedef struct DBDMA_io DBDMA_io;

@@ -44,6 +45,10 @@ struct DBDMA_io {
    uint8_t head_remainder[0x200];
    uint8_t tail_remainder[0x200];
    QEMUIOVector iov;
    /* DMA request */
    void *dma_mem;
    dma_addr_t dma_len;
    DMADirection dir;
};

/*
Loading