Commit eda807f0 authored by Kan Liang's avatar Kan Liang Committed by Yunying Sun
Browse files

perf/x86/uncore: Apply the unit control RB tree to MSR uncore units

mainline inclusion
from mainline-v6.11-rc1
commit b1d9ea2e1ca44987c8409cc628dfb0c84e93dce9
category: feature
bugzilla: https://gitee.com/openeuler/intel-kernel/issues/IAGJQ7
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=b1d9ea2e1ca44987c8409cc628dfb0c84e93dce9



-------------------------------------

The unit control RB tree has the unit control and unit ID information
for all the MSR units. Use them to replace the box_ctl and
uncore_msr_box_ctl() to get an accurate unit control address for MSR
uncore units.

Add intel_generic_uncore_assign_hw_event(), which utilizes the accurate
unit control address from the unit control RB tree to calculate the
config_base and event_base.

The unit id related information should be retrieved from the unit
control RB tree as well.

Intel-SIG: commit b1d9ea2e1ca4 perf/x86/uncore: Apply the unit control RB tree to MSR uncore units
Backport SPR/EMR CXL and HBM perfmon support to kernel v5.10

Signed-off-by: default avatarKan Liang <kan.liang@linux.intel.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Tested-by: default avatarYunying Sun <yunying.sun@intel.com>
Link: https://lore.kernel.org/r/20240614134631.1092359-6-kan.liang@linux.intel.com


Signed-off-by: default avatarYunying Sun <yunying.sun@intel.com>
parent ef1ce8e9
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -251,6 +251,9 @@ static void uncore_assign_hw_event(struct intel_uncore_box *box,
		return;
	}

	if (intel_generic_uncore_assign_hw_event(event, box))
		return;

	hwc->config_base = uncore_event_ctl(box, hwc->idx);
	hwc->event_base  = uncore_perf_ctr(box, hwc->idx);
}
+44 −5
Original line number Diff line number Diff line
@@ -491,19 +491,31 @@ static const struct attribute_group generic_uncore_format_group = {
	.attrs = generic_uncore_formats_attr,
};

static u64 intel_generic_uncore_box_ctl(struct intel_uncore_box *box)
{
	struct intel_uncore_discovery_unit *unit;

	unit = intel_uncore_find_discovery_unit(box->pmu->type->boxes,
						-1, box->pmu->pmu_idx);
	if (WARN_ON_ONCE(!unit))
		return 0;

	return unit->addr;
}

void intel_generic_uncore_msr_init_box(struct intel_uncore_box *box)
{
	wrmsrl(uncore_msr_box_ctl(box), GENERIC_PMON_BOX_CTL_INT);
	wrmsrl(intel_generic_uncore_box_ctl(box), GENERIC_PMON_BOX_CTL_INT);
}

void intel_generic_uncore_msr_disable_box(struct intel_uncore_box *box)
{
	wrmsrl(uncore_msr_box_ctl(box), GENERIC_PMON_BOX_CTL_FRZ);
	wrmsrl(intel_generic_uncore_box_ctl(box), GENERIC_PMON_BOX_CTL_FRZ);
}

void intel_generic_uncore_msr_enable_box(struct intel_uncore_box *box)
{
	wrmsrl(uncore_msr_box_ctl(box), 0);
	wrmsrl(intel_generic_uncore_box_ctl(box), 0);
}

static void intel_generic_uncore_msr_enable_event(struct intel_uncore_box *box,
@@ -531,6 +543,31 @@ static struct intel_uncore_ops generic_uncore_msr_ops = {
	.read_counter		= uncore_msr_read_counter,
};

bool intel_generic_uncore_assign_hw_event(struct perf_event *event,
					  struct intel_uncore_box *box)
{
	struct hw_perf_event *hwc = &event->hw;
	u64 box_ctl;

	if (!box->pmu->type->boxes)
		return false;

	if (box->pci_dev || box->io_addr) {
		hwc->config_base = uncore_pci_event_ctl(box, hwc->idx);
		hwc->event_base  = uncore_pci_perf_ctr(box, hwc->idx);
		return true;
	}

	box_ctl = intel_generic_uncore_box_ctl(box);
	if (!box_ctl)
		return false;

	hwc->config_base = box_ctl + box->pmu->type->event_ctl + hwc->idx;
	hwc->event_base  = box_ctl + box->pmu->type->perf_ctr + hwc->idx;

	return true;
}

void intel_generic_uncore_pci_init_box(struct intel_uncore_box *box)
{
	struct pci_dev *pdev = box->pci_dev;
@@ -689,10 +726,12 @@ static bool uncore_update_uncore_type(enum uncore_access_type type_id,
	switch (type_id) {
	case UNCORE_ACCESS_MSR:
		uncore->ops = &generic_uncore_msr_ops;
		uncore->perf_ctr = (unsigned int)type->box_ctrl + type->ctr_offset;
		uncore->event_ctl = (unsigned int)type->box_ctrl + type->ctl_offset;
		uncore->perf_ctr = (unsigned int)type->ctr_offset;
		uncore->event_ctl = (unsigned int)type->ctl_offset;
		uncore->box_ctl = (unsigned int)type->box_ctrl;
		uncore->msr_offsets = type->box_offset;
		uncore->boxes = &type->units;
		uncore->num_boxes = type->num_units;
		break;
	case UNCORE_ACCESS_PCI:
		uncore->ops = &generic_uncore_pci_ops;
+2 −0
Original line number Diff line number Diff line
@@ -171,3 +171,5 @@ intel_uncore_generic_init_uncores(enum uncore_access_type type_id, int num_extra

int intel_uncore_find_discovery_unit_id(struct rb_root *units, int die,
					unsigned int pmu_idx);
bool intel_generic_uncore_assign_hw_event(struct perf_event *event,
					  struct intel_uncore_box *box);
+10 −6
Original line number Diff line number Diff line
@@ -5441,10 +5441,11 @@ static int spr_cha_hw_config(struct intel_uncore_box *box, struct perf_event *ev
	struct hw_perf_event_extra *reg1 = &event->hw.extra_reg;
	bool tie_en = !!(event->hw.config & SPR_CHA_PMON_CTL_TID_EN);
	struct intel_uncore_type *type = box->pmu->type;
	int id = intel_uncore_find_discovery_unit_id(type->boxes, -1, box->pmu->pmu_idx);

	if (tie_en) {
		reg1->reg = SPR_C0_MSR_PMON_BOX_FILTER0 +
			    HSWEP_CBO_MSR_OFFSET * type->box_ids[box->pmu->pmu_idx];
			    HSWEP_CBO_MSR_OFFSET * id;
		reg1->config = event->attr.config1 & SPR_CHA_PMON_BOX_FILTER_TID;
		reg1->idx = 0;
	}
@@ -5916,18 +5917,21 @@ uncore_find_type_by_id(struct intel_uncore_type **types, int type_id)
static int uncore_type_max_boxes(struct intel_uncore_type **types,
				 int type_id)
{
	struct intel_uncore_discovery_unit *unit;
	struct intel_uncore_type *type;
	int i, max = 0;
	struct rb_node *node;
	int max = 0;

	type = uncore_find_type_by_id(types, type_id);
	if (!type)
		return 0;

	for (i = 0; i < type->num_boxes; i++) {
		if (type->box_ids[i] > max)
			max = type->box_ids[i];
	}
	for (node = rb_first(type->boxes); node; node = rb_next(node)) {
		unit = rb_entry(node, struct intel_uncore_discovery_unit, node);

		if (unit->id > max)
			max = unit->id;
	}
	return max + 1;
}