Commit 2d80e0ab authored by Peter Maydell's avatar Peter Maydell
Browse files

Merge remote-tracking branch 'remotes/agraf/tags/signed-ppc-for-upstream' into staging



Patch queue for ppc - 2014-06-27

Changes include:

  - instruction emulation fixes
  - linux-user fixes
  - mac99: layout fixes
  - pseries: Initial VFIO support
  - pseries: support for UUID
  - pseries: support for -boot m

# gpg: Signature made Fri 27 Jun 2014 12:51:01 BST using RSA key ID 03FEDC60
# gpg: Can't check signature: public key not found

* remotes/agraf/tags/signed-ppc-for-upstream: (32 commits)
  PPC: e500: Only create dt entries for existing serial ports
  spapr_pci: Use XICS interrupt allocator and do not cache interrupts in PHB
  vmstate: Add preallocation for migrating arrays (VMS_ALLOC flag)
  xics: Implement xics_ics_free()
  spapr: Remove @next_irq
  spapr: Move interrupt allocator to xics
  xics: Disable flags reset on xics reset
  xics: Add xics_find_source()
  xics: Add flags for interrupts
  spapr: Add RTAS sysparm SPLPAR Characteristics
  spapr: Add RTAS sysparm UUID
  spapr: Fix RTAS sysparm DIAGNOSTICS_RUN_MODE
  spapr: Add rtas_st_buffer utility function
  spapr: Define a 2.1 pseries machine
  spapr: Fix code design style (s/SPAPRMachine/sPAPRMachineState)
  target-ppc: Add support for POWER8 pvr 0x4D0000
  uninorth: Fix PCI hole size
  mac99: Add motherboard devices before PCI cards
  target-ppc: Remove unused gen_qemu_ld8s()
  target-ppc: Remove unused IMM and d extract helpers
  ...

