qemu-ppc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Qemu-ppc] [PATCH v2 4/8] ppc/pnv: add a PnvICPState object


From: David Gibson
Subject: Re: [Qemu-ppc] [PATCH v2 4/8] ppc/pnv: add a PnvICPState object
Date: Thu, 23 Mar 2017 15:12:00 +1100
User-agent: Mutt/1.8.0 (2017-02-23)

On Thu, Mar 16, 2017 at 03:35:08PM +0100, Cédric Le Goater wrote:
> This provides a new ICPState object for the PowerNV machine (POWER8).
> Access to the Interrupt Management area is done though a memory
> region. It contains the registers of the Interrupt Control Presenters
> of each thread which are used to accept, return, forward interrupts in
> the system.
> 
> Signed-off-by: Cédric Le Goater <address@hidden>

Revieed-by: David Gibson <address@hidden>

> ---
> 
>  Changes since v1:
> 
>  - moved the memory region from PnvCore to a specific PnvICPState object
> 
>  hw/intc/Makefile.objs |   1 +
>  hw/intc/xics_pnv.c    | 180 
> ++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/hw/ppc/xics.h |  12 ++++
>  3 files changed, 193 insertions(+)
>  create mode 100644 hw/intc/xics_pnv.c
> 
> diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
> index adedd0da5fd8..78426a7dafcd 100644
> --- a/hw/intc/Makefile.objs
> +++ b/hw/intc/Makefile.objs
> @@ -35,6 +35,7 @@ obj-$(CONFIG_SH4) += sh_intc.o
>  obj-$(CONFIG_XICS) += xics.o
>  obj-$(CONFIG_XICS_SPAPR) += xics_spapr.o
>  obj-$(CONFIG_XICS_KVM) += xics_kvm.o
> +obj-$(CONFIG_POWERNV) += xics_pnv.o
>  obj-$(CONFIG_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
>  obj-$(CONFIG_S390_FLIC) += s390_flic.o
>  obj-$(CONFIG_S390_FLIC_KVM) += s390_flic_kvm.o
> diff --git a/hw/intc/xics_pnv.c b/hw/intc/xics_pnv.c
> new file mode 100644
> index 000000000000..68a3ef6097a6
> --- /dev/null
> +++ b/hw/intc/xics_pnv.c
> @@ -0,0 +1,180 @@
> +/*
> + * QEMU PowerPC PowerNV ICP model
> + *
> + * Copyright (c) 2016, IBM Corporation.
> + *
> + * This library is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU Lesser General Public License
> + * as published by the Free Software Foundation; either version 2 of
> + * the License, or (at your option) any later version.
> + *
> + * This library is distributed in the hope that it will be useful, but
> + * WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
> + * Lesser General Public License for more details.
> + *
> + * You should have received a copy of the GNU Lesser General Public
> + * License along with this library; if not, see 
> <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "sysemu/sysemu.h"
> +#include "qapi/error.h"
> +#include "qemu/log.h"
> +#include "hw/ppc/xics.h"
> +
> +static uint64_t pnv_icp_read(void *opaque, hwaddr addr, unsigned width)
> +{
> +    ICPState *icp = ICP(opaque);
> +    PnvICPState *picp = PNV_ICP(opaque);
> +    bool byte0 = (width == 1 && (addr & 0x3) == 0);
> +    uint64_t val = 0xffffffff;
> +
> +    switch (addr & 0xffc) {
> +    case 0: /* poll */
> +        val = icp_ipoll(icp, NULL);
> +        if (byte0) {
> +            val >>= 24;
> +        } else if (width != 4) {
> +            goto bad_access;
> +        }
> +        break;
> +    case 4: /* xirr */
> +        if (byte0) {
> +            val = icp_ipoll(icp, NULL) >> 24;
> +        } else if (width == 4) {
> +            val = icp_accept(icp);
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 12:
> +        if (byte0) {
> +            val = icp->mfrr;
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 16:
> +        if (width == 4) {
> +            val = picp->links[0];
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 20:
> +        if (width == 4) {
> +            val = picp->links[1];
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 24:
> +        if (width == 4) {
> +            val = picp->links[2];
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    default:
> +bad_access:
> +        qemu_log_mask(LOG_GUEST_ERROR, "XICS: Bad ICP access 0x%"
> +                      HWADDR_PRIx"/%d\n", addr, width);
> +    }
> +
> +    return val;
> +}
> +
> +static void pnv_icp_write(void *opaque, hwaddr addr, uint64_t val,
> +                              unsigned width)
> +{
> +    ICPState *icp = ICP(opaque);
> +    PnvICPState *picp = PNV_ICP(opaque);
> +    bool byte0 = (width == 1 && (addr & 0x3) == 0);
> +
> +    switch (addr & 0xffc) {
> +    case 4: /* xirr */
> +        if (byte0) {
> +            icp_set_cppr(icp, val);
> +        } else if (width == 4) {
> +            icp_eoi(icp, val);
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 12:
> +        if (byte0) {
> +            icp_set_mfrr(icp, val);
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 16:
> +        if (width == 4) {
> +            picp->links[0] = val;
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 20:
> +        if (width == 4) {
> +            picp->links[1] = val;
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    case 24:
> +        if (width == 4) {
> +            picp->links[2] = val;
> +        } else {
> +            goto bad_access;
> +        }
> +        break;
> +    default:
> +bad_access:
> +        qemu_log_mask(LOG_GUEST_ERROR, "XICS: Bad ICP access 0x%"
> +                      HWADDR_PRIx"/%d\n", addr, width);
> +    }
> +}
> +
> +static const MemoryRegionOps pnv_icp_ops = {
> +    .read = pnv_icp_read,
> +    .write = pnv_icp_write,
> +    .valid.min_access_size = 1,
> +    .valid.max_access_size = 4,
> +    .impl.min_access_size = 1,
> +    .impl.max_access_size = 4,
> +    .endianness = DEVICE_BIG_ENDIAN,
> +};
> +
> +static void pnv_icp_realize(DeviceState *dev, Error **errp)
> +{
> +    PnvICPState *icp = PNV_ICP(dev);
> +
> +    memory_region_init_io(&icp->mmio, OBJECT(dev), &pnv_icp_ops,
> +                          icp, "icp-thread", 0x1000);
> +}
> +
> +static void pnv_icp_class_init(ObjectClass *klass, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(klass);
> +    ICPStateClass *icpc = ICP_CLASS(klass);
> +
> +    icpc->realize = pnv_icp_realize;
> +    dc->desc = "PowerNV ICP";
> +}
> +
> +static const TypeInfo pnv_icp_info = {
> +    .name          = TYPE_PNV_ICP,
> +    .parent        = TYPE_ICP,
> +    .instance_size = sizeof(PnvICPState),
> +    .class_init    = pnv_icp_class_init,
> +    .class_size    = sizeof(ICPStateClass),
> +};
> +
> +static void pnv_icp_register_types(void)
> +{
> +    type_register_static(&pnv_icp_info);
> +}
> +
> +type_init(pnv_icp_register_types)
> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
> index 0863e3a079f5..cfcf7ecece69 100644
> --- a/include/hw/ppc/xics.h
> +++ b/include/hw/ppc/xics.h
> @@ -41,10 +41,12 @@
>   */
>  typedef struct ICPStateClass ICPStateClass;
>  typedef struct ICPState ICPState;
> +typedef struct PnvICPState PnvICPState;
>  typedef struct ICSStateClass ICSStateClass;
>  typedef struct ICSState ICSState;
>  typedef struct ICSIRQState ICSIRQState;
>  typedef struct XICSFabric XICSFabric;
> +typedef struct PowerPCCPU PowerPCCPU;
>  
>  #define TYPE_ICP "icp"
>  #define ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_ICP)
> @@ -52,6 +54,9 @@ typedef struct XICSFabric XICSFabric;
>  #define TYPE_KVM_ICP "icp-kvm"
>  #define KVM_ICP(obj) OBJECT_CHECK(ICPState, (obj), TYPE_KVM_ICP)
>  
> +#define TYPE_PNV_ICP "pnv-icp"
> +#define PNV_ICP(obj) OBJECT_CHECK(PnvICPState, (obj), TYPE_PNV_ICP)
> +
>  #define ICP_CLASS(klass) \
>       OBJECT_CLASS_CHECK(ICPStateClass, (klass), TYPE_ICP)
>  #define ICP_GET_CLASS(obj) \
> @@ -81,6 +86,13 @@ struct ICPState {
>      XICSFabric *xics;
>  };
>  
> +struct PnvICPState {
> +    ICPState parent_obj;
> +
> +    MemoryRegion mmio;
> +    uint32_t links[3];
> +};
> +
>  #define TYPE_ICS_BASE "ics-base"
>  #define ICS_BASE(obj) OBJECT_CHECK(ICSState, (obj), TYPE_ICS_BASE)
>  

-- 
David Gibson                    | I'll have my music baroque, and my code
david AT gibson.dropbear.id.au  | minimalist, thank you.  NOT _the_ _other_
                                | _way_ _around_!
http://www.ozlabs.org/~dgibson

Attachment: signature.asc
Description: PGP signature


reply via email to

[Prev in Thread] Current Thread [Next in Thread]