Skip to content

Commit

Permalink
perf/x86/intel/uncore: Add IMC uncore support for Snow Ridge
Browse files Browse the repository at this point in the history
IMC uncore unit can only be accessed via MMIO on Snow Ridge.
The MMIO space of IMC uncore is at the specified offsets from the
MEM0_BAR. Add snr_uncore_get_mc_dev() to locate the PCI device with
MMIO_BASE and MEM0_BAR register.

Add new ops to access the IMC registers via MMIO.

Add 3 new free running counters for clocks, read and write bandwidth.

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-7-git-send-email-kan.liang@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
  • Loading branch information
Kan Liang authored and Ingo Molnar committed Jun 17, 2019
1 parent 07ce734 commit ee49532
Show file tree
Hide file tree
Showing 3 changed files with 201 additions and 1 deletion.
3 changes: 2 additions & 1 deletion arch/x86/events/intel/uncore.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ struct event_constraint uncore_constraint_empty =

MODULE_LICENSE("GPL");

static int uncore_pcibus_to_physid(struct pci_bus *bus)
int uncore_pcibus_to_physid(struct pci_bus *bus)
{
struct pci2phy_map *map;
int phys_id = -1;
Expand Down Expand Up @@ -1441,6 +1441,7 @@ static const struct intel_uncore_init_fun icl_uncore_init __initconst = {
static const struct intel_uncore_init_fun snr_uncore_init __initconst = {
.cpu_init = snr_uncore_cpu_init,
.pci_init = snr_uncore_pci_init,
.mmio_init = snr_uncore_mmio_init,
};

static const struct x86_cpu_id intel_uncore_match[] __initconst = {
Expand Down
2 changes: 2 additions & 0 deletions arch/x86/events/intel/uncore.h
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ struct pci2phy_map {
};

struct pci2phy_map *__find_pci2phy_map(int segment);
int uncore_pcibus_to_physid(struct pci_bus *bus);

ssize_t uncore_event_show(struct kobject *kobj,
struct kobj_attribute *attr, char *buf);
Expand Down Expand Up @@ -555,6 +556,7 @@ int skx_uncore_pci_init(void);
void skx_uncore_cpu_init(void);
int snr_uncore_pci_init(void);
void snr_uncore_cpu_init(void);
void snr_uncore_mmio_init(void);

/* uncore_nhmex.c */
void nhmex_uncore_cpu_init(void);
197 changes: 197 additions & 0 deletions arch/x86/events/intel/uncore_snbep.c
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,19 @@
#define SNR_PCIE3_PCI_PMON_CTR0 0x4e8
#define SNR_PCIE3_PCI_PMON_BOX_CTL 0x4e4

/* SNR IMC */
#define SNR_IMC_MMIO_PMON_FIXED_CTL 0x54
#define SNR_IMC_MMIO_PMON_FIXED_CTR 0x38
#define SNR_IMC_MMIO_PMON_CTL0 0x40
#define SNR_IMC_MMIO_PMON_CTR0 0x8
#define SNR_IMC_MMIO_PMON_BOX_CTL 0x22800
#define SNR_IMC_MMIO_OFFSET 0x4000
#define SNR_IMC_MMIO_SIZE 0x4000
#define SNR_IMC_MMIO_BASE_OFFSET 0xd0
#define SNR_IMC_MMIO_BASE_MASK 0x1FFFFFFF
#define SNR_IMC_MMIO_MEM0_OFFSET 0xd8
#define SNR_IMC_MMIO_MEM0_MASK 0x7FF

DEFINE_UNCORE_FORMAT_ATTR(event, event, "config:0-7");
DEFINE_UNCORE_FORMAT_ATTR(event2, event, "config:0-6");
DEFINE_UNCORE_FORMAT_ATTR(event_ext, event, "config:0-7,21");
Expand Down Expand Up @@ -4370,4 +4383,188 @@ int snr_uncore_pci_init(void)
return 0;
}

static struct pci_dev *snr_uncore_get_mc_dev(int id)
{
struct pci_dev *mc_dev = NULL;
int phys_id, pkg;

while (1) {
mc_dev = pci_get_device(PCI_VENDOR_ID_INTEL, 0x3451, mc_dev);
if (!mc_dev)
break;
phys_id = uncore_pcibus_to_physid(mc_dev->bus);
if (phys_id < 0)
continue;
pkg = topology_phys_to_logical_pkg(phys_id);
if (pkg < 0)
continue;
else if (pkg == id)
break;
}
return mc_dev;
}

static void snr_uncore_mmio_init_box(struct intel_uncore_box *box)
{
struct pci_dev *pdev = snr_uncore_get_mc_dev(box->dieid);
unsigned int box_ctl = uncore_mmio_box_ctl(box);
resource_size_t addr;
u32 pci_dword;

if (!pdev)
return;

pci_read_config_dword(pdev, SNR_IMC_MMIO_BASE_OFFSET, &pci_dword);
addr = (pci_dword & SNR_IMC_MMIO_BASE_MASK) << 23;

pci_read_config_dword(pdev, SNR_IMC_MMIO_MEM0_OFFSET, &pci_dword);
addr |= (pci_dword & SNR_IMC_MMIO_MEM0_MASK) << 12;

addr += box_ctl;

box->io_addr = ioremap(addr, SNR_IMC_MMIO_SIZE);
if (!box->io_addr)
return;

writel(IVBEP_PMON_BOX_CTL_INT, box->io_addr);
}

static void snr_uncore_mmio_disable_box(struct intel_uncore_box *box)
{
u32 config;

if (!box->io_addr)
return;

config = readl(box->io_addr);
config |= SNBEP_PMON_BOX_CTL_FRZ;
writel(config, box->io_addr);
}

static void snr_uncore_mmio_enable_box(struct intel_uncore_box *box)
{
u32 config;

if (!box->io_addr)
return;

config = readl(box->io_addr);
config &= ~SNBEP_PMON_BOX_CTL_FRZ;
writel(config, box->io_addr);
}

static void snr_uncore_mmio_enable_event(struct intel_uncore_box *box,
struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;

if (!box->io_addr)
return;

writel(hwc->config | SNBEP_PMON_CTL_EN,
box->io_addr + hwc->config_base);
}

static void snr_uncore_mmio_disable_event(struct intel_uncore_box *box,
struct perf_event *event)
{
struct hw_perf_event *hwc = &event->hw;

if (!box->io_addr)
return;

writel(hwc->config, box->io_addr + hwc->config_base);
}

static struct intel_uncore_ops snr_uncore_mmio_ops = {
.init_box = snr_uncore_mmio_init_box,
.exit_box = uncore_mmio_exit_box,
.disable_box = snr_uncore_mmio_disable_box,
.enable_box = snr_uncore_mmio_enable_box,
.disable_event = snr_uncore_mmio_disable_event,
.enable_event = snr_uncore_mmio_enable_event,
.read_counter = uncore_mmio_read_counter,
};

static struct uncore_event_desc snr_uncore_imc_events[] = {
INTEL_UNCORE_EVENT_DESC(clockticks, "event=0x00,umask=0x00"),
INTEL_UNCORE_EVENT_DESC(cas_count_read, "event=0x04,umask=0x0f"),
INTEL_UNCORE_EVENT_DESC(cas_count_read.scale, "6.103515625e-5"),
INTEL_UNCORE_EVENT_DESC(cas_count_read.unit, "MiB"),
INTEL_UNCORE_EVENT_DESC(cas_count_write, "event=0x04,umask=0x30"),
INTEL_UNCORE_EVENT_DESC(cas_count_write.scale, "6.103515625e-5"),
INTEL_UNCORE_EVENT_DESC(cas_count_write.unit, "MiB"),
{ /* end: all zeroes */ },
};

static struct intel_uncore_type snr_uncore_imc = {
.name = "imc",
.num_counters = 4,
.num_boxes = 2,
.perf_ctr_bits = 48,
.fixed_ctr_bits = 48,
.fixed_ctr = SNR_IMC_MMIO_PMON_FIXED_CTR,
.fixed_ctl = SNR_IMC_MMIO_PMON_FIXED_CTL,
.event_descs = snr_uncore_imc_events,
.perf_ctr = SNR_IMC_MMIO_PMON_CTR0,
.event_ctl = SNR_IMC_MMIO_PMON_CTL0,
.event_mask = SNBEP_PMON_RAW_EVENT_MASK,
.box_ctl = SNR_IMC_MMIO_PMON_BOX_CTL,
.mmio_offset = SNR_IMC_MMIO_OFFSET,
.ops = &snr_uncore_mmio_ops,
.format_group = &skx_uncore_format_group,
};

enum perf_uncore_snr_imc_freerunning_type_id {
SNR_IMC_DCLK,
SNR_IMC_DDR,

SNR_IMC_FREERUNNING_TYPE_MAX,
};

static struct freerunning_counters snr_imc_freerunning[] = {
[SNR_IMC_DCLK] = { 0x22b0, 0x0, 0, 1, 48 },
[SNR_IMC_DDR] = { 0x2290, 0x8, 0, 2, 48 },
};

static struct uncore_event_desc snr_uncore_imc_freerunning_events[] = {
INTEL_UNCORE_EVENT_DESC(dclk, "event=0xff,umask=0x10"),

INTEL_UNCORE_EVENT_DESC(read, "event=0xff,umask=0x20"),
INTEL_UNCORE_EVENT_DESC(read.scale, "3.814697266e-6"),
INTEL_UNCORE_EVENT_DESC(read.unit, "MiB"),
INTEL_UNCORE_EVENT_DESC(write, "event=0xff,umask=0x21"),
INTEL_UNCORE_EVENT_DESC(write.scale, "3.814697266e-6"),
INTEL_UNCORE_EVENT_DESC(write.unit, "MiB"),
};

static struct intel_uncore_ops snr_uncore_imc_freerunning_ops = {
.init_box = snr_uncore_mmio_init_box,
.exit_box = uncore_mmio_exit_box,
.read_counter = uncore_mmio_read_counter,
.hw_config = uncore_freerunning_hw_config,
};

static struct intel_uncore_type snr_uncore_imc_free_running = {
.name = "imc_free_running",
.num_counters = 3,
.num_boxes = 1,
.num_freerunning_types = SNR_IMC_FREERUNNING_TYPE_MAX,
.freerunning = snr_imc_freerunning,
.ops = &snr_uncore_imc_freerunning_ops,
.event_descs = snr_uncore_imc_freerunning_events,
.format_group = &skx_uncore_iio_freerunning_format_group,
};

static struct intel_uncore_type *snr_mmio_uncores[] = {
&snr_uncore_imc,
&snr_uncore_imc_free_running,
NULL,
};

void snr_uncore_mmio_init(void)
{
uncore_mmio_uncores = snr_mmio_uncores;
}

/* end of SNR uncore support */

0 comments on commit ee49532

Please sign in to comment.