Signed-off-by: default avatarPeter Maydell <peter.maydell@linaro.org>
parents de6793e8 79c0ff2c
Loading
Loading
Loading
Loading
+167 −15
Original line number Diff line number Diff line
@@ -437,7 +437,7 @@ static void ics_set_irq(void *opaque, int srcno, int val)
{
    ICSState *ics = (ICSState *)opaque;

    if (ics->islsi[srcno]) {
    if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
        set_irq_lsi(ics, srcno, val);
    } else {
        set_irq_msi(ics, srcno, val);
@@ -474,7 +474,7 @@ static void ics_write_xive(ICSState *ics, int nr, int server,

    trace_xics_ics_write_xive(nr, srcno, server, priority);

    if (ics->islsi[srcno]) {
    if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
        write_xive_lsi(ics, srcno);
    } else {
        write_xive_msi(ics, srcno);
@@ -496,7 +496,7 @@ static void ics_resend(ICSState *ics)

    for (i = 0; i < ics->nr_irqs; i++) {
        /* FIXME: filter by server#? */
        if (ics->islsi[i]) {
        if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
            resend_lsi(ics, i);
        } else {
            resend_msi(ics, i);
@@ -511,7 +511,7 @@ static void ics_eoi(ICSState *ics, int nr)

    trace_xics_ics_eoi(nr);

    if (ics->islsi[srcno]) {
    if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_LSI) {
        irq->status &= ~XICS_STATUS_SENT;
    }
}
@@ -520,11 +520,18 @@ static void ics_reset(DeviceState *dev)
{
    ICSState *ics = ICS(dev);
    int i;
    uint8_t flags[ics->nr_irqs];

    for (i = 0; i < ics->nr_irqs; i++) {
        flags[i] = ics->irqs[i].flags;
    }

    memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs);

    for (i = 0; i < ics->nr_irqs; i++) {
        ics->irqs[i].priority = 0xff;
        ics->irqs[i].saved_priority = 0xff;
        ics->irqs[i].flags = flags[i];
    }
}

@@ -563,13 +570,14 @@ static int ics_dispatch_post_load(void *opaque, int version_id)

static const VMStateDescription vmstate_ics_irq = {
    .name = "ics/irq",
    .version_id = 1,
    .version_id = 2,
    .minimum_version_id = 1,
    .fields = (VMStateField[]) {
        VMSTATE_UINT32(server, ICSIRQState),
        VMSTATE_UINT8(priority, ICSIRQState),
        VMSTATE_UINT8(saved_priority, ICSIRQState),
        VMSTATE_UINT8(status, ICSIRQState),
        VMSTATE_UINT8(flags, ICSIRQState),
        VMSTATE_END_OF_LIST()
    },
};
@@ -606,7 +614,6 @@ static void ics_realize(DeviceState *dev, Error **errp)
        return;
    }
    ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
    ics->islsi = g_malloc0(ics->nr_irqs * sizeof(bool));
    ics->qirqs = qemu_allocate_irqs(ics_set_irq, ics, ics->nr_irqs);
}

@@ -633,21 +640,166 @@ static const TypeInfo ics_info = {
/*
 * Exported functions
 */
static int xics_find_source(XICSState *icp, int irq)
{
    int sources = 1;
    int src;

    /* FIXME: implement multiple sources */
    for (src = 0; src < sources; ++src) {
        ICSState *ics = &icp->ics[src];
        if (ics_valid_irq(ics, irq)) {
            return src;
        }
    }

    return -1;
}

qemu_irq xics_get_qirq(XICSState *icp, int irq)
{
    if (!ics_valid_irq(icp->ics, irq)) {
    int src = xics_find_source(icp, irq);

    if (src >= 0) {
        ICSState *ics = &icp->ics[src];
        return ics->qirqs[irq - ics->offset];
    }

    return NULL;
}

    return icp->ics->qirqs[irq - icp->ics->offset];
static void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
{
    assert(!(ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MASK));

    ics->irqs[srcno].flags |=
        lsi ? XICS_FLAGS_IRQ_LSI : XICS_FLAGS_IRQ_MSI;
}

void xics_set_irq_type(XICSState *icp, int irq, bool lsi)
{
    assert(ics_valid_irq(icp->ics, irq));
    int src = xics_find_source(icp, irq);
    ICSState *ics;

    icp->ics->islsi[irq - icp->ics->offset] = lsi;
    assert(src >= 0);

    ics = &icp->ics[src];
    ics_set_irq_type(ics, irq - ics->offset, lsi);
}

#define ICS_IRQ_FREE(ics, srcno)   \
    (!((ics)->irqs[(srcno)].flags & (XICS_FLAGS_IRQ_MASK)))

static int ics_find_free_block(ICSState *ics, int num, int alignnum)
{
    int first, i;

    for (first = 0; first < ics->nr_irqs; first += alignnum) {
        if (num > (ics->nr_irqs - first)) {
            return -1;
        }
        for (i = first; i < first + num; ++i) {
            if (!ICS_IRQ_FREE(ics, i)) {
                break;
            }
        }
        if (i == (first + num)) {
            return first;
        }
    }

    return -1;
}

int xics_alloc(XICSState *icp, int src, int irq_hint, bool lsi)
{
    ICSState *ics = &icp->ics[src];
    int irq;

    if (irq_hint) {
        assert(src == xics_find_source(icp, irq_hint));
        if (!ICS_IRQ_FREE(ics, irq_hint - ics->offset)) {
            trace_xics_alloc_failed_hint(src, irq_hint);
            return -1;
        }
        irq = irq_hint;
    } else {
        irq = ics_find_free_block(ics, 1, 1);
        if (irq < 0) {
            trace_xics_alloc_failed_no_left(src);
            return -1;
        }
        irq += ics->offset;
    }

    ics_set_irq_type(ics, irq - ics->offset, lsi);
    trace_xics_alloc(src, irq);

    return irq;
}

/*
 * Allocate block of consequtive IRQs, returns a number of the first.
 * If align==true, aligns the first IRQ number to num.
 */
int xics_alloc_block(XICSState *icp, int src, int num, bool lsi, bool align)
{
    int i, first = -1;
    ICSState *ics = &icp->ics[src];

    assert(src == 0);
    /*
     * MSIMesage::data is used for storing VIRQ so
     * it has to be aligned to num to support multiple
     * MSI vectors. MSI-X is not affected by this.
     * The hint is used for the first IRQ, the rest should
     * be allocated continuously.
     */
    if (align) {
        assert((num == 1) || (num == 2) || (num == 4) ||
               (num == 8) || (num == 16) || (num == 32));
        first = ics_find_free_block(ics, num, num);
    } else {
        first = ics_find_free_block(ics, num, 1);
    }

    if (first >= 0) {
        for (i = first; i < first + num; ++i) {
            ics_set_irq_type(ics, i, lsi);
        }
    }
    first += ics->offset;

    trace_xics_alloc_block(src, first, num, lsi, align);

    return first;
}

static void ics_free(ICSState *ics, int srcno, int num)
{
    int i;

    for (i = srcno; i < srcno + num; ++i) {
        if (ICS_IRQ_FREE(ics, i)) {
            trace_xics_ics_free_warn(ics - ics->icp->ics, i + ics->offset);
        }
        memset(&ics->irqs[i], 0, sizeof(ICSIRQState));
    }
}

void xics_free(XICSState *icp, int irq, int num)
{
    int src = xics_find_source(icp, irq);

    if (src >= 0) {
        ICSState *ics = &icp->ics[src];

        /* FIXME: implement multiple sources */
        assert(src == 0);

        trace_xics_ics_free(ics - icp->ics, irq, num);
        ics_free(ics, irq - ics->offset, num);
    }
}

/*
@@ -866,10 +1018,10 @@ static void xics_realize(DeviceState *dev, Error **errp)
    }

    /* Registration of global state belongs into realize */
    spapr_rtas_register("ibm,set-xive", rtas_set_xive);
    spapr_rtas_register("ibm,get-xive", rtas_get_xive);
    spapr_rtas_register("ibm,int-off", rtas_int_off);
    spapr_rtas_register("ibm,int-on", rtas_int_on);
    spapr_rtas_register(RTAS_IBM_SET_XIVE, "ibm,set-xive", rtas_set_xive);
    spapr_rtas_register(RTAS_IBM_GET_XIVE, "ibm,get-xive", rtas_get_xive);
    spapr_rtas_register(RTAS_IBM_INT_OFF, "ibm,int-off", rtas_int_off);
    spapr_rtas_register(RTAS_IBM_INT_ON, "ibm,int-on", rtas_int_on);

    spapr_register_hypercall(H_CPPR, h_cppr);
    spapr_register_hypercall(H_IPI, h_ipi);
+17 −17
Original line number Diff line number Diff line
@@ -38,10 +38,6 @@
typedef struct KVMXICSState {
    XICSState parent_obj;

    uint32_t set_xive_token;
    uint32_t get_xive_token;
    uint32_t int_off_token;
    uint32_t int_on_token;
    int kernel_xics_fd;
} KVMXICSState;

@@ -224,7 +220,7 @@ static int ics_set_kvm_state(ICSState *ics, int version_id)
            state |= KVM_XICS_MASKED;
        }

        if (ics->islsi[i]) {
        if (ics->irqs[i].flags & XICS_FLAGS_IRQ_LSI) {
            state |= KVM_XICS_LEVEL_SENSITIVE;
            if (irq->status & XICS_STATUS_ASSERTED) {
                state |= KVM_XICS_PENDING;
@@ -253,7 +249,7 @@ static void ics_kvm_set_irq(void *opaque, int srcno, int val)
    int rc;

    args.irq = srcno + ics->offset;
    if (!ics->islsi[srcno]) {
    if (ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MSI) {
        if (!val) {
            return;
        }
@@ -271,11 +267,18 @@ static void ics_kvm_reset(DeviceState *dev)
{
    ICSState *ics = ICS(dev);
    int i;
    uint8_t flags[ics->nr_irqs];

    for (i = 0; i < ics->nr_irqs; i++) {
        flags[i] = ics->irqs[i].flags;
    }

    memset(ics->irqs, 0, sizeof(ICSIRQState) * ics->nr_irqs);

    for (i = 0; i < ics->nr_irqs; i++) {
        ics->irqs[i].priority = 0xff;
        ics->irqs[i].saved_priority = 0xff;
        ics->irqs[i].flags = flags[i];
    }

    ics_set_kvm_state(ics, 1);
@@ -290,7 +293,6 @@ static void ics_kvm_realize(DeviceState *dev, Error **errp)
        return;
    }
    ics->irqs = g_malloc0(ics->nr_irqs * sizeof(ICSIRQState));
    ics->islsi = g_malloc0(ics->nr_irqs * sizeof(bool));
    ics->qirqs = qemu_allocate_irqs(ics_kvm_set_irq, ics, ics->nr_irqs);
}

@@ -392,32 +394,30 @@ static void xics_kvm_realize(DeviceState *dev, Error **errp)
        goto fail;
    }

    icpkvm->set_xive_token = spapr_rtas_register("ibm,set-xive", rtas_dummy);
    icpkvm->get_xive_token = spapr_rtas_register("ibm,get-xive", rtas_dummy);
    icpkvm->int_off_token = spapr_rtas_register("ibm,int-off", rtas_dummy);
    icpkvm->int_on_token = spapr_rtas_register("ibm,int-on", rtas_dummy);
    spapr_rtas_register(RTAS_IBM_SET_XIVE, "ibm,set-xive", rtas_dummy);
    spapr_rtas_register(RTAS_IBM_GET_XIVE, "ibm,get-xive", rtas_dummy);
    spapr_rtas_register(RTAS_IBM_INT_OFF, "ibm,int-off", rtas_dummy);
    spapr_rtas_register(RTAS_IBM_INT_ON, "ibm,int-on", rtas_dummy);

    rc = kvmppc_define_rtas_kernel_token(icpkvm->set_xive_token,
                                         "ibm,set-xive");
    rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_SET_XIVE, "ibm,set-xive");
    if (rc < 0) {
        error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,set-xive");
        goto fail;
    }

    rc = kvmppc_define_rtas_kernel_token(icpkvm->get_xive_token,
                                         "ibm,get-xive");
    rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_GET_XIVE, "ibm,get-xive");
    if (rc < 0) {
        error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,get-xive");
        goto fail;
    }

    rc = kvmppc_define_rtas_kernel_token(icpkvm->int_on_token, "ibm,int-on");
    rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_INT_ON, "ibm,int-on");
    if (rc < 0) {
        error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,int-on");
        goto fail;
    }

    rc = kvmppc_define_rtas_kernel_token(icpkvm->int_off_token, "ibm,int-off");
    rc = kvmppc_define_rtas_kernel_token(RTAS_IBM_INT_OFF, "ibm,int-off");
    if (rc < 0) {
        error_setg(errp, "kvmppc_define_rtas_kernel_token: ibm,int-off");
        goto fail;
+78 −0
Original line number Diff line number Diff line
@@ -39,6 +39,7 @@
#include "qemu/range.h"
#include "sysemu/kvm.h"
#include "sysemu/sysemu.h"
#include "hw/misc/vfio.h"

/* #define DEBUG_VFIO */
#ifdef DEBUG_VFIO
@@ -3649,6 +3650,39 @@ static int vfio_connect_container(VFIOGroup *group, AddressSpace *as)

        container->iommu_data.type1.initialized = true;

    } else if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_SPAPR_TCE_IOMMU)) {
        ret = ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &fd);
        if (ret) {
            error_report("vfio: failed to set group container: %m");
            ret = -errno;
            goto free_container_exit;
        }

        ret = ioctl(fd, VFIO_SET_IOMMU, VFIO_SPAPR_TCE_IOMMU);
        if (ret) {
            error_report("vfio: failed to set iommu for container: %m");
            ret = -errno;
            goto free_container_exit;
        }

        /*
         * The host kernel code implementing VFIO_IOMMU_DISABLE is called
         * when container fd is closed so we do not call it explicitly
         * in this file.
         */
        ret = ioctl(fd, VFIO_IOMMU_ENABLE);
        if (ret) {
            error_report("vfio: failed to enable container: %m");
            ret = -errno;
            goto free_container_exit;
        }

        container->iommu_data.type1.listener = vfio_memory_listener;
        container->iommu_data.release = vfio_listener_release;

        memory_listener_register(&container->iommu_data.type1.listener,
                                 container->space->as);

    } else {
        error_report("vfio: No available IOMMU models");
        ret = -EINVAL;
@@ -4318,3 +4352,47 @@ static void register_vfio_pci_dev_type(void)
}

