Skip to content

[Deepin-Kernel-SIG] [linux 6.6-y] [Upstream] [Intel] Intel: Backport SPR/EMR CXL and HBM perfmon support to kernel 6.6 #841

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Jun 16, 2025

Conversation

Avenger-285714
Copy link
Collaborator

@Avenger-285714 Avenger-285714 commented Jun 2, 2025

bugzilla: https://bugzilla.openanolis.cn/show_bug.cgi?id=9608

Some unknown uncore PMON types(like /sys/devices/uncore_type__) can be found in both SPR(Sapphire Rapids, 4th Gen Xeon) and EMR(Emerald Rapids, 5th Gen Xeon) that has built-in HBM or CXL devices available.

The unknown PMON types are HBM and CXL PMON. Except for the name, the other information regarding the HBM and CXL PMON counters can be retrieved via the discovery table. Add them into the uncores tables for SPR and EMR.

The first 7 patches update the generic support of the discovery table. The last patch enables the HBM and CXL PMON uncore counters for SPR and EMR.

Upstream commits from v6.11-rc1:
f8a86a9 perf/x86/intel/uncore: Support HBM and CXL PMON counters
15a4bd5 perf/x86/uncore: Cleanup unused unit structure
f76a842 perf/x86/uncore: Apply the unit control RB tree to PCI uncore units
b1d9ea2 perf/x86/uncore: Apply the unit control RB tree to MSR uncore units
80580da perf/x86/uncore: Apply the unit control RB tree to MMIO uncore units
585463f perf/x86/uncore: Retrieve the unit ID from the unit control RB tree
c74443d perf/x86/uncore: Support per PMU cpumask
0007f39 perf/x86/uncore: Save the unit control address of all units

Test:
Before backport, on SPR or EMR that has HBM or CXL devices, there're "uncore_type_" devices available under "/sys/devices/".
After backport, on SPR or EMR that has HBM or CXL devices, there're "uncore_hbm_x" and/or "uncore{cxlcm,cxldp}_x" devices under "/sys/devices/", and cxl(uncore_cxlcm/cxldp) and/or hbm(cxl_hbm) perf events work fine with command like below:

perf stat -e uncore_cxlcm/event=0x1,umask=0x2/,uncore_cxlcm/event=0x1,umask=0x2/,uncore_cxlcm/event=0x1,umask=0x2/,uncore_cxlcm/event=0x1,umask=0x2/ -a --no-merge sleep 1
For cxldp, use event "uncore_cxldp/event=0x1,umask=0x1/". For hbm, use event "uncore_hbm/event=0x1,umask=0x0".

Note:

  1. The backported patches have no deviations from the mainline upstream version.
  2. The backported patches have been validated on Intel SPR/EMR servers.
  3. The patch set only contains CXL/HBM perfmon support for SPR/EMR. Next Xeon Granite Rapids support is not included, and will be supported later with separated patch set.

Link: https://gitee.com/anolis/cloud-kernel/pulls/3586

Summary by Sourcery

Backport upstream perf/x86 Intel uncore discovery refactoring together with HBM and CXL perfmon support for Sapphire Rapids (SPR) and Emerald Rapids (EMR) to Linux 6.6, enabling new uncore_hbm, uncore_cxlcm, and uncore_cxldp devices and perf events.

New Features:

  • Enable HBM and CXL PMON counters for SPR and EMR uncore blocks.
  • Add new uncore types: cxlcm, cxldp, and hbm for SPR and EMR platforms.

Enhancements:

  • Refactor uncore discovery to store units in a red-black tree instead of fixed arrays.
  • Unify generic MSR, PCI and MMIO uncore operations to use discovery-based unit control addresses.
  • Update PMU setup to track per-PMU CPU masks and support dynamic unit cleanup callbacks.

Tests:

  • Validate on Intel SPR/EMR servers that new uncore_hbm, uncore_cxlcm, and uncore_cxldp devices appear under /sys/devices and perf stat events execute correctly.

Kan Liang added 8 commits June 2, 2025 22:19
ANBZ: #9608

commit 0007f39 upstream.

The unit control address of some CXL units may be wrongly calculated
under some configuration on a EMR machine.

The current implementation only saves the unit control address of the
units from the first die, and the first unit of the rest of dies. Perf
assumed that the units from the other dies have the same offset as the
first die. So the unit control address of the rest of the units can be
calculated. However, the assumption is wrong, especially for the CXL
units.

Introduce an RB tree for each uncore type to save the unit control
address and three kinds of ID information (unit ID, PMU ID, and die ID)
for all units.
The unit ID is a physical ID of a unit.
The PMU ID is a logical ID assigned to a unit. The logical IDs start
from 0 and must be contiguous. The physical ID and the logical ID are
1:1 mapping. The units with the same physical ID in different dies share
the same PMU.
The die ID indicates which die a unit belongs to.

