perf/x86/intel/uncore: Parse uncore discovery tables
A self-describing mechanism for the uncore PerfMon hardware has been
introduced with the latest Intel platforms. By reading through an MMIO
page worth of information, perf can 'discover' all the standard uncore
PerfMon registers in a machine.
The discovery mechanism relies on BIOS's support. With a proper BIOS,
a PCI device with the unique capability ID 0x23 can be found on each
die. Perf can retrieve the information of all available uncore PerfMons
from the device via MMIO. The information is composed of one global
discovery table and several unit discovery tables.
- The global discovery table includes global uncore information of the
die, e.g., the address of the global control register, the offset of
the global status register, the number of uncore units, the offset of
unit discovery tables, etc.
- The unit discovery table includes generic uncore unit information,
e.g., the access type, the counter width, the address of counters,
the address of the counter control, the unit ID, the unit type, etc.
The unit is also called "box" in the code.
Perf can provide basic uncore support based on this information
with the following patches.
To locate the PCI device with the discovery tables, check the generic
PCI ID first. If it doesn't match, go through the entire PCI device tree
and locate the device with the unique capability ID.
The uncore information is similar among dies. To save parsing time and
space, only completely parse and store the discovery tables on the first
die and the first box of each die. The parsed information is stored in
an
RB tree structure, intel_uncore_discovery_type. The size of the stored
discovery tables varies among platforms. It's around 4KB for a Sapphire
Rapids server.
If a BIOS doesn't support the 'discovery' mechanism, the uncore driver
will exit with -ENODEV. There is nothing changed.
Add a module parameter to disable the discovery feature. If a BIOS gets
the discovery tables wrong, users can have an option to disable the
feature. For the current patchset, the uncore driver will exit with
-ENODEV. In the future, it may fall back to the hardcode uncore driver
on a known platform.
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/1616003977-90612-2-git-send-email-kan.liang@linux.intel.com
2021-03-17 10:59:33 -07:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
|
|
|
|
|
|
|
/* Generic device ID of a discovery table device */
|
|
|
|
#define UNCORE_DISCOVERY_TABLE_DEVICE 0x09a7
|
|
|
|
/* Capability ID for a discovery table device */
|
|
|
|
#define UNCORE_EXT_CAP_ID_DISCOVERY 0x23
|
|
|
|
/* First DVSEC offset */
|
|
|
|
#define UNCORE_DISCOVERY_DVSEC_OFFSET 0x8
|
|
|
|
/* Mask of the supported discovery entry type */
|
|
|
|
#define UNCORE_DISCOVERY_DVSEC_ID_MASK 0xffff
|
|
|
|
/* PMON discovery entry type ID */
|
|
|
|
#define UNCORE_DISCOVERY_DVSEC_ID_PMON 0x1
|
|
|
|
/* Second DVSEC offset */
|
|
|
|
#define UNCORE_DISCOVERY_DVSEC2_OFFSET 0xc
|
|
|
|
/* Mask of the discovery table BAR offset */
|
|
|
|
#define UNCORE_DISCOVERY_DVSEC2_BIR_MASK 0x7
|
|
|
|
/* Discovery table BAR base offset */
|
|
|
|
#define UNCORE_DISCOVERY_BIR_BASE 0x10
|
|
|
|
/* Discovery table BAR step */
|
|
|
|
#define UNCORE_DISCOVERY_BIR_STEP 0x4
|
|
|
|
/* Global discovery table size */
|
|
|
|
#define UNCORE_DISCOVERY_GLOBAL_MAP_SIZE 0x20
|
|
|
|
|
2023-01-12 13:01:04 -07:00
|
|
|
#define UNCORE_DISCOVERY_PCI_DOMAIN_OFFSET 28
|
|
|
|
#define UNCORE_DISCOVERY_PCI_DOMAIN(data) \
|
|
|
|
((data >> UNCORE_DISCOVERY_PCI_DOMAIN_OFFSET) & 0x7)
|
|
|
|
#define UNCORE_DISCOVERY_PCI_BUS_OFFSET 20
|
|
|
|
#define UNCORE_DISCOVERY_PCI_BUS(data) \
|
|
|
|
((data >> UNCORE_DISCOVERY_PCI_BUS_OFFSET) & 0xff)
|
|
|
|
#define UNCORE_DISCOVERY_PCI_DEVFN_OFFSET 12
|
|
|
|
#define UNCORE_DISCOVERY_PCI_DEVFN(data) \
|
|
|
|
((data >> UNCORE_DISCOVERY_PCI_DEVFN_OFFSET) & 0xff)
|
2021-03-17 10:59:36 -07:00
|
|
|
#define UNCORE_DISCOVERY_PCI_BOX_CTRL(data) (data & 0xfff)
|
|
|
|
|
|
|
|
|
perf/x86/intel/uncore: Parse uncore discovery tables
A self-describing mechanism for the uncore PerfMon hardware has been
introduced with the latest Intel platforms. By reading through an MMIO
page worth of information, perf can 'discover' all the standard uncore
PerfMon registers in a machine.
The discovery mechanism relies on BIOS's support. With a proper BIOS,
a PCI device with the unique capability ID 0x23 can be found on each
die. Perf can retrieve the information of all available uncore PerfMons
from the device via MMIO. The information is composed of one global
discovery table and several unit discovery tables.
- The global discovery table includes global uncore information of the
die, e.g., the address of the global control register, the offset of
the global status register, the number of uncore units, the offset of
unit discovery tables, etc.
- The unit discovery table includes generic uncore unit information,
e.g., the access type, the counter width, the address of counters,
the address of the counter control, the unit ID, the unit type, etc.
The unit is also called "box" in the code.
Perf can provide basic uncore support based on this information
with the following patches.
To locate the PCI device with the discovery tables, check the generic
PCI ID first. If it doesn't match, go through the entire PCI device tree
and locate the device with the unique capability ID.
The uncore information is similar among dies. To save parsing time and
space, only completely parse and store the discovery tables on the first
die and the first box of each die. The parsed information is stored in
an
RB tree structure, intel_uncore_discovery_type. The size of the stored
discovery tables varies among platforms. It's around 4KB for a Sapphire
Rapids server.
If a BIOS doesn't support the 'discovery' mechanism, the uncore driver
will exit with -ENODEV. There is nothing changed.
Add a module parameter to disable the discovery feature. If a BIOS gets
the discovery tables wrong, users can have an option to disable the
feature. For the current patchset, the uncore driver will exit with
-ENODEV. In the future, it may fall back to the hardcode uncore driver
on a known platform.
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/1616003977-90612-2-git-send-email-kan.liang@linux.intel.com
2021-03-17 10:59:33 -07:00
|
|
|
#define uncore_discovery_invalid_unit(unit) \
|
2021-08-26 08:32:38 -07:00
|
|
|
(!unit.table1 || !unit.ctl || \
|
perf/x86/intel/uncore: Parse uncore discovery tables
A self-describing mechanism for the uncore PerfMon hardware has been
introduced with the latest Intel platforms. By reading through an MMIO
page worth of information, perf can 'discover' all the standard uncore
PerfMon registers in a machine.
The discovery mechanism relies on BIOS's support. With a proper BIOS,
a PCI device with the unique capability ID 0x23 can be found on each
die. Perf can retrieve the information of all available uncore PerfMons
from the device via MMIO. The information is composed of one global
discovery table and several unit discovery tables.
- The global discovery table includes global uncore information of the
die, e.g., the address of the global control register, the offset of
the global status register, the number of uncore units, the offset of
unit discovery tables, etc.
- The unit discovery table includes generic uncore unit information,
e.g., the access type, the counter width, the address of counters,
the address of the counter control, the unit ID, the unit type, etc.
The unit is also called "box" in the code.
Perf can provide basic uncore support based on this information
with the following patches.
To locate the PCI device with the discovery tables, check the generic
PCI ID first. If it doesn't match, go through the entire PCI device tree
and locate the device with the unique capability ID.
The uncore information is similar among dies. To save parsing time and
space, only completely parse and store the discovery tables on the first
die and the first box of each die. The parsed information is stored in
an
RB tree structure, intel_uncore_discovery_type. The size of the stored
discovery tables varies among platforms. It's around 4KB for a Sapphire
Rapids server.
If a BIOS doesn't support the 'discovery' mechanism, the uncore driver
will exit with -ENODEV. There is nothing changed.
Add a module parameter to disable the discovery feature. If a BIOS gets
the discovery tables wrong, users can have an option to disable the
feature. For the current patchset, the uncore driver will exit with
-ENODEV. In the future, it may fall back to the hardcode uncore driver
on a known platform.
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/1616003977-90612-2-git-send-email-kan.liang@linux.intel.com
2021-03-17 10:59:33 -07:00
|
|
|
unit.table1 == -1ULL || unit.ctl == -1ULL || \
|
|
|
|
unit.table3 == -1ULL)
|
|
|
|
|
2021-03-17 10:59:34 -07:00
|
|
|
#define GENERIC_PMON_CTL_EV_SEL_MASK 0x000000ff
|
|
|
|
#define GENERIC_PMON_CTL_UMASK_MASK 0x0000ff00
|
|
|
|
#define GENERIC_PMON_CTL_EDGE_DET (1 << 18)
|
|
|
|
#define GENERIC_PMON_CTL_INVERT (1 << 23)
|
|
|
|
#define GENERIC_PMON_CTL_TRESH_MASK 0xff000000
|
|
|
|
#define GENERIC_PMON_RAW_EVENT_MASK (GENERIC_PMON_CTL_EV_SEL_MASK | \
|
|
|
|
GENERIC_PMON_CTL_UMASK_MASK | \
|
|
|
|
GENERIC_PMON_CTL_EDGE_DET | \
|
|
|
|
GENERIC_PMON_CTL_INVERT | \
|
|
|
|
GENERIC_PMON_CTL_TRESH_MASK)
|
|
|
|
|
|
|
|
#define GENERIC_PMON_BOX_CTL_FRZ (1 << 0)
|
|
|
|
#define GENERIC_PMON_BOX_CTL_RST_CTRL (1 << 8)
|
|
|
|
#define GENERIC_PMON_BOX_CTL_RST_CTRS (1 << 9)
|
|
|
|
#define GENERIC_PMON_BOX_CTL_INT (GENERIC_PMON_BOX_CTL_RST_CTRL | \
|
|
|
|
GENERIC_PMON_BOX_CTL_RST_CTRS)
|
|
|
|
|
perf/x86/intel/uncore: Parse uncore discovery tables
A self-describing mechanism for the uncore PerfMon hardware has been
introduced with the latest Intel platforms. By reading through an MMIO
page worth of information, perf can 'discover' all the standard uncore
PerfMon registers in a machine.
The discovery mechanism relies on BIOS's support. With a proper BIOS,
a PCI device with the unique capability ID 0x23 can be found on each
die. Perf can retrieve the information of all available uncore PerfMons
from the device via MMIO. The information is composed of one global
discovery table and several unit discovery tables.
- The global discovery table includes global uncore information of the
die, e.g., the address of the global control register, the offset of
the global status register, the number of uncore units, the offset of
unit discovery tables, etc.
- The unit discovery table includes generic uncore unit information,
e.g., the access type, the counter width, the address of counters,
the address of the counter control, the unit ID, the unit type, etc.
The unit is also called "box" in the code.
Perf can provide basic uncore support based on this information
with the following patches.
To locate the PCI device with the discovery tables, check the generic
PCI ID first. If it doesn't match, go through the entire PCI device tree
and locate the device with the unique capability ID.
The uncore information is similar among dies. To save parsing time and
space, only completely parse and store the discovery tables on the first
die and the first box of each die. The parsed information is stored in
an
RB tree structure, intel_uncore_discovery_type. The size of the stored
discovery tables varies among platforms. It's around 4KB for a Sapphire
Rapids server.
If a BIOS doesn't support the 'discovery' mechanism, the uncore driver
will exit with -ENODEV. There is nothing changed.
Add a module parameter to disable the discovery feature. If a BIOS gets
the discovery tables wrong, users can have an option to disable the
feature. For the current patchset, the uncore driver will exit with
-ENODEV. In the future, it may fall back to the hardcode uncore driver
on a known platform.
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/1616003977-90612-2-git-send-email-kan.liang@linux.intel.com
2021-03-17 10:59:33 -07:00
|
|
|
enum uncore_access_type {
|
|
|
|
UNCORE_ACCESS_MSR = 0,
|
|
|
|
UNCORE_ACCESS_MMIO,
|
|
|
|
UNCORE_ACCESS_PCI,
|
|
|
|
|
|
|
|
UNCORE_ACCESS_MAX,
|
|
|
|
};
|
|
|
|
|
|
|
|
struct uncore_global_discovery {
|
|
|
|
union {
|
|
|
|
u64 table1;
|
|
|
|
struct {
|
|
|
|
u64 type : 8,
|
|
|
|
stride : 8,
|
|
|
|
max_units : 10,
|
|
|
|
__reserved_1 : 36,
|
|
|
|
access_type : 2;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
u64 ctl; /* Global Control Address */
|
|
|
|
|
|
|
|
union {
|
|
|
|
u64 table3;
|
|
|
|
struct {
|
|
|
|
u64 status_offset : 8,
|
|
|
|
num_status : 16,
|
|
|
|
__reserved_2 : 40;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
struct uncore_unit_discovery {
|
|
|
|
union {
|
|
|
|
u64 table1;
|
|
|
|
struct {
|
|
|
|
u64 num_regs : 8,
|
|
|
|
ctl_offset : 8,
|
|
|
|
bit_width : 8,
|
|
|
|
ctr_offset : 8,
|
|
|
|
status_offset : 8,
|
|
|
|
__reserved_1 : 22,
|
|
|
|
access_type : 2;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
u64 ctl; /* Unit Control Address */
|
|
|
|
|
|
|
|
union {
|
|
|
|
u64 table3;
|
|
|
|
struct {
|
|
|
|
u64 box_type : 16,
|
|
|
|
box_id : 16,
|
|
|
|
__reserved_2 : 32;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
perf/x86/uncore: Save the unit control address of all units
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.
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20240614134631.1092359-2-kan.liang@linux.intel.com
2024-06-14 06:46:24 -07:00
|
|
|
struct intel_uncore_discovery_unit {
|
|
|
|
struct rb_node node;
|
|
|
|
unsigned int pmu_idx; /* The idx of the corresponding PMU */
|
|
|
|
unsigned int id; /* Unit ID */
|
|
|
|
unsigned int die; /* Die ID */
|
|
|
|
u64 addr; /* Unit Control Address */
|
|
|
|
};
|
|
|
|
|
perf/x86/intel/uncore: Parse uncore discovery tables
A self-describing mechanism for the uncore PerfMon hardware has been
introduced with the latest Intel platforms. By reading through an MMIO
page worth of information, perf can 'discover' all the standard uncore
PerfMon registers in a machine.
The discovery mechanism relies on BIOS's support. With a proper BIOS,
a PCI device with the unique capability ID 0x23 can be found on each
die. Perf can retrieve the information of all available uncore PerfMons
from the device via MMIO. The information is composed of one global
discovery table and several unit discovery tables.
- The global discovery table includes global uncore information of the
die, e.g., the address of the global control register, the offset of
the global status register, the number of uncore units, the offset of
unit discovery tables, etc.
- The unit discovery table includes generic uncore unit information,
e.g., the access type, the counter width, the address of counters,
the address of the counter control, the unit ID, the unit type, etc.
The unit is also called "box" in the code.
Perf can provide basic uncore support based on this information
with the following patches.
To locate the PCI device with the discovery tables, check the generic
PCI ID first. If it doesn't match, go through the entire PCI device tree
and locate the device with the unique capability ID.
The uncore information is similar among dies. To save parsing time and
space, only completely parse and store the discovery tables on the first
die and the first box of each die. The parsed information is stored in
an
RB tree structure, intel_uncore_discovery_type. The size of the stored
discovery tables varies among platforms. It's around 4KB for a Sapphire
Rapids server.
If a BIOS doesn't support the 'discovery' mechanism, the uncore driver
will exit with -ENODEV. There is nothing changed.
Add a module parameter to disable the discovery feature. If a BIOS gets
the discovery tables wrong, users can have an option to disable the
feature. For the current patchset, the uncore driver will exit with
-ENODEV. In the future, it may fall back to the hardcode uncore driver
on a known platform.
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/1616003977-90612-2-git-send-email-kan.liang@linux.intel.com
2021-03-17 10:59:33 -07:00
|
|
|
struct intel_uncore_discovery_type {
|
|
|
|
struct rb_node node;
|
|
|
|
enum uncore_access_type access_type;
|
perf/x86/uncore: Save the unit control address of all units
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.
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20240614134631.1092359-2-kan.liang@linux.intel.com
2024-06-14 06:46:24 -07:00
|
|
|
struct rb_root units; /* Unit ctrl addr for all units */
|
perf/x86/intel/uncore: Parse uncore discovery tables
A self-describing mechanism for the uncore PerfMon hardware has been
introduced with the latest Intel platforms. By reading through an MMIO
page worth of information, perf can 'discover' all the standard uncore
PerfMon registers in a machine.
The discovery mechanism relies on BIOS's support. With a proper BIOS,
a PCI device with the unique capability ID 0x23 can be found on each
die. Perf can retrieve the information of all available uncore PerfMons
from the device via MMIO. The information is composed of one global
discovery table and several unit discovery tables.
- The global discovery table includes global uncore information of the
die, e.g., the address of the global control register, the offset of
the global status register, the number of uncore units, the offset of
unit discovery tables, etc.
- The unit discovery table includes generic uncore unit information,
e.g., the access type, the counter width, the address of counters,
the address of the counter control, the unit ID, the unit type, etc.
The unit is also called "box" in the code.
Perf can provide basic uncore support based on this information
with the following patches.
To locate the PCI device with the discovery tables, check the generic
PCI ID first. If it doesn't match, go through the entire PCI device tree
and locate the device with the unique capability ID.
The uncore information is similar among dies. To save parsing time and
space, only completely parse and store the discovery tables on the first
die and the first box of each die. The parsed information is stored in
an
RB tree structure, intel_uncore_discovery_type. The size of the stored
discovery tables varies among platforms. It's around 4KB for a Sapphire
Rapids server.
If a BIOS doesn't support the 'discovery' mechanism, the uncore driver
will exit with -ENODEV. There is nothing changed.
Add a module parameter to disable the discovery feature. If a BIOS gets
the discovery tables wrong, users can have an option to disable the
feature. For the current patchset, the uncore driver will exit with
-ENODEV. In the future, it may fall back to the hardcode uncore driver
on a known platform.
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/1616003977-90612-2-git-send-email-kan.liang@linux.intel.com
2021-03-17 10:59:33 -07:00
|
|
|
u16 type; /* Type ID of the uncore block */
|
|
|
|
u8 num_counters;
|
|
|
|
u8 counter_width;
|
|
|
|
u8 ctl_offset; /* Counter Control 0 offset */
|
|
|
|
u8 ctr_offset; /* Counter 0 offset */
|
perf/x86/uncore: Save the unit control address of all units
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.
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lore.kernel.org/r/20240614134631.1092359-2-kan.liang@linux.intel.com
2024-06-14 06:46:24 -07:00
|
|
|
u16 num_units; /* number of units */
|
perf/x86/intel/uncore: Parse uncore discovery tables
A self-describing mechanism for the uncore PerfMon hardware has been
introduced with the latest Intel platforms. By reading through an MMIO
page worth of information, perf can 'discover' all the standard uncore
PerfMon registers in a machine.
The discovery mechanism relies on BIOS's support. With a proper BIOS,
a PCI device with the unique capability ID 0x23 can be found on each
die. Perf can retrieve the information of all available uncore PerfMons
from the device via MMIO. The information is composed of one global
discovery table and several unit discovery tables.
- The global discovery table includes global uncore information of the
die, e.g., the address of the global control register, the offset of
the global status register, the number of uncore units, the offset of
unit discovery tables, etc.
- The unit discovery table includes generic uncore unit information,
e.g., the access type, the counter width, the address of counters,
the address of the counter control, the unit ID, the unit type, etc.
The unit is also called "box" in the code.
Perf can provide basic uncore support based on this information
with the following patches.
To locate the PCI device with the discovery tables, check the generic
PCI ID first. If it doesn't match, go through the entire PCI device tree
and locate the device with the unique capability ID.
The uncore information is similar among dies. To save parsing time and
space, only completely parse and store the discovery tables on the first
die and the first box of each die. The parsed information is stored in
an
RB tree structure, intel_uncore_discovery_type. The size of the stored
discovery tables varies among platforms. It's around 4KB for a Sapphire
Rapids server.
If a BIOS doesn't support the 'discovery' mechanism, the uncore driver
will exit with -ENODEV. There is nothing changed.
Add a module parameter to disable the discovery feature. If a BIOS gets
the discovery tables wrong, users can have an option to disable the
feature. For the current patchset, the uncore driver will exit with
-ENODEV. In the future, it may fall back to the hardcode uncore driver
on a known platform.
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/1616003977-90612-2-git-send-email-kan.liang@linux.intel.com
2021-03-17 10:59:33 -07:00
|
|
|
};
|
|
|
|
|
2023-01-12 13:01:03 -07:00
|
|
|
bool intel_uncore_has_discovery_tables(int *ignore);
|
perf/x86/intel/uncore: Parse uncore discovery tables
A self-describing mechanism for the uncore PerfMon hardware has been
introduced with the latest Intel platforms. By reading through an MMIO
page worth of information, perf can 'discover' all the standard uncore
PerfMon registers in a machine.
The discovery mechanism relies on BIOS's support. With a proper BIOS,
a PCI device with the unique capability ID 0x23 can be found on each
die. Perf can retrieve the information of all available uncore PerfMons
from the device via MMIO. The information is composed of one global
discovery table and several unit discovery tables.
- The global discovery table includes global uncore information of the
die, e.g., the address of the global control register, the offset of
the global status register, the number of uncore units, the offset of
unit discovery tables, etc.
- The unit discovery table includes generic uncore unit information,
e.g., the access type, the counter width, the address of counters,
the address of the counter control, the unit ID, the unit type, etc.
The unit is also called "box" in the code.
Perf can provide basic uncore support based on this information
with the following patches.
To locate the PCI device with the discovery tables, check the generic
PCI ID first. If it doesn't match, go through the entire PCI device tree
and locate the device with the unique capability ID.
The uncore information is similar among dies. To save parsing time and
space, only completely parse and store the discovery tables on the first
die and the first box of each die. The parsed information is stored in
an
RB tree structure, intel_uncore_discovery_type. The size of the stored
discovery tables varies among platforms. It's around 4KB for a Sapphire
Rapids server.
If a BIOS doesn't support the 'discovery' mechanism, the uncore driver
will exit with -ENODEV. There is nothing changed.
Add a module parameter to disable the discovery feature. If a BIOS gets
the discovery tables wrong, users can have an option to disable the
feature. For the current patchset, the uncore driver will exit with
-ENODEV. In the future, it may fall back to the hardcode uncore driver
on a known platform.
Signed-off-by: Kan Liang <kan.liang@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/1616003977-90612-2-git-send-email-kan.liang@linux.intel.com
2021-03-17 10:59:33 -07:00
|
|
|
void intel_uncore_clear_discovery_tables(void);
|
2021-03-17 10:59:34 -07:00
|
|
|
void intel_uncore_generic_uncore_cpu_init(void);
|
2021-03-17 10:59:36 -07:00
|
|
|
int intel_uncore_generic_uncore_pci_init(void);
|
2021-03-17 10:59:37 -07:00
|
|
|
void intel_uncore_generic_uncore_mmio_init(void);
|
2021-06-30 14:08:25 -07:00
|
|
|
|
2021-06-30 14:08:26 -07:00
|
|
|
void intel_generic_uncore_msr_init_box(struct intel_uncore_box *box);
|
|
|
|
void intel_generic_uncore_msr_disable_box(struct intel_uncore_box *box);
|
|
|
|
void intel_generic_uncore_msr_enable_box(struct intel_uncore_box *box);
|
|
|
|
|
2021-06-30 14:08:31 -07:00
|
|
|
void intel_generic_uncore_mmio_init_box(struct intel_uncore_box *box);
|
|
|
|
void intel_generic_uncore_mmio_disable_box(struct intel_uncore_box *box);
|
|
|
|
void intel_generic_uncore_mmio_enable_box(struct intel_uncore_box *box);
|
|
|
|
void intel_generic_uncore_mmio_disable_event(struct intel_uncore_box *box,
|
|
|
|
struct perf_event *event);
|
2022-01-13 15:05:54 -07:00
|
|
|
void intel_generic_uncore_mmio_enable_event(struct intel_uncore_box *box,
|
|
|
|
struct perf_event *event);
|
2021-06-30 14:08:31 -07:00
|
|
|
|
2021-06-30 14:08:32 -07:00
|
|
|
void intel_generic_uncore_pci_init_box(struct intel_uncore_box *box);
|
|
|
|
void intel_generic_uncore_pci_disable_box(struct intel_uncore_box *box);
|
|
|
|
void intel_generic_uncore_pci_enable_box(struct intel_uncore_box *box);
|
|
|
|
void intel_generic_uncore_pci_disable_event(struct intel_uncore_box *box,
|
|
|
|
struct perf_event *event);
|
|
|
|
u64 intel_generic_uncore_pci_read_counter(struct intel_uncore_box *box,
|
|
|
|
struct perf_event *event);
|
|
|
|
|
2021-06-30 14:08:25 -07:00
|
|
|
struct intel_uncore_type **
|
2021-06-30 14:08:38 -07:00
|
|
|
intel_uncore_generic_init_uncores(enum uncore_access_type type_id, int num_extra);
|
2024-06-14 06:46:25 -07:00
|
|
|
|
|
|
|
int intel_uncore_find_discovery_unit_id(struct rb_root *units, int die,
|
|
|
|
unsigned int pmu_idx);
|
2024-06-14 06:46:28 -07:00
|
|
|
bool intel_generic_uncore_assign_hw_event(struct perf_event *event,
|
|
|
|
struct intel_uncore_box *box);
|
2024-06-14 06:46:29 -07:00
|
|
|
void uncore_find_add_unit(struct intel_uncore_discovery_unit *node,
|
|
|
|
struct rb_root *root, u16 *num_units);
|