type_init(register_vfio_pci_dev_type)

static int vfio_container_do_ioctl(AddressSpace *as, int32_t groupid,
                                   int req, void *param)
{
    VFIOGroup *group;
    VFIOContainer *container;
    int ret = -1;

    group = vfio_get_group(groupid, as);
    if (!group) {
        error_report("vfio: group %d not registered", groupid);
        return ret;
    }

    container = group->container;
    if (group->container) {
        ret = ioctl(container->fd, req, param);
        if (ret < 0) {
            error_report("vfio: failed to ioctl container: ret=%d, %s",
                         ret, strerror(errno));
        }
    }

    vfio_put_group(group);

    return ret;
}

int vfio_container_ioctl(AddressSpace *as, int32_t groupid,
                         int req, void *param)
{
    /* We allow only certain ioctls to the container */
    switch (req) {
    case VFIO_CHECK_EXTENSION:
    case VFIO_IOMMU_SPAPR_TCE_GET_INFO:
        break;
    default:
        /* Return an error on unknown requests */
        error_report("vfio: unsupported ioctl %X", req);
        return -1;
    }

    return vfio_container_do_ioctl(as, groupid, req, param);
}
+2 −2
Original line number Diff line number Diff line
@@ -153,8 +153,8 @@ static int spapr_nvram_init(VIOsPAPRDevice *dev)
        return -1;
    }

    spapr_rtas_register("nvram-fetch", rtas_nvram_fetch);
    spapr_rtas_register("nvram-store", rtas_nvram_store);
    spapr_rtas_register(RTAS_NVRAM_FETCH, "nvram-fetch", rtas_nvram_fetch);
    spapr_rtas_register(RTAS_NVRAM_STORE, "nvram-store", rtas_nvram_store);

    return 0;
}
+1 −1
Original line number Diff line number Diff line
@@ -230,7 +230,7 @@ PCIBus *pci_pmac_init(qemu_irq *pic,
    d = UNI_NORTH_PCI_HOST_BRIDGE(dev);
    memory_region_init(&d->pci_mmio, OBJECT(d), "pci-mmio", 0x100000000ULL);
    memory_region_init_alias(&d->pci_hole, OBJECT(d), "pci-hole", &d->pci_mmio,
                             0x80000000ULL, 0x70000000ULL);
                             0x80000000ULL, 0x10000000ULL);
    memory_region_add_subregion(address_space_mem, 0x80000000ULL,
                                &d->pci_hole);

Loading