perf/x86/intel/uncore: Support MMIO type uncore blocks

A new MMIO type uncore box is introduced on Snow Ridge server. The
counters of MMIO type uncore box can only be accessed by MMIO.

Add a new uncore type, uncore_mmio_uncores, for MMIO type uncore blocks.

Support MMIO type uncore blocks in CPU hot plug. The MMIO space has to
be map/unmap for the first/last CPU. The context also need to be
migrated if the bind CPU changes.

Add mmio_init() to init and register PMUs for MMIO type uncore blocks.

Add a helper to calculate the box_ctl address.

The helpers which calculate ctl/ctr can be shared with PCI type uncore
blocks.

Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: acme@kernel.org
Cc: eranian@google.com
Link: https://lkml.kernel.org/r/1556672028-119221-5-git-send-email-kan.liang@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
Kan Liang 2019-04-30 17:53:46 -07:00 коммит произвёл Ingo Molnar
Родитель c8872d90e0
Коммит 3da04b8a00
2 изменённых файлов: 60 добавлений и 12 удалений

Просмотреть файл

@ -8,6 +8,7 @@
static struct intel_uncore_type *empty_uncore[] = { NULL, }; static struct intel_uncore_type *empty_uncore[] = { NULL, };
struct intel_uncore_type **uncore_msr_uncores = empty_uncore; struct intel_uncore_type **uncore_msr_uncores = empty_uncore;
struct intel_uncore_type **uncore_pci_uncores = empty_uncore; struct intel_uncore_type **uncore_pci_uncores = empty_uncore;
struct intel_uncore_type **uncore_mmio_uncores = empty_uncore;
static bool pcidrv_registered; static bool pcidrv_registered;
struct pci_driver *uncore_pci_driver; struct pci_driver *uncore_pci_driver;
@ -1178,12 +1179,14 @@ static int uncore_event_cpu_offline(unsigned int cpu)
target = -1; target = -1;
uncore_change_context(uncore_msr_uncores, cpu, target); uncore_change_context(uncore_msr_uncores, cpu, target);
uncore_change_context(uncore_mmio_uncores, cpu, target);
uncore_change_context(uncore_pci_uncores, cpu, target); uncore_change_context(uncore_pci_uncores, cpu, target);
unref: unref:
/* Clear the references */ /* Clear the references */
die = topology_logical_die_id(cpu); die = topology_logical_die_id(cpu);
uncore_box_unref(uncore_msr_uncores, die); uncore_box_unref(uncore_msr_uncores, die);
uncore_box_unref(uncore_mmio_uncores, die);
return 0; return 0;
} }
@ -1252,12 +1255,13 @@ static int uncore_box_ref(struct intel_uncore_type **types,
static int uncore_event_cpu_online(unsigned int cpu) static int uncore_event_cpu_online(unsigned int cpu)
{ {
int ret, die, target; int die, target, msr_ret, mmio_ret;
die = topology_logical_die_id(cpu); die = topology_logical_die_id(cpu);
ret = uncore_box_ref(uncore_msr_uncores, die, cpu); msr_ret = uncore_box_ref(uncore_msr_uncores, die, cpu);
if (ret) mmio_ret = uncore_box_ref(uncore_mmio_uncores, die, cpu);
return ret; if (msr_ret && mmio_ret)
return -ENOMEM;
/* /*
* Check if there is an online cpu in the package * Check if there is an online cpu in the package
@ -1269,7 +1273,10 @@ static int uncore_event_cpu_online(unsigned int cpu)
cpumask_set_cpu(cpu, &uncore_cpu_mask); cpumask_set_cpu(cpu, &uncore_cpu_mask);
if (!msr_ret)
uncore_change_context(uncore_msr_uncores, -1, cpu); uncore_change_context(uncore_msr_uncores, -1, cpu);
if (!mmio_ret)
uncore_change_context(uncore_mmio_uncores, -1, cpu);
uncore_change_context(uncore_pci_uncores, -1, cpu); uncore_change_context(uncore_pci_uncores, -1, cpu);
return 0; return 0;
} }
@ -1317,12 +1324,35 @@ err:
return ret; return ret;
} }
static int __init uncore_mmio_init(void)
{
struct intel_uncore_type **types = uncore_mmio_uncores;
int ret;
ret = uncore_types_init(types, true);
if (ret)
goto err;
for (; *types; types++) {
ret = type_pmu_register(*types);
if (ret)
goto err;
}
return 0;
err:
uncore_types_exit(uncore_mmio_uncores);
uncore_mmio_uncores = empty_uncore;
return ret;
}
#define X86_UNCORE_MODEL_MATCH(model, init) \ #define X86_UNCORE_MODEL_MATCH(model, init) \
{ X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&init } { X86_VENDOR_INTEL, 6, model, X86_FEATURE_ANY, (unsigned long)&init }
struct intel_uncore_init_fun { struct intel_uncore_init_fun {
void (*cpu_init)(void); void (*cpu_init)(void);
int (*pci_init)(void); int (*pci_init)(void);
void (*mmio_init)(void);
}; };
static const struct intel_uncore_init_fun nhm_uncore_init __initconst = { static const struct intel_uncore_init_fun nhm_uncore_init __initconst = {
@ -1437,7 +1467,7 @@ static int __init intel_uncore_init(void)
{ {
const struct x86_cpu_id *id; const struct x86_cpu_id *id;
struct intel_uncore_init_fun *uncore_init; struct intel_uncore_init_fun *uncore_init;
int pret = 0, cret = 0, ret; int pret = 0, cret = 0, mret = 0, ret;
id = x86_match_cpu(intel_uncore_match); id = x86_match_cpu(intel_uncore_match);
if (!id) if (!id)
@ -1460,7 +1490,12 @@ static int __init intel_uncore_init(void)
cret = uncore_cpu_init(); cret = uncore_cpu_init();
} }
if (cret && pret) if (uncore_init->mmio_init) {
uncore_init->mmio_init();
mret = uncore_mmio_init();
}
if (cret && pret && mret)
return -ENODEV; return -ENODEV;
/* Install hotplug callbacks to setup the targets for each package */ /* Install hotplug callbacks to setup the targets for each package */
@ -1474,6 +1509,7 @@ static int __init intel_uncore_init(void)
err: err:
uncore_types_exit(uncore_msr_uncores); uncore_types_exit(uncore_msr_uncores);
uncore_types_exit(uncore_mmio_uncores);
uncore_pci_exit(); uncore_pci_exit();
return ret; return ret;
} }
@ -1483,6 +1519,7 @@ static void __exit intel_uncore_exit(void)
{ {
cpuhp_remove_state(CPUHP_AP_PERF_X86_UNCORE_ONLINE); cpuhp_remove_state(CPUHP_AP_PERF_X86_UNCORE_ONLINE);
uncore_types_exit(uncore_msr_uncores); uncore_types_exit(uncore_msr_uncores);
uncore_types_exit(uncore_mmio_uncores);
uncore_pci_exit(); uncore_pci_exit();
} }
module_exit(intel_uncore_exit); module_exit(intel_uncore_exit);

Просмотреть файл

@ -56,7 +56,10 @@ struct intel_uncore_type {
unsigned fixed_ctr; unsigned fixed_ctr;
unsigned fixed_ctl; unsigned fixed_ctl;
unsigned box_ctl; unsigned box_ctl;
union {
unsigned msr_offset; unsigned msr_offset;
unsigned mmio_offset;
};
unsigned num_shared_regs:8; unsigned num_shared_regs:8;
unsigned single_fixed:1; unsigned single_fixed:1;
unsigned pair_ctr_ctl:1; unsigned pair_ctr_ctl:1;
@ -190,6 +193,13 @@ static inline bool uncore_pmc_freerunning(int idx)
return idx == UNCORE_PMC_IDX_FREERUNNING; return idx == UNCORE_PMC_IDX_FREERUNNING;
} }
static inline
unsigned int uncore_mmio_box_ctl(struct intel_uncore_box *box)
{
return box->pmu->type->box_ctl +
box->pmu->type->mmio_offset * box->pmu->pmu_idx;
}
static inline unsigned uncore_pci_box_ctl(struct intel_uncore_box *box) static inline unsigned uncore_pci_box_ctl(struct intel_uncore_box *box)
{ {
return box->pmu->type->box_ctl; return box->pmu->type->box_ctl;
@ -330,7 +340,7 @@ unsigned uncore_msr_perf_ctr(struct intel_uncore_box *box, int idx)
static inline static inline
unsigned uncore_fixed_ctl(struct intel_uncore_box *box) unsigned uncore_fixed_ctl(struct intel_uncore_box *box)
{ {
if (box->pci_dev) if (box->pci_dev || box->io_addr)
return uncore_pci_fixed_ctl(box); return uncore_pci_fixed_ctl(box);
else else
return uncore_msr_fixed_ctl(box); return uncore_msr_fixed_ctl(box);
@ -339,7 +349,7 @@ unsigned uncore_fixed_ctl(struct intel_uncore_box *box)
static inline static inline
unsigned uncore_fixed_ctr(struct intel_uncore_box *box) unsigned uncore_fixed_ctr(struct intel_uncore_box *box)
{ {
if (box->pci_dev) if (box->pci_dev || box->io_addr)
return uncore_pci_fixed_ctr(box); return uncore_pci_fixed_ctr(box);
else else
return uncore_msr_fixed_ctr(box); return uncore_msr_fixed_ctr(box);
@ -348,7 +358,7 @@ unsigned uncore_fixed_ctr(struct intel_uncore_box *box)
static inline static inline
unsigned uncore_event_ctl(struct intel_uncore_box *box, int idx) unsigned uncore_event_ctl(struct intel_uncore_box *box, int idx)
{ {
if (box->pci_dev) if (box->pci_dev || box->io_addr)
return uncore_pci_event_ctl(box, idx); return uncore_pci_event_ctl(box, idx);
else else
return uncore_msr_event_ctl(box, idx); return uncore_msr_event_ctl(box, idx);
@ -357,7 +367,7 @@ unsigned uncore_event_ctl(struct intel_uncore_box *box, int idx)
static inline static inline
unsigned uncore_perf_ctr(struct intel_uncore_box *box, int idx) unsigned uncore_perf_ctr(struct intel_uncore_box *box, int idx)
{ {
if (box->pci_dev) if (box->pci_dev || box->io_addr)
return uncore_pci_perf_ctr(box, idx); return uncore_pci_perf_ctr(box, idx);
else else
return uncore_msr_perf_ctr(box, idx); return uncore_msr_perf_ctr(box, idx);
@ -507,6 +517,7 @@ u64 uncore_shared_reg_config(struct intel_uncore_box *box, int idx);
extern struct intel_uncore_type **uncore_msr_uncores; extern struct intel_uncore_type **uncore_msr_uncores;
extern struct intel_uncore_type **uncore_pci_uncores; extern struct intel_uncore_type **uncore_pci_uncores;
extern struct intel_uncore_type **uncore_mmio_uncores;
extern struct pci_driver *uncore_pci_driver; extern struct pci_driver *uncore_pci_driver;
extern raw_spinlock_t pci2phy_map_lock; extern raw_spinlock_t pci2phy_map_lock;
extern struct list_head pci2phy_map_head; extern struct list_head pci2phy_map_head;