All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Gibson <david@gibson.dropbear.id.au>
To: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
Cc: qemu-ppc@nongnu.org, qemu-devel@nongnu.org, clg@kaod.org,
	Benjamin Herrenschmidt <benh@kernel.crashing.org>
Subject: Re: [Qemu-devel] [PATCH v1 02/11] ppc/xics: Move SPAPR specific code to a separate file
Date: Fri, 24 Jun 2016 15:19:51 +1000	[thread overview]
Message-ID: <20160624051951.GI15625@voom.fritz.box> (raw)
In-Reply-To: <1466704050-15108-3-git-send-email-nikunj@linux.vnet.ibm.com>

[-- Attachment #1: Type: text/plain, Size: 33595 bytes --]

On Thu, Jun 23, 2016 at 11:17:21PM +0530, Nikunj A Dadhania wrote:
> From: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> 
> Leave the core ICP/ICS logic in xics.c and move the top level
> class wrapper, hypercall and RTAS handlers to xics_spapr.c
> 
> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
> [add cpu.h in xics_spapr.c, move set_nr_irqs and set_nr_servers to
>  xics_spapr.c]
> Signed-off-by: Nikunj A Dadhania <nikunj@linux.vnet.ibm.com>
> ---
>  default-configs/ppc64-softmmu.mak |   1 +
>  hw/intc/Makefile.objs             |   1 +
>  hw/intc/xics.c                    | 418 +-----------------------------------
>  hw/intc/xics_spapr.c              | 432 ++++++++++++++++++++++++++++++++++++++
>  include/hw/ppc/xics.h             |  21 ++
>  5 files changed, 464 insertions(+), 409 deletions(-)
>  create mode 100644 hw/intc/xics_spapr.c
> 
> diff --git a/default-configs/ppc64-softmmu.mak b/default-configs/ppc64-softmmu.mak
> index bb71b23..c4be59f 100644
> --- a/default-configs/ppc64-softmmu.mak
> +++ b/default-configs/ppc64-softmmu.mak
> @@ -49,6 +49,7 @@ CONFIG_ETSEC=y
>  CONFIG_LIBDECNUMBER=y
>  # For pSeries
>  CONFIG_XICS=$(CONFIG_PSERIES)
> +CONFIG_XICS_SPAPR=$(CONFIG_PSERIES)
>  CONFIG_XICS_KVM=$(and $(CONFIG_PSERIES),$(CONFIG_KVM))
>  # For PReP
>  CONFIG_MC146818RTC=y
> diff --git a/hw/intc/Makefile.objs b/hw/intc/Makefile.objs
> index c7bbf88..530df2e 100644
> --- a/hw/intc/Makefile.objs
> +++ b/hw/intc/Makefile.objs
> @@ -30,6 +30,7 @@ obj-$(CONFIG_OPENPIC_KVM) += openpic_kvm.o
>  obj-$(CONFIG_RASPI) += bcm2835_ic.o bcm2836_control.o
>  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_ALLWINNER_A10_PIC) += allwinner-a10-pic.o
>  obj-$(CONFIG_S390_FLIC) += s390_flic.o
> diff --git a/hw/intc/xics.c b/hw/intc/xics.c
> index a715532..6ca391f 100644
> --- a/hw/intc/xics.c
> +++ b/hw/intc/xics.c
> @@ -32,12 +32,11 @@
>  #include "hw/hw.h"
>  #include "trace.h"
>  #include "qemu/timer.h"
> -#include "hw/ppc/spapr.h"
>  #include "hw/ppc/xics.h"
>  #include "qemu/error-report.h"
>  #include "qapi/visitor.h"
>  
> -static int get_cpu_index_by_dt_id(int cpu_dt_id)
> +int get_cpu_index_by_dt_id(int cpu_dt_id)

If this is made public it needs  xics_*() name the current one is too
generic for a global symbol.

