qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH v3 5/8] ppc/pnv: create the ICP and ICS objects


From: David Gibson
Subject: Re: [Qemu-devel] [PATCH v3 5/8] ppc/pnv: create the ICP and ICS objects under the machine
Date: Sun, 2 Apr 2017 16:11:00 +1000
User-agent: Mutt/1.8.0 (2017-02-23)

On Thu, Mar 30, 2017 at 10:15:11AM +0200, Cédric Le Goater wrote:
> On 03/30/2017 03:55 AM, David Gibson wrote:
> > On Wed, Mar 29, 2017 at 10:13:59AM +0200, Cédric Le Goater wrote:
> >> On 03/29/2017 07:18 AM, David Gibson wrote:
> >>> On Tue, Mar 28, 2017 at 09:32:29AM +0200, Cédric Le Goater wrote:
> >>>> Like this is done for the sPAPR machine, we use a simple array under
> >>>> the PowerNV machine to store the Interrupt Control Presenters (ICP)
> >>>> objects, one for each vCPU. This array is indexed by 'cpu_index' of
> >>>> the CPUState but the users will provide a core PIR number. The mapping
> >>>> is done in the icp_get() handler of the machine and is transparent to
> >>>> XICS.
> >>>>
> >>>> The Interrupt Control Sources (ICS), Processor Service Interface and
> >>>> PCI-E interface models, will be introduced in subsequent patches. For
> >>>> now, we have none, so we just prepare ground with place holders.
> >>>>
> >>>> Finally, to interface with the XICS layer which manipulates the ICP
> >>>> and ICS objects, we extend the PowerNV machine with an XICSFabric
> >>>> interface and its associated handlers.
> >>>>
> >>>> Signed-off-by: Cédric Le Goater <address@hidden>
> >>>> ---
> >>>>
> >>>>  Changes since v2:
> >>>>
> >>>>  - removed the list of ICS. The handlers will iterate on the chips to
> >>>>    use the available ICS.
> >>>>
> >>>>  Changes since v1:
> >>>>
> >>>>  - handled pir-to-cpu_index mapping under icp_get 
> >>>>  - removed ics_eio handler
> >>>>  - changed ICP name indexing
> >>>>  - removed sysbus parenting of the ICP object
> >>>>
> >>>>  hw/ppc/pnv.c         | 96 
> >>>> ++++++++++++++++++++++++++++++++++++++++++++++++++++
> >>>>  include/hw/ppc/pnv.h |  3 ++
> >>>>  2 files changed, 99 insertions(+)
> >>>>
> >>>> diff --git a/hw/ppc/pnv.c b/hw/ppc/pnv.c
> >>>> index 3fa722af82e6..e441b8ac1cad 100644
> >>>> --- a/hw/ppc/pnv.c
> >>>> +++ b/hw/ppc/pnv.c
> >>>> @@ -33,7 +33,10 @@
> >>>>  #include "exec/address-spaces.h"
> >>>>  #include "qemu/cutils.h"
> >>>>  #include "qapi/visitor.h"
> >>>> +#include "monitor/monitor.h"
> >>>> +#include "hw/intc/intc.h"
> >>>>  
> >>>> +#include "hw/ppc/xics.h"
> >>>>  #include "hw/ppc/pnv_xscom.h"
> >>>>  
> >>>>  #include "hw/isa/isa.h"
> >>>> @@ -417,6 +420,23 @@ static void ppc_powernv_init(MachineState *machine)
> >>>>          machine->cpu_model = "POWER8";
> >>>>      }
> >>>>  
> >>>> +    /* Create the Interrupt Control Presenters before the vCPUs */
> >>>> +    pnv->nr_servers = pnv->num_chips * smp_cores * smp_threads;
> >>>> +    pnv->icps = g_new0(PnvICPState, pnv->nr_servers);
> >>>> +    for (i = 0; i < pnv->nr_servers; i++) {
> >>>> +        PnvICPState *icp = &pnv->icps[i];
> >>>> +        char name[32];
> >>>> +
> >>>> +        /* TODO: fix ICP object name to be in sync with the core name */
> >>>> +        snprintf(name, sizeof(name), "icp[%d]", i);
> >>>
> >>> It may end up being the same value, but since the qom name is exposed
> >>> to the outside, it would be better to have it be the PIR, rather than
> >>> the cpu_index.
> >>
> >> The problem is that the ICPState objects are created before the PnvChip
> >> objects. The PnvChip sanitizes the core layout in terms HW id and then 
> >> creates the PnvCore objects. The core creates a PowerPCCPU object per 
> >> thread and, in the realize function, uses the XICSFabric to look for
> >> a matching ICP to link the CPU with. 
> >>
> >> So it is a little complex to do what you ask for ...
> >>
> >> What would really simplify the code, would be to allocate a TYPE_PNV_ICP
> >> object when the PowerPCCPU object is realized and store it under the 
> >> 'icp/intc' backlink. The XICSFabric handler icp_get() would not need 
> >> the 'icps' array anymore. 
> >>
> >> How's that proposal ?
> > 
> > Sounds workable.  You could do that from the core realize function,
> > couldn't you?
> 
> OK, it would look better from a QOM perspective, I agree, as we would 
> not "realize" the PowerPCCPU object before creating the ICP object.
> I will send an update of this patch for you to review : 
> 
>       [PATCH v4 5/9] ppc/pnv: create the ICP object under PnvCore
> 
> 
> We could follow the exact same pattern for the sPAPR machine if we 
> knew which ICP type to use (KVM or not). May be a new XICSFabric 
> handler :
> 
>       const char *icp_type(XICSFabric *xi)
> 
> would help for that ? I don't think we can use a property because of 
> the hotplug mechanism.

Hmm, couldn't we just move our existing logic for deciding the ICP
type into the spapr core object?

> 
>  
> >>>> +        object_initialize(icp, sizeof(*icp), TYPE_PNV_ICP);
> >>>> +        object_property_add_child(OBJECT(pnv), name, OBJECT(icp),
> >>>> +                                  &error_fatal);
> >>>> +        object_property_add_const_link(OBJECT(icp), "xics", OBJECT(pnv),
> >>>> +                                       &error_fatal);
> >>>> +        object_property_set_bool(OBJECT(icp), true, "realized", 
> >>>> &error_fatal);
> >>>> +    }
> >>>> +
> >>>>      /* Create the processor chips */
> >>>>      chip_typename = g_strdup_printf(TYPE_PNV_CHIP "-%s", 
> >>>> machine->cpu_model);
> >>>>      if (!object_class_by_name(chip_typename)) {
> >>>> @@ -737,6 +757,71 @@ static const TypeInfo pnv_chip_info = {
> >>>>      .abstract      = true,
> >>>>  };
> >>>>  
> >>>> +static ICSState *pnv_ics_get(XICSFabric *xi, int irq)
> >>>> +{
> >>>> +    PnvMachineState *pnv = POWERNV_MACHINE(xi);
> >>>> +    int i;
> >>>> +
> >>>> +    for (i = 0; i < pnv->num_chips; i++) {
> >>>> +        /* place holder */
> >>>> +    }
> >>>> +    return NULL;
> >>>> +}
> >>>> +
> >>>> +static void pnv_ics_resend(XICSFabric *xi)
> >>>> +{
> >>>> +    PnvMachineState *pnv = POWERNV_MACHINE(xi);
> >>>> +    int i;
> >>>> +
> >>>> +    for (i = 0; i < pnv->num_chips; i++) {
> >>>> +        /* place holder */
> >>>> +    }
> >>>> +}
> >>>
> >>> Seems like the above two functions belong in a later patch.
> >>
> >> OK. I guess we can add these handlers in the next patchset introducing 
> >> PSI. 
> >> I will check that the tests still run because the XICS layer uses the 
> >> XICSFabric handlers blindly without any checks.
> > 
> > Well, sure, but the whole XICS isn't going to work without real
> > implementations of the ICS callbacks, so I don't see that it matters.
> 
> Just to be very clear, what I meant is that we need to define all
> the handlers at once because the XICS layer does not check the 
> handler validity and we would end up calling NULL. In patchset v4,
> the handlers are empty routines. 
> 
> Thanks,
> 
> C. 
>  
> >>  
> >>>> +
> >>>> +static PowerPCCPU *ppc_get_vcpu_by_pir(int pir)
> >>>> +{
> >>>> +    CPUState *cs;
> >>>> +
> >>>> +    CPU_FOREACH(cs) {
> >>>> +        PowerPCCPU *cpu = POWERPC_CPU(cs);
> >>>> +        CPUPPCState *env = &cpu->env;
> >>>> +
> >>>> +        if (env->spr_cb[SPR_PIR].default_value == pir) {
> >>>> +            return cpu;
> >>>> +        }
> >>>> +    }
> >>>> +
> >>>> +    return NULL;
> >>>> +}
> >>>> +
> >>>> +static ICPState *pnv_icp_get(XICSFabric *xi, int pir)
> >>>> +{
> >>>> +    PnvMachineState *pnv = POWERNV_MACHINE(xi);
> >>>> +    PowerPCCPU *cpu = ppc_get_vcpu_by_pir(pir);
> >>>> +
> >>>> +    if (!cpu) {
> >>>> +        return NULL;
> >>>> +    }
> >>>> +
> >>>> +    assert(cpu->parent_obj.cpu_index < pnv->nr_servers);
> >>>> +    return ICP(&pnv->icps[cpu->parent_obj.cpu_index]);
> >>>
> >>> Should use CPU() instead of parent_obj here.
> >>
> >> OK. I might just remove the array though.
> >>
> >> Thanks,
> >>
> >> C.
> >>
> >>
> >>>> +}
> >>>> +
> >>>> +static void pnv_pic_print_info(InterruptStatsProvider *obj,
> >>>> +                               Monitor *mon)
> >>>> +{
> >>>> +    PnvMachineState *pnv = POWERNV_MACHINE(obj);
> >>>> +    int i;
> >>>> +
> >>>> +    for (i = 0; i < pnv->nr_servers; i++) {
> >>>> +        icp_pic_print_info(ICP(&pnv->icps[i]), mon);
> >>>> +    }
> >>>> +
> >>>> +    for (i = 0; i < pnv->num_chips; i++) {
> >>>> +        /* place holder */
> >>>> +    }
> >>>> +}
> >>>> +
> >>>>  static void pnv_get_num_chips(Object *obj, Visitor *v, const char *name,
> >>>>                                void *opaque, Error **errp)
> >>>>  {
> >>>> @@ -787,6 +872,8 @@ static void 
> >>>> powernv_machine_class_props_init(ObjectClass *oc)
> >>>>  static void powernv_machine_class_init(ObjectClass *oc, void *data)
> >>>>  {
> >>>>      MachineClass *mc = MACHINE_CLASS(oc);
> >>>> +    XICSFabricClass *xic = XICS_FABRIC_CLASS(oc);
> >>>> +    InterruptStatsProviderClass *ispc = 
> >>>> INTERRUPT_STATS_PROVIDER_CLASS(oc);
> >>>>  
> >>>>      mc->desc = "IBM PowerNV (Non-Virtualized)";
> >>>>      mc->init = ppc_powernv_init;
> >>>> @@ -797,6 +884,10 @@ static void powernv_machine_class_init(ObjectClass 
> >>>> *oc, void *data)
> >>>>      mc->no_parallel = 1;
> >>>>      mc->default_boot_order = NULL;
> >>>>      mc->default_ram_size = 1 * G_BYTE;
> >>>> +    xic->icp_get = pnv_icp_get;
> >>>> +    xic->ics_get = pnv_ics_get;
> >>>> +    xic->ics_resend = pnv_ics_resend;
> >>>> +    ispc->print_info = pnv_pic_print_info;
> >>>>  
> >>>>      powernv_machine_class_props_init(oc);
> >>>>  }
> >>>> @@ -807,6 +898,11 @@ static const TypeInfo powernv_machine_info = {
> >>>>      .instance_size = sizeof(PnvMachineState),
> >>>>      .instance_init = powernv_machine_initfn,
> >>>>      .class_init    = powernv_machine_class_init,
> >>>> +    .interfaces = (InterfaceInfo[]) {
> >>>> +        { TYPE_XICS_FABRIC },
> >>>> +        { TYPE_INTERRUPT_STATS_PROVIDER },
> >>>> +        { },
> >>>> +    },
> >>>>  };
> >>>>  
> >>>>  static void powernv_machine_register_types(void)
> >>>> diff --git a/include/hw/ppc/pnv.h b/include/hw/ppc/pnv.h
> >>>> index df98a72006e4..1ca197d2ec83 100644
> >>>> --- a/include/hw/ppc/pnv.h
> >>>> +++ b/include/hw/ppc/pnv.h
> >>>> @@ -22,6 +22,7 @@
> >>>>  #include "hw/boards.h"
> >>>>  #include "hw/sysbus.h"
> >>>>  #include "hw/ppc/pnv_lpc.h"
> >>>> +#include "hw/ppc/xics.h"
> >>>>  
> >>>>  #define TYPE_PNV_CHIP "powernv-chip"
> >>>>  #define PNV_CHIP(obj) OBJECT_CHECK(PnvChip, (obj), TYPE_PNV_CHIP)
> >>>> @@ -114,6 +115,8 @@ typedef struct PnvMachineState {
> >>>>      PnvChip      **chips;
> >>>>  
> >>>>      ISABus       *isa_bus;
> >>>> +    PnvICPState  *icps;
> >>>> +    uint32_t     nr_servers;
> >>>>  } PnvMachineState;
> >>>>  
> >>>>  #define PNV_FDT_ADDR          0x01000000
> >>>
> >>
> > 
> 

-- 
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]