The RB tree can be searched by two different keys (unit ID or PMU ID +
die ID). During the RB tree setup, the unit ID is used as a key to look
up the RB tree. The perf can create/assign a proper PMU ID to the unit.
Later, after the RB tree is setup, PMU ID + die ID is used as a key to
look up the RB tree to fill the cpumask of a PMU. It's used more
frequently, so PMU ID + die ID is compared in the unit_less().
The uncore_find_unit() has to be O(N). But the RB tree setup only occurs
once during the driver load time. It should be acceptable.

Compared with the current implementation, more space is required to save
the information of all units. The extra size should be acceptable.
For example, on EMR, there are 221 units at most. For a 2-socket machine,
the extra space is ~6KB at most.

Intel-SIG: commit 0007f39 perf/x86/uncore: Save the unit control address of all units
Backport SPR/EMR HBM and CXL PMON support to kernel v6.6

Signed-off-by: Kan Liang <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Yunying Sun: amend commit log ]
Signed-off-by: Yunying Sun <[email protected]>
ANBZ: #9608

commit c74443d upstream.

The cpumask of some uncore units, e.g., CXL uncore units, may be wrong
under some configurations. Perf may access an uncore counter of a
non-existent uncore unit.

The uncore driver assumes that all uncore units are symmetric among
dies. A global cpumask is shared among all uncore PMUs. However, some
CXL uncore units may only be available on some dies.

A per PMU cpumask is introduced to track the CPU mask of this PMU.
The driver searches the unit control RB tree to check whether the PMU is
available on a given die, and updates the per PMU cpumask accordingly.

Intel-SIG: commit c74443d perf/x86/uncore: Support per PMU cpumask
Backport SPR/EMR HBM and CXL PMON support to kernel v6.6

Signed-off-by: Kan Liang <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Tested-by: Yunying Sun <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Yunying Sun: amend commit log ]
Signed-off-by: Yunying Sun <[email protected]>
ANBZ: #9608

commit 585463f upstream.

The box_ids only save the unit ID for the first die. If a unit, e.g., a
CXL unit, doesn't exist in the first die. The unit ID cannot be
retrieved.

The unit control RB tree also stores the unit ID information.
Retrieve the unit ID from the unit control RB tree

Intel-SIG: commit 585463f perf/x86/uncore: Retrieve the unit ID from the unit control RB tree
Backport SPR/EMR HBM and CXL PMON support to kernel v6.6

Signed-off-by: Kan Liang <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Tested-by: Yunying Sun <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Yunying Sun: amend commit log ]
Signed-off-by: Yunying Sun <[email protected]>
ANBZ: #9608

commit 80580da upstream.

The unit control RB tree has the unit control and unit ID information
for all the units. Use it to replace the box_ctls/mmio_offsets to get
an accurate unit control address for MMIO uncore units.

Intel-SIG: commit 80580da perf/x86/uncore: Apply the unit control RB tree to MMIO uncore units
Backport SPR/EMR HBM and CXL PMON support to kernel v6.6

Signed-off-by: Kan Liang <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Tested-by: Yunying Sun <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Yunying Sun: amend commit log ]
Signed-off-by: Yunying Sun <[email protected]>
ANBZ: #9608

commit b1d9ea2 upstream.

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 b1d9ea2 perf/x86/uncore: Apply the unit control RB tree to MSR uncore units
Backport SPR/EMR HBM and CXL PMON support to kernel v6.6

Signed-off-by: Kan Liang <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Tested-by: Yunying Sun <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Yunying Sun: amend commit log ]
Signed-off-by: Yunying Sun <[email protected]>
ANBZ: #9608

commit f76a842 upstream.

The unit control RB tree has the unit control and unit ID information
for all the PCI units. Use them to replace the box_ctls/pci_offsets to
get an accurate unit control address for PCI uncore units.

The UPI/M3UPI units in the discovery table are ignored. Please see the
commit 65248a9 ("perf/x86/uncore: Add a quirk for UPI on SPR").
Manually allocate a unit control RB tree for UPI/M3UPI.
Add cleanup_extra_boxes to release such manual allocation.

Intel-SIG: commit f76a842 perf/x86/uncore: Apply the unit control RB tree to PCI uncore units
Backport SPR/EMR HBM and CXL PMON support to kernel v6.6

Signed-off-by: Kan Liang <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Tested-by: Yunying Sun <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Yunying Sun: amend commit log ]
Signed-off-by: Yunying Sun <[email protected]>
ANBZ: #9608

commit 15a4bd5 upstream.

The unit control and ID information are retrieved from the unit control
RB tree. No one uses the old structure anymore. Remove them.

Intel-SIG: commit 15a4bd5 perf/x86/uncore: Cleanup unused unit structure
Backport SPR/EMR HBM and CXL PMON support to kernel v6.6

Signed-off-by: Kan Liang <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Tested-by: Yunying Sun <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Yunying Sun: amend commit log ]
Signed-off-by: Yunying Sun <[email protected]>
ANBZ: #9608

commit f8a86a9 upstream.