>  {
>      PowerPCCPU *cpu = ppc_get_vcpu_by_dt_id(cpu_dt_id);
>  
> @@ -242,7 +241,7 @@ static void icp_resend(XICSState *icp, int server)
>      ics_resend(icp->ics);
>  }
>  
> -static void icp_set_cppr(XICSState *icp, int server, uint8_t cppr)
> +void icp_set_cppr(XICSState *icp, int server, uint8_t cppr)
>  {
>      ICPState *ss = icp->ss + server;
>      uint8_t old_cppr;
> @@ -266,7 +265,7 @@ static void icp_set_cppr(XICSState *icp, int server, uint8_t cppr)
>      }
>  }
>  
> -static void icp_set_mfrr(XICSState *icp, int server, uint8_t mfrr)
> +void icp_set_mfrr(XICSState *icp, int server, uint8_t mfrr)
>  {
>      ICPState *ss = icp->ss + server;
>  
> @@ -276,7 +275,7 @@ static void icp_set_mfrr(XICSState *icp, int server, uint8_t mfrr)
>      }
>  }
>  
> -static uint32_t icp_accept(ICPState *ss)
> +uint32_t icp_accept(ICPState *ss)
>  {
>      uint32_t xirr = ss->xirr;
>  
> @@ -289,7 +288,7 @@ static uint32_t icp_accept(ICPState *ss)
>      return xirr;
>  }
>  
> -static void icp_eoi(XICSState *icp, int server, uint32_t xirr)
> +void icp_eoi(XICSState *icp, int server, uint32_t xirr)
>  {
>      ICPState *ss = icp->ss + server;
>  
> @@ -390,12 +389,6 @@ static const TypeInfo icp_info = {
>  /*
>   * ICS: Source layer
>   */
> -static int ics_valid_irq(ICSState *ics, uint32_t nr)
> -{
> -    return (nr >= ics->offset)
> -        && (nr < (ics->offset + ics->nr_irqs));
> -}
> -
>  static void resend_msi(ICSState *ics, int srcno)
>  {
>      ICSIRQState *irq = ics->irqs + srcno;
> @@ -480,8 +473,8 @@ static void write_xive_lsi(ICSState *ics, int srcno)
>      resend_lsi(ics, srcno);
>  }
>  
> -static void ics_write_xive(ICSState *ics, int nr, int server,
> -                           uint8_t priority, uint8_t saved_priority)
> +void ics_write_xive(ICSState *ics, int nr, int server,
> +                    uint8_t priority, uint8_t saved_priority)
>  {
>      int srcno = nr - ics->offset;
>      ICSIRQState *irq = ics->irqs + srcno;
> @@ -658,7 +651,7 @@ static const TypeInfo ics_info = {
>  /*
>   * Exported functions
>   */
> -static int xics_find_source(XICSState *icp, int irq)
> +int xics_find_source(XICSState *icp, int irq)
>  {
>      int sources = 1;
>      int src;
> @@ -686,7 +679,7 @@ qemu_irq xics_get_qirq(XICSState *icp, int irq)
>      return NULL;
>  }
>  
> -static void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
> +void ics_set_irq_type(ICSState *ics, int srcno, bool lsi)
>  {
>      assert(!(ics->irqs[srcno].flags & XICS_FLAGS_IRQ_MASK));
>  
> @@ -705,402 +698,9 @@ void xics_set_irq_type(XICSState *icp, int irq, bool lsi)
>      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_spapr_alloc(XICSState *icp, int src, int irq_hint, bool lsi,
> -                     Error **errp)
> -{
> -    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)) {
> -            error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint);
> -            return -1;
> -        }
> -        irq = irq_hint;
> -    } else {
> -        irq = ics_find_free_block(ics, 1, 1);
> -        if (irq < 0) {
> -            error_setg(errp, "can't allocate IRQ: no IRQ left");
> -            return -1;
> -        }
> -        irq += ics->offset;
> -    }
> -
> -    ics_set_irq_type(ics, irq - ics->offset, lsi);
> -    trace_xics_alloc(src, irq);
> -
> -    return irq;
> -}
> -
> -/*
> - * Allocate block of consecutive IRQs, and return the number of the first IRQ in the block.
> - * If align==true, aligns the first IRQ number to num.
> - */
> -int xics_spapr_alloc_block(XICSState *icp, int src, int num, bool lsi,
> -                           bool align, Error **errp)
> -{
> -    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) {
> -        error_setg(errp, "can't find a free %d-IRQ block", num);
> -        return -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_spapr_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);
> -    }
> -}
> -
> -/*
> - * Guest interfaces
> - */
> -
> -static target_ulong h_cppr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> -                           target_ulong opcode, target_ulong *args)
> -{
> -    CPUState *cs = CPU(cpu);
> -    target_ulong cppr = args[0];
> -
> -    icp_set_cppr(spapr->icp, cs->cpu_index, cppr);
> -    return H_SUCCESS;
> -}
> -
> -static target_ulong h_ipi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> -                          target_ulong opcode, target_ulong *args)
> -{
> -    target_ulong server = get_cpu_index_by_dt_id(args[0]);
> -    target_ulong mfrr = args[1];
> -
> -    if (server >= spapr->icp->nr_servers) {
> -        return H_PARAMETER;
> -    }
> -
> -    icp_set_mfrr(spapr->icp, server, mfrr);
> -    return H_SUCCESS;
> -}
> -
> -static target_ulong h_xirr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> -                           target_ulong opcode, target_ulong *args)
> -{
> -    CPUState *cs = CPU(cpu);
> -    uint32_t xirr = icp_accept(spapr->icp->ss + cs->cpu_index);
> -
> -    args[0] = xirr;
> -    return H_SUCCESS;
> -}
> -
> -static target_ulong h_xirr_x(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> -                             target_ulong opcode, target_ulong *args)
> -{
> -    CPUState *cs = CPU(cpu);
> -    ICPState *ss = &spapr->icp->ss[cs->cpu_index];
> -    uint32_t xirr = icp_accept(ss);
> -
> -    args[0] = xirr;
> -    args[1] = cpu_get_host_ticks();
> -    return H_SUCCESS;
> -}
> -
> -static target_ulong h_eoi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> -                          target_ulong opcode, target_ulong *args)
> -{
> -    CPUState *cs = CPU(cpu);
> -    target_ulong xirr = args[0];
> -
> -    icp_eoi(spapr->icp, cs->cpu_index, xirr);
> -    return H_SUCCESS;
> -}
> -
> -static target_ulong h_ipoll(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> -                            target_ulong opcode, target_ulong *args)
> -{
> -    CPUState *cs = CPU(cpu);
> -    ICPState *ss = &spapr->icp->ss[cs->cpu_index];
> -
> -    args[0] = ss->xirr;
> -    args[1] = ss->mfrr;
> -
> -    return H_SUCCESS;
> -}
> -
> -static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> -                          uint32_t token,
> -                          uint32_t nargs, target_ulong args,
> -                          uint32_t nret, target_ulong rets)
> -{
> -    ICSState *ics = spapr->icp->ics;
> -    uint32_t nr, server, priority;
> -
> -    if ((nargs != 3) || (nret != 1)) {
> -        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> -        return;
> -    }
> -
> -    nr = rtas_ld(args, 0);
> -    server = get_cpu_index_by_dt_id(rtas_ld(args, 1));
> -    priority = rtas_ld(args, 2);
> -
> -    if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
> -        || (priority > 0xff)) {
> -        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> -        return;
> -    }
> -
> -    ics_write_xive(ics, nr, server, priority, priority);
> -
> -    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
> -}
> -
> -static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> -                          uint32_t token,
> -                          uint32_t nargs, target_ulong args,
> -                          uint32_t nret, target_ulong rets)
> -{
> -    ICSState *ics = spapr->icp->ics;
> -    uint32_t nr;
> -
> -    if ((nargs != 1) || (nret != 3)) {
> -        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> -        return;
> -    }
> -
> -    nr = rtas_ld(args, 0);
> -
> -    if (!ics_valid_irq(ics, nr)) {
> -        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> -        return;
> -    }
> -
> -    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
> -    rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
> -    rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
> -}
> -
> -static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> -                         uint32_t token,
> -                         uint32_t nargs, target_ulong args,
> -                         uint32_t nret, target_ulong rets)
> -{
> -    ICSState *ics = spapr->icp->ics;
> -    uint32_t nr;
> -
> -    if ((nargs != 1) || (nret != 1)) {
> -        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> -        return;
> -    }
> -
> -    nr = rtas_ld(args, 0);
> -
> -    if (!ics_valid_irq(ics, nr)) {
> -        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> -        return;
> -    }
> -
> -    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
> -                   ics->irqs[nr - ics->offset].priority);
> -
> -    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
> -}
> -
> -static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> -                        uint32_t token,
> -                        uint32_t nargs, target_ulong args,
> -                        uint32_t nret, target_ulong rets)
> -{
> -    ICSState *ics = spapr->icp->ics;
> -    uint32_t nr;
> -
> -    if ((nargs != 1) || (nret != 1)) {
> -        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> -        return;
> -    }
> -
> -    nr = rtas_ld(args, 0);
> -
> -    if (!ics_valid_irq(ics, nr)) {
> -        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> -        return;
> -    }
> -
> -    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
> -                   ics->irqs[nr - ics->offset].saved_priority,
> -                   ics->irqs[nr - ics->offset].saved_priority);
> -
> -    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
> -}
> -
> -/*
> - * XICS
> - */
> -
> -static void xics_set_nr_irqs(XICSState *icp, uint32_t nr_irqs, Error **errp)
> -{
> -    icp->nr_irqs = icp->ics->nr_irqs = nr_irqs;
> -}
> -
> -static void xics_set_nr_servers(XICSState *icp, uint32_t nr_servers,
> -                                Error **errp)
> -{
> -    int i;
> -
> -    icp->nr_servers = nr_servers;
> -
> -    icp->ss = g_malloc0(icp->nr_servers*sizeof(ICPState));
> -    for (i = 0; i < icp->nr_servers; i++) {
> -        char buffer[32];
> -        object_initialize(&icp->ss[i], sizeof(icp->ss[i]), TYPE_ICP);
> -        snprintf(buffer, sizeof(buffer), "icp[%d]", i);
> -        object_property_add_child(OBJECT(icp), buffer, OBJECT(&icp->ss[i]),
> -                                  errp);
> -    }
> -}
> -
> -static void xics_spapr_realize(DeviceState *dev, Error **errp)
> -{
> -    XICSState *icp = XICS(dev);
> -    Error *error = NULL;
> -    int i;
> -
> -    if (!icp->nr_servers) {
> -        error_setg(errp, "Number of servers needs to be greater 0");
> -        return;
> -    }
> -
> -    /* Registration of global state belongs into realize */
> -    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);
> -    spapr_register_hypercall(H_XIRR, h_xirr);
> -    spapr_register_hypercall(H_XIRR_X, h_xirr_x);
> -    spapr_register_hypercall(H_EOI, h_eoi);
> -    spapr_register_hypercall(H_IPOLL, h_ipoll);
> -
> -    object_property_set_bool(OBJECT(icp->ics), true, "realized", &error);
> -    if (error) {
> -        error_propagate(errp, error);
> -        return;
> -    }
> -
> -    for (i = 0; i < icp->nr_servers; i++) {
> -        object_property_set_bool(OBJECT(&icp->ss[i]), true, "realized", &error);
> -        if (error) {
> -            error_propagate(errp, error);
> -            return;
> -        }
> -    }
> -}
> -
> -static void xics_spapr_initfn(Object *obj)
> -{
> -    XICSState *xics = XICS(obj);
> -
> -    xics->ics = ICS(object_new(TYPE_ICS));
> -    object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
> -    xics->ics->icp = xics;
> -}
> -
> -static void xics_spapr_class_init(ObjectClass *oc, void *data)
> -{
> -    DeviceClass *dc = DEVICE_CLASS(oc);
> -    XICSStateClass *xsc = XICS_SPAPR_CLASS(oc);
> -
> -    dc->realize = xics_spapr_realize;
> -    xsc->set_nr_irqs = xics_set_nr_irqs;
> -    xsc->set_nr_servers = xics_set_nr_servers;
> -}
> -
> -static const TypeInfo xics_spapr_info = {
> -    .name          = TYPE_XICS_SPAPR,
> -    .parent        = TYPE_XICS_COMMON,
> -    .instance_size = sizeof(XICSState),
> -    .class_size = sizeof(XICSStateClass),
> -    .class_init    = xics_spapr_class_init,
> -    .instance_init = xics_spapr_initfn,
> -};
> -
>  static void xics_register_types(void)
>  {
>      type_register_static(&xics_common_info);
> -    type_register_static(&xics_spapr_info);
>      type_register_static(&ics_info);
>      type_register_static(&icp_info);
>  }
> diff --git a/hw/intc/xics_spapr.c b/hw/intc/xics_spapr.c
> new file mode 100644
> index 0000000..48d458a
> --- /dev/null
> +++ b/hw/intc/xics_spapr.c
> @@ -0,0 +1,432 @@
> +/*
> + * QEMU PowerPC pSeries Logical Partition (aka sPAPR) hardware System Emulator
> + *
> + * PAPR Virtualized Interrupt System, aka ICS/ICP aka xics
> + *
> + * Copyright (c) 2010,2011 David Gibson, IBM Corporation.
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a copy
> + * of this software and associated documentation files (the "Software"), to deal
> + * in the Software without restriction, including without limitation the rights
> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
> + * copies of the Software, and to permit persons to whom the Software is
> + * furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice shall be included in
> + * all copies or substantial portions of the Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
> + * THE SOFTWARE.
> + *
> + */
> +
> +#include "qemu/osdep.h"
> +#include "cpu.h"
> +#include "hw/hw.h"
> +#include "trace.h"
> +#include "qemu/timer.h"
> +#include "hw/ppc/spapr.h"
> +#include "hw/ppc/xics.h"
> +#include "qapi/visitor.h"
> +#include "qapi/error.h"
> +
> +/*
> + * Guest interfaces
> + */
> +
> +static target_ulong h_cppr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> +                           target_ulong opcode, target_ulong *args)
> +{
> +    CPUState *cs = CPU(cpu);
> +    target_ulong cppr = args[0];
> +
> +    icp_set_cppr(spapr->icp, cs->cpu_index, cppr);
> +    return H_SUCCESS;
> +}
> +
> +static target_ulong h_ipi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> +                          target_ulong opcode, target_ulong *args)
> +{
> +    target_ulong server = get_cpu_index_by_dt_id(args[0]);
> +    target_ulong mfrr = args[1];
> +
> +    if (server >= spapr->icp->nr_servers) {
> +        return H_PARAMETER;
> +    }
> +
> +    icp_set_mfrr(spapr->icp, server, mfrr);
> +    return H_SUCCESS;
> +}
> +
> +static target_ulong h_xirr(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> +                           target_ulong opcode, target_ulong *args)
> +{
> +    CPUState *cs = CPU(cpu);
> +    uint32_t xirr = icp_accept(spapr->icp->ss + cs->cpu_index);
> +
> +    args[0] = xirr;
> +    return H_SUCCESS;
> +}
> +
> +static target_ulong h_xirr_x(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> +                             target_ulong opcode, target_ulong *args)
> +{
> +    CPUState *cs = CPU(cpu);
> +    ICPState *ss = &spapr->icp->ss[cs->cpu_index];
> +    uint32_t xirr = icp_accept(ss);
> +
> +    args[0] = xirr;
> +    args[1] = cpu_get_host_ticks();
> +    return H_SUCCESS;
> +}
> +
> +static target_ulong h_eoi(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> +                          target_ulong opcode, target_ulong *args)
> +{
> +    CPUState *cs = CPU(cpu);
> +    target_ulong xirr = args[0];
> +
> +    icp_eoi(spapr->icp, cs->cpu_index, xirr);
> +    return H_SUCCESS;
> +}
> +
> +static target_ulong h_ipoll(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> +                            target_ulong opcode, target_ulong *args)
> +{
> +    CPUState *cs = CPU(cpu);
> +    ICPState *ss = &spapr->icp->ss[cs->cpu_index];
> +
> +    args[0] = ss->xirr;
> +    args[1] = ss->mfrr;
> +
> +    return H_SUCCESS;
> +}
> +
> +static void rtas_set_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> +                          uint32_t token,
> +                          uint32_t nargs, target_ulong args,
> +                          uint32_t nret, target_ulong rets)
> +{
> +    ICSState *ics = spapr->icp->ics;
> +    uint32_t nr, server, priority;
> +
> +    if ((nargs != 3) || (nret != 1)) {
> +        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> +        return;
> +    }
> +
> +    nr = rtas_ld(args, 0);
> +    server = get_cpu_index_by_dt_id(rtas_ld(args, 1));
> +    priority = rtas_ld(args, 2);
> +
> +    if (!ics_valid_irq(ics, nr) || (server >= ics->icp->nr_servers)
> +        || (priority > 0xff)) {
> +        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> +        return;
> +    }
> +
> +    ics_write_xive(ics, nr, server, priority, priority);
> +
> +    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
> +}
> +
> +static void rtas_get_xive(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> +                          uint32_t token,
> +                          uint32_t nargs, target_ulong args,
> +                          uint32_t nret, target_ulong rets)
> +{
> +    ICSState *ics = spapr->icp->ics;
> +    uint32_t nr;
> +
> +    if ((nargs != 1) || (nret != 3)) {
> +        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> +        return;
> +    }
> +
> +    nr = rtas_ld(args, 0);
> +
> +    if (!ics_valid_irq(ics, nr)) {
> +        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> +        return;
> +    }
> +
> +    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
> +    rtas_st(rets, 1, ics->irqs[nr - ics->offset].server);
> +    rtas_st(rets, 2, ics->irqs[nr - ics->offset].priority);
> +}
> +
> +static void rtas_int_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> +                         uint32_t token,
> +                         uint32_t nargs, target_ulong args,
> +                         uint32_t nret, target_ulong rets)
> +{
> +    ICSState *ics = spapr->icp->ics;
> +    uint32_t nr;
> +
> +    if ((nargs != 1) || (nret != 1)) {
> +        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> +        return;
> +    }
> +
> +    nr = rtas_ld(args, 0);
> +
> +    if (!ics_valid_irq(ics, nr)) {
> +        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> +        return;
> +    }
> +
> +    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server, 0xff,
> +                   ics->irqs[nr - ics->offset].priority);
> +
> +    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
> +}
> +
> +static void rtas_int_on(PowerPCCPU *cpu, sPAPRMachineState *spapr,
> +                        uint32_t token,
> +                        uint32_t nargs, target_ulong args,
> +                        uint32_t nret, target_ulong rets)
> +{
> +    ICSState *ics = spapr->icp->ics;
> +    uint32_t nr;
> +
> +    if ((nargs != 1) || (nret != 1)) {
> +        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> +        return;
> +    }
> +
> +    nr = rtas_ld(args, 0);
> +
> +    if (!ics_valid_irq(ics, nr)) {
> +        rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
> +        return;
> +    }
> +
> +    ics_write_xive(ics, nr, ics->irqs[nr - ics->offset].server,
> +                   ics->irqs[nr - ics->offset].saved_priority,
> +                   ics->irqs[nr - ics->offset].saved_priority);
> +
> +    rtas_st(rets, 0, RTAS_OUT_SUCCESS);
> +}
> +
> +static void xics_spapr_set_nr_irqs(XICSState *icp, uint32_t nr_irqs,
> +                                   Error **errp)
> +{
> +    icp->nr_irqs = icp->ics->nr_irqs = nr_irqs;
> +}
> +
> +static void xics_spapr_set_nr_servers(XICSState *icp, uint32_t nr_servers,
> +                                      Error **errp)
> +{
> +    int i;
> +
> +    icp->nr_servers = nr_servers;
> +
> +    icp->ss = g_malloc0(icp->nr_servers * sizeof(ICPState));
> +    for (i = 0; i < icp->nr_servers; i++) {
> +        char buffer[32];
> +        object_initialize(&icp->ss[i], sizeof(icp->ss[i]), TYPE_ICP);
> +        snprintf(buffer, sizeof(buffer), "icp[%d]", i);
> +        object_property_add_child(OBJECT(icp), buffer, OBJECT(&icp->ss[i]),
> +                                  errp);
> +    }
> +}
> +
> +static void xics_spapr_realize(DeviceState *dev, Error **errp)
> +{
> +    XICSState *icp = XICS(dev);
> +    Error *error = NULL;
> +    int i;
> +
> +    if (!icp->nr_servers) {
> +        error_setg(errp, "Number of servers needs to be greater 0");
> +        return;
> +    }
> +
> +    /* Registration of global state belongs into realize */
> +    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);
> +    spapr_register_hypercall(H_XIRR, h_xirr);
> +    spapr_register_hypercall(H_XIRR_X, h_xirr_x);
> +    spapr_register_hypercall(H_EOI, h_eoi);
> +    spapr_register_hypercall(H_IPOLL, h_ipoll);
> +
> +    object_property_set_bool(OBJECT(icp->ics), true, "realized", &error);
> +    if (error) {
> +        error_propagate(errp, error);
> +        return;
> +    }
> +
> +    for (i = 0; i < icp->nr_servers; i++) {
> +        object_property_set_bool(OBJECT(&icp->ss[i]), true, "realized", &error);
> +        if (error) {
> +            error_propagate(errp, error);
> +            return;
> +        }
> +    }
> +}
> +
> +static void xics_spapr_initfn(Object *obj)
> +{
> +    XICSState *xics = XICS(obj);
> +
> +    xics->ics = ICS(object_new(TYPE_ICS));
> +    object_property_add_child(obj, "ics", OBJECT(xics->ics), NULL);
> +    xics->ics->icp = xics;
> +}
> +
> +static void xics_spapr_class_init(ObjectClass *oc, void *data)
> +{
> +    DeviceClass *dc = DEVICE_CLASS(oc);
> +    XICSStateClass *xsc = XICS_SPAPR_CLASS(oc);
> +
> +    dc->realize = xics_spapr_realize;
> +    xsc->set_nr_irqs = xics_spapr_set_nr_irqs;
> +    xsc->set_nr_servers = xics_spapr_set_nr_servers;
> +}
> +
> +static const TypeInfo xics_spapr_info = {
> +    .name          = TYPE_XICS_SPAPR,
> +    .parent        = TYPE_XICS_COMMON,
> +    .instance_size = sizeof(XICSState),
> +    .class_size = sizeof(XICSStateClass),
> +    .class_init    = xics_spapr_class_init,
> +    .instance_init = xics_spapr_initfn,
> +};
> +
> +#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_spapr_alloc(XICSState *icp, int src, int irq_hint, bool lsi,
> +                     Error **errp)
> +{
> +    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)) {
> +            error_setg(errp, "can't allocate IRQ %d: already in use", irq_hint);
> +            return -1;
> +        }
> +        irq = irq_hint;
> +    } else {
> +        irq = ics_find_free_block(ics, 1, 1);
> +        if (irq < 0) {
> +            error_setg(errp, "can't allocate IRQ: no IRQ left");
> +            return -1;
> +        }
> +        irq += ics->offset;
> +    }
> +
> +    ics_set_irq_type(ics, irq - ics->offset, lsi);
> +    trace_xics_alloc(src, irq);
> +
> +    return irq;
> +}
> +
> +/*
> + * Allocate block of consecutive IRQs, and return the number of the first IRQ in
> + * the block. If align==true, aligns the first IRQ number to num.
> + */
> +int xics_spapr_alloc_block(XICSState *icp, int src, int num, bool lsi,
> +                           bool align, Error **errp)
> +{
> +    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) {
> +        error_setg(errp, "can't find a free %d-IRQ block", num);
> +        return -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_spapr_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);
> +    }
> +}
> +
> +static void xics_spapr_register_types(void)
> +{
> +    type_register_static(&xics_spapr_info);
> +}
> +
> +type_init(xics_spapr_register_types)
> diff --git a/include/hw/ppc/xics.h b/include/hw/ppc/xics.h
> index 452a978..76b45ef 100644
> --- a/include/hw/ppc/xics.h
> +++ b/include/hw/ppc/xics.h
> @@ -145,6 +145,12 @@ struct ICSState {
>      XICSState *icp;
>  };
>  
> +static inline bool ics_valid_irq(ICSState *ics, uint32_t nr)
> +{
> +    return (nr >= ics->offset)
> +        && (nr < (ics->offset + ics->nr_irqs));
> +}
> +
>  struct ICSIRQState {
>      uint32_t server;
>      uint8_t priority;
> @@ -174,4 +180,19 @@ void xics_spapr_free(XICSState *icp, int irq, int num);
>  void xics_cpu_setup(XICSState *icp, PowerPCCPU *cpu);
>  void xics_cpu_destroy(XICSState *icp, PowerPCCPU *cpu);
>  
> +/* Internal XICS interfaces */
> +int get_cpu_index_by_dt_id(int cpu_dt_id);
> +
> +void icp_set_cppr(XICSState *icp, int server, uint8_t cppr);
> +void icp_set_mfrr(XICSState *icp, int server, uint8_t mfrr);
> +uint32_t icp_accept(ICPState *ss);
> +void icp_eoi(XICSState *icp, int server, uint32_t xirr);
> +
> +void ics_write_xive(ICSState *ics, int nr, int server,
> +                    uint8_t priority, uint8_t saved_priority);
> +
> +void ics_set_irq_type(ICSState *ics, int srcno, bool lsi);
> +
> +int xics_find_source(XICSState *icp, int irq);
> +
>  #endif /* __XICS_H__ */

-- 
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 #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

  reply	other threads:[~2016-06-24  5:21 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-06-23 17:47 [Qemu-devel] [PATCH v1 00/11] sPAPR xics rework/cleanup Nikunj A Dadhania
2016-06-23 17:47 ` [Qemu-devel] [PATCH v1 01/11] ppc/xics: Rename existing xics to xics_spapr Nikunj A Dadhania
2016-06-24  5:17   ` David Gibson
2016-06-24  5:53     ` Nikunj A Dadhania
2016-06-23 17:47 ` [Qemu-devel] [PATCH v1 02/11] ppc/xics: Move SPAPR specific code to a separate file Nikunj A Dadhania
2016-06-24  5:19   ` David Gibson [this message]
2016-06-24  5:57     ` Nikunj A Dadhania
2016-06-24  6:12       ` David Gibson
2016-06-23 17:47 ` [Qemu-devel] [PATCH v1 03/11] ppc/xics: Implement H_IPOLL using an accessor Nikunj A Dadhania
2016-06-24  5:21   ` David Gibson
2016-06-23 17:47 ` [Qemu-devel] [PATCH v1 04/11] ppc/xics: Remove unused xics_set_irq_type() Nikunj A Dadhania
2016-06-24  5:45   ` David Gibson
2016-06-23 17:47 ` [Qemu-devel] [PATCH v1 05/11] ppc/xics: Replace "icp" with "xics" in most places Nikunj A Dadhania
2016-06-27  3:43   ` David Gibson
2016-06-23 17:47 ` [Qemu-devel] [PATCH v1 06/11] ppc/xics: Make the ICSState a list Nikunj A Dadhania
2016-06-27  4:20   ` David Gibson
2016-06-27  4:56     ` Nikunj A Dadhania
2016-06-27  5:30       ` David Gibson
2016-06-27  5:32         ` Nikunj A Dadhania
2016-06-27  4:59     ` Nikunj A Dadhania
2016-06-23 17:47 ` [Qemu-devel] [PATCH v1 07/11] ppc/xics: An ICS with offset 0 is assumed to be uninitialized Nikunj A Dadhania
2016-06-23 17:47 ` [Qemu-devel] [PATCH v1 08/11] ppc/xics: Use a helper to add a new ICS Nikunj A Dadhania
2016-06-27  4:21   ` David Gibson
2016-06-23 17:47 ` [Qemu-devel] [PATCH v1 09/11] ppc/xics: Split ICS into ics-base and ics class Nikunj A Dadhania
2016-06-27  4:26   ` David Gibson
2016-06-27  5:18     ` Nikunj A Dadhania
2016-06-27 10:11       ` Nikunj A Dadhania
2016-06-28  3:00         ` David Gibson
2016-06-28  5:06           ` Nikunj A Dadhania
2016-06-28  6:25             ` David Gibson
2016-06-23 17:47 ` [Qemu-devel] [PATCH v1 10/11] ppc/xics: Add "native" XICS subclass Nikunj A Dadhania
2016-06-27  4:36   ` David Gibson
2016-06-27  9:53     ` Nikunj A Dadhania
2016-06-28  2:58       ` David Gibson
2016-06-23 17:47 ` [Qemu-devel] [PATCH v1 11/11] ppc/xics: Add xics to the monitor "info pic" command Nikunj A Dadhania
2016-06-27  4:48   ` David Gibson
2016-06-27  5:56     ` Benjamin Herrenschmidt

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20160624051951.GI15625@voom.fritz.box \
    --to=david@gibson.dropbear.id.au \
    --cc=benh@kernel.crashing.org \
    --cc=clg@kaod.org \
    --cc=nikunj@linux.vnet.ibm.com \
    --cc=qemu-devel@nongnu.org \
    --cc=qemu-ppc@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.