On Fri, Oct 11, 2019 at 04:59:37PM +0000, Moger, Babu wrote: > > On 10/10/19 10:59 PM, Eduardo Habkost wrote: > > On Fri, Sep 06, 2019 at 07:13:09PM +0000, Moger, Babu wrote: > >> Adds new epyc property in PCMachineState and also in MachineState. > >> This property will be used to initialize the mode specific handlers > >> to generate apic ids. > >> > >> Signed-off-by: Babu Moger <babu.mo...@amd.com> > >> --- > > [...] > >> diff --git a/include/hw/boards.h b/include/hw/boards.h > >> index 12eb5032a5..0001d42e50 100644 > >> --- a/include/hw/boards.h > >> +++ b/include/hw/boards.h > >> @@ -299,6 +299,8 @@ struct MachineState { > >> AccelState *accelerator; > >> CPUArchIdList *possible_cpus; > >> CpuTopology smp; > >> + bool epyc; > >> + > > > > This won't scale at all when we start adding new CPU models with > > different topology constraints. > > Yes, I knew. This could cause scaling issues. Let me see if we could > do anything different. > > > > > I still have hope we can avoid having separate set of topology ID > > functions (see my reply to "hw/386: Add new epyc mode topology > > Yes. That was my hope too. Let me think thru this bit more. I will come > back on this.
If you don't manage to use a common function in the next version, it's not a big deal. My main request is to make the calculations easier to follow (e.g. avoiding any expression with more than two terms, and always using an explicit "_per_*" suffix in all variables and constants). There's one possible problem I didn't realize yesterday: we might need a mechanism to force a field width to be larger than apicid_bitwidth_for_count(number_of_ids) (e.g. having 2 bits for core ID even if there's only 1 or 2 cores per CCX). Maybe the solution is to add optional field width parameters to X86CPUTopoInfo. Then we could redefine the width functions like this: static inline unsigned apicid_core_width(X86CPUTopoInfo *topo) { return MAX(apicid_bitwidth_for_count(topo->nr_cores), topo->min_core_bits); } Maybe we could replace the collection of fields with arrays to make all calculations generic. Untested example: enum TopoField { TOPO_FIELD_THREADS = 0, TOPO_FIELD_CORES, TOPO_FIELD_CCXS, /* AMD */ TOPO_FIELD_DIES = TOPO_FIELD_CCX, /* Intel */ TOPO_FIELD_NODES, TOPO_FIELD_PKG, MAX_TOPO_FIELD, }; struct TopoFieldDefinition { /* Number of IDs at this level */ unsigned count; /* Minimum number of APIC ID bits for this level */ unsigned min_width; }; struct X86CPUTopoInfo { TopoFieldDefinition fields[MAX_TOPO_FIELD]; }; struct X85CPUTopoIDs { unsigned ids[MAX_TOPO_FIELD]; }; static inline unsigned apicid_field_width(const X86CPUTopoInfo *topo, TopoField field) { TopoFieldDefinition *def = &topo->fields[field]; return MAX(apicid_bitwidth_for_count(def->count), def->min_width); } static inline unsigned apicid_field_offset(const X86CPUTopoInfo *topo, TopoField field) { if (field == 0) { return 0; } return apicid_field_offset(topo, field - 1) + apic_id_field_width(topo, field - 1); } static inline apic_id_t apicid_from_topo_ids(const X86CPUTopoInfo *topo, const X86CPUTopoIDs *ids) { TopoField field; apic_id_t r = 0; for (field = 0; l < MAX_TOPO_FIELD; l++) { unsigned offset = apicid_field_offset(topo, field); unsigned width = apicid_field_width(topo, field); assert(apicid_bitwidth_for_count(ids->ids[field] + 1) < apicid_field_width(topo, field)); r = deposit64(r, offset, width, ids->ids[field]; } return r; } static inline void x86_topo_ids_from_apicid(apic_id_t apicid, const X86CPUTopoInfo *topo, X86CPUTopoIDs *ids) { TopoField field; for (field = 0; l < MAX_TOPO_FIELD; l++) { unsigned offset = apicid_field_offset(topo, field); unsigned width = apicid_field_width(topo, field); ids->ids[field] = extract64(apicid, offset, width); } } > > > > decoding functions"). But if we really have to create separate > > functions, we can make them part of the CPU model table, not a > > boolean machine property. > > -- Eduardo