root/arch/x86/events/intel/uncore_discovery.h
/* SPDX-License-Identifier: GPL-2.0-only */

/* Store the full address of the global discovery table */
#define UNCORE_DISCOVERY_MSR                    0x201e
/* Base address of uncore perfmon discovery table for CBB domain */
#define CBB_UNCORE_DISCOVERY_MSR                0x710
/* Base address of uncore perfmon discovery table for the package */
#define PACKAGE_UNCORE_DISCOVERY_MSR            0x711

/* Generic device ID of a discovery table device */
#define UNCORE_DISCOVERY_TABLE_DEVICE           0x09a7
/* Device ID used on DMR */
#define DMR_UNCORE_DISCOVERY_TABLE_DEVICE       0x09a1
/* 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

#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)
#define UNCORE_DISCOVERY_PCI_BOX_CTRL(data)     (data & 0xfff)


#define uncore_discovery_invalid_unit(unit)                     \
        (!unit.table1 || !unit.ctl || \
         unit.table1 == -1ULL || unit.ctl == -1ULL ||   \
         unit.table3 == -1ULL)

#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)

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;
                };
        };
};

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 */
};

struct intel_uncore_discovery_type {
        struct rb_node  node;
        enum uncore_access_type access_type;
        struct rb_root  units;          /* Unit ctrl addr for all units */
        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 */
        u16             num_units;      /* number of units */
};

bool uncore_discovery(struct uncore_plat_init *init);
void intel_uncore_clear_discovery_tables(void);
void intel_uncore_generic_uncore_cpu_init(void);
int intel_uncore_generic_uncore_pci_init(void);
void intel_uncore_generic_uncore_mmio_init(void);

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);

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);
void intel_generic_uncore_mmio_enable_event(struct intel_uncore_box *box,
                                            struct perf_event *event);

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);

struct intel_uncore_type **
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);
void uncore_find_add_unit(struct intel_uncore_discovery_unit *node,
                          struct rb_root *root, u16 *num_units);
struct intel_uncore_type **
uncore_get_uncores(enum uncore_access_type type_id, int num_extra,
                   struct intel_uncore_type **extra, int max_num_types,
                   struct intel_uncore_type **uncores);