Unknown uncore PMON types can be found in both SPR and EMR with HBM or
CXL.

 $ls /sys/devices/ | grep type
 uncore_type_12_16
 uncore_type_12_18
 uncore_type_12_2
 uncore_type_12_4
 uncore_type_12_6
 uncore_type_12_8
 uncore_type_13_17
 uncore_type_13_19
 uncore_type_13_3
 uncore_type_13_5
 uncore_type_13_7
 uncore_type_13_9

The unknown PMON types are HBM and CXL PMON. Except for the name, the
other information regarding the HBM and CXL PMON counters can be
retrieved via the discovery table. Add them into the uncores tables for
SPR and EMR.

The event config registers for all CXL related units are 8-byte apart.
Add SPR_UNCORE_MMIO_OFFS8_COMMON_FORMAT to specially handle it.

Intel-SIG: commit f8a86a9 perf/x86/intel/uncore: Support HBM and CXL PMON counters
Backport SPR/EMR HBM and CXL PMON support to kernel v6.6

Signed-off-by: Kan Liang <[email protected]>
Signed-off-by: Peter Zijlstra (Intel) <[email protected]>
Tested-by: Yunying Sun <[email protected]>
Link: https://lore.kernel.org/r/[email protected]
[ Yunying Sun: amend commit log ]
Signed-off-by: Yunying Sun <[email protected]>
@Avenger-285714 Avenger-285714 requested a review from Copilot June 2, 2025 14:22
@deepin-ci-robot deepin-ci-robot requested a review from huangbibo June 2, 2025 14:22
@Avenger-285714 Avenger-285714 requested a review from opsiff June 2, 2025 14:23
Copy link

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Backport support for HBM and CXL perfmon counters on Intel SPR/EMR platforms into kernel 6.6, enhancing generic discovery table handling and integrating new uncore types.

  • Extend discovery-based unit management with rbtree structures and helper functions
  • Add CXL (cxlcm, cxldp) and HBM uncore types for SPR with MMIO ops
  • Update PMU init, event assignment, and cleanup to use discovery units

Reviewed Changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
arch/x86/events/intel/uncore_snbep.c Use discovery-based unit ID for CHA filter register calculation
arch/x86/events/intel/uncore_discovery.h Introduce intel_uncore_discovery_unit and discovery APIs
arch/x86/events/intel/uncore_discovery.c Implement rbtree-based unit discovery and management
arch/x86/events/intel/uncore.h Add boxes root and extra cleanup callbacks to uncore type
arch/x86/events/intel/uncore.c Integrate discovery-based box control in MSR/PCI/MMIO operations

@@ -5901,10 +5901,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);

Copy link
Preview

Copilot AI Jun 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

intel_uncore_find_discovery_unit_id may return -1 on failure; using this negative ID in offset calculations could result in invalid MSR accesses. Validate that id >= 0 before use and handle error cases appropriately.

Suggested change
if (id < 0)
return -EINVAL;

Copilot uses AI. Check for mistakes.

@@ -1502,7 +1523,7 @@ static void uncore_box_unref(struct intel_uncore_type **types, int id)
pmu = type->pmus;
for (i = 0; i < type->num_boxes; i++, pmu++) {
box = pmu->boxes[id];
if (box && atomic_dec_return(&box->refcnt) == 0)
if (box && box->cpu >= 0 && atomic_dec_return(&box->refcnt) == 0)
Copy link
Preview

Copilot AI Jun 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Restricting refcount decrement to boxes with cpu >= 0 may leave boxes with cpu < 0 unbalanced, causing resource leaks. Consider always decrementing the refcnt when unref is expected or ensuring that cpu is properly set before unref.

Suggested change
if (box && box->cpu >= 0 && atomic_dec_return(&box->refcnt) == 0)
if (box && atomic_dec_return(&box->refcnt) == 0)

Copilot uses AI. Check for mistakes.

Copy link

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @Avenger-285714 - I've reviewed your changes and they look great!

Here's what I looked at during the review
  • 🟡 General issues: 2 issues found
  • 🟢 Security: all looks good
  • 🟢 Testing: all looks good
  • 🟢 Complexity: all looks good
  • 🟢 Documentation: all looks good

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

type->box_ctrl_die = kcalloc(__uncore_max_dies, sizeof(u64), GFP_KERNEL);
if (!type->box_ctrl_die)
goto free_type;
type->units = RB_ROOT;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Missing initialization for num_units in discovery type

Please initialize type->num_units = 0 in add_uncore_discovery_type to prevent undefined behavior when using uncore_find_add_unit.

void intel_generic_uncore_mmio_init_box(struct intel_uncore_box *box)
{
u64 box_ctl = generic_uncore_mmio_box_ctl(box);
static struct intel_uncore_discovery_unit *unit;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Remove static from local discovery unit pointer

Using a static local variable here causes its value to persist and introduces thread-safety issues. Use a regular local variable to prevent stale pointers and unintended sharing.

@opsiff opsiff merged commit 7618412 into deepin-community:linux-6.6.y Jun 16, 2025
6 of 7 checks passed
@deepin-ci-robot
Copy link

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: opsiff

The full list of commands accepted by this bot can be found here.

The pull request process is described here

Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants