Rename existing intel_pt.h to intel_pt_perf.h as a perf-specific header,
and make a new intel_pt.h as a common header of Intel PT feature. Also
add intel_pt_cap.c for Intel PT capability stuff.

Signed-off-by: Takao Indoh <[email protected]>
---
 arch/x86/include/asm/intel_pt.h           |   82 ++++++++++++++++++
 arch/x86/kernel/cpu/Makefile              |    1 +
 arch/x86/kernel/cpu/intel_pt.h            |  131 -----------------------------
 arch/x86/kernel/cpu/intel_pt_cap.c        |   69 +++++++++++++++
 arch/x86/kernel/cpu/intel_pt_perf.h       |   78 +++++++++++++++++
 arch/x86/kernel/cpu/perf_event_intel_pt.c |   54 ++----------
 6 files changed, 239 insertions(+), 176 deletions(-)
 create mode 100644 arch/x86/include/asm/intel_pt.h
 delete mode 100644 arch/x86/kernel/cpu/intel_pt.h
 create mode 100644 arch/x86/kernel/cpu/intel_pt_cap.c
 create mode 100644 arch/x86/kernel/cpu/intel_pt_perf.h

diff --git a/arch/x86/include/asm/intel_pt.h b/arch/x86/include/asm/intel_pt.h
new file mode 100644
index 0000000..7cb16e1
--- /dev/null
+++ b/arch/x86/include/asm/intel_pt.h
@@ -0,0 +1,82 @@
+/*
+ * Intel(R) Processor Trace common header
+ * Copyright (c) 2013-2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * Intel PT is specified in the Intel Architecture Instruction Set Extensions
+ * Programming Reference:
+ * http://software.intel.com/en-us/intel-isa-extensions
+ */
+
+#ifndef __INTEL_PT_H__
+#define __INTEL_PT_H__
+
+/*
+ * Table of Physical Addresses bits
+ */
+enum topa_sz {
+       TOPA_4K = 0,
+       TOPA_8K,
+       TOPA_16K,
+       TOPA_32K,
+       TOPA_64K,
+       TOPA_128K,
+       TOPA_256K,
+       TOPA_512K,
+       TOPA_1MB,
+       TOPA_2MB,
+       TOPA_4MB,
+       TOPA_8MB,
+       TOPA_16MB,
+       TOPA_32MB,
+       TOPA_64MB,
+       TOPA_128MB,
+       TOPA_SZ_END,
+};
+
+static inline unsigned int sizes(enum topa_sz tsz)
+{
+       return 1 << (tsz + 12);
+};
+
+struct topa_entry {
+       u64     end     : 1;
+       u64     rsvd0   : 1;
+       u64     intr    : 1;
+       u64     rsvd1   : 1;
+       u64     stop    : 1;
+       u64     rsvd2   : 1;
+       u64     size    : 4;
+       u64     rsvd3   : 2;
+       u64     base    : 36;
+       u64     rsvd4   : 16;
+};
+
+#define TOPA_SHIFT 12
+#define PT_CPUID_LEAVES 2
+
+/*
+ * Capability stuff
+ */
+enum pt_capabilities {
+       PT_CAP_max_subleaf = 0,
+       PT_CAP_cr3_filtering,
+       PT_CAP_topa_output,
+       PT_CAP_topa_multiple_entries,
+       PT_CAP_payloads_lip,
+};
+
+void pt_cap_init(void);
+u32 pt_cap_get(enum pt_capabilities cap);
+const char *pt_cap_name(enum pt_capabilities cap);
+int pt_cap_num(void);
+
+#endif /* __INTEL_PT_H__ */
diff --git a/arch/x86/kernel/cpu/Makefile b/arch/x86/kernel/cpu/Makefile
index 9bff687..77d371c 100644
--- a/arch/x86/kernel/cpu/Makefile
+++ b/arch/x86/kernel/cpu/Makefile
@@ -29,6 +29,7 @@ obj-$(CONFIG_CPU_SUP_CYRIX_32)                += cyrix.o
 obj-$(CONFIG_CPU_SUP_CENTAUR)          += centaur.o
 obj-$(CONFIG_CPU_SUP_TRANSMETA_32)     += transmeta.o
 obj-$(CONFIG_CPU_SUP_UMC_32)           += umc.o
+obj-$(CONFIG_CPU_SUP_INTEL)            += intel_pt_cap.o
 
 obj-$(CONFIG_PERF_EVENTS)              += perf_event.o
 
diff --git a/arch/x86/kernel/cpu/intel_pt.h b/arch/x86/kernel/cpu/intel_pt.h
deleted file mode 100644
index 1c338b0..0000000
--- a/arch/x86/kernel/cpu/intel_pt.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- * Intel(R) Processor Trace PMU driver for perf
- * Copyright (c) 2013-2014, Intel Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- * Intel PT is specified in the Intel Architecture Instruction Set Extensions
- * Programming Reference:
- * http://software.intel.com/en-us/intel-isa-extensions
- */
-
-#ifndef __INTEL_PT_H__
-#define __INTEL_PT_H__
-
-/*
- * Single-entry ToPA: when this close to region boundary, switch
- * buffers to avoid losing data.
- */
-#define TOPA_PMI_MARGIN 512
-
-/*
- * Table of Physical Addresses bits
- */
-enum topa_sz {
-       TOPA_4K = 0,
-       TOPA_8K,
-       TOPA_16K,
-       TOPA_32K,
-       TOPA_64K,
-       TOPA_128K,
-       TOPA_256K,
-       TOPA_512K,
-       TOPA_1MB,
-       TOPA_2MB,
-       TOPA_4MB,
-       TOPA_8MB,
-       TOPA_16MB,
-       TOPA_32MB,
-       TOPA_64MB,
-       TOPA_128MB,
-       TOPA_SZ_END,
-};
-
-static inline unsigned int sizes(enum topa_sz tsz)
-{
-       return 1 << (tsz + 12);
-};
-
-struct topa_entry {
-       u64     end     : 1;
-       u64     rsvd0   : 1;
-       u64     intr    : 1;
-       u64     rsvd1   : 1;
-       u64     stop    : 1;
-       u64     rsvd2   : 1;
-       u64     size    : 4;
-       u64     rsvd3   : 2;
-       u64     base    : 36;
-       u64     rsvd4   : 16;
-};
-
-#define TOPA_SHIFT 12
-#define PT_CPUID_LEAVES 2
-
-enum pt_capabilities {
-       PT_CAP_max_subleaf = 0,
-       PT_CAP_cr3_filtering,
-       PT_CAP_topa_output,
-       PT_CAP_topa_multiple_entries,
-       PT_CAP_payloads_lip,
-};
-
-struct pt_pmu {
-       struct pmu              pmu;
-       u32                     caps[4 * PT_CPUID_LEAVES];
-};
-
-/**
- * struct pt_buffer - buffer configuration; one buffer per task_struct or
- *             cpu, depending on perf event configuration
- * @cpu:       cpu for per-cpu allocation
- * @tables:    list of ToPA tables in this buffer
- * @first:     shorthand for first topa table
- * @last:      shorthand for last topa table
- * @cur:       current topa table
- * @nr_pages:  buffer size in pages
- * @cur_idx:   current output region's index within @cur table
- * @output_off:        offset within the current output region
- * @data_size: running total of the amount of data in this buffer
- * @lost:      if data was lost/truncated
- * @head:      logical write offset inside the buffer
- * @snapshot:  if this is for a snapshot/overwrite counter
- * @stop_pos:  STOP topa entry in the buffer
- * @intr_pos:  INT topa entry in the buffer
- * @data_pages:        array of pages from perf
- * @topa_index:        table of topa entries indexed by page offset
- */
-struct pt_buffer {
-       int                     cpu;
-       struct list_head        tables;
-       struct topa             *first, *last, *cur;
-       unsigned int            cur_idx;
-       size_t                  output_off;
-       unsigned long           nr_pages;
-       local_t                 data_size;
-       local_t                 lost;
-       local64_t               head;
-       bool                    snapshot;
-       unsigned long           stop_pos, intr_pos;
-       void                    **data_pages;
-       struct topa_entry       *topa_index[0];
-};
-
-/**
- * struct pt - per-cpu pt context
- * @handle:    perf output handle
- * @handle_nmi:        do handle PT PMI on this cpu, there's an active event
- */
-struct pt {
-       struct perf_output_handle handle;
-       int                     handle_nmi;
-};
-
-#endif /* __INTEL_PT_H__ */
diff --git a/arch/x86/kernel/cpu/intel_pt_cap.c 
b/arch/x86/kernel/cpu/intel_pt_cap.c
new file mode 100644
index 0000000..a2cfbfc
--- /dev/null
+++ b/arch/x86/kernel/cpu/intel_pt_cap.c
@@ -0,0 +1,69 @@
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/mm.h>
+#include <asm/intel_pt.h>
+
+enum cpuid_regs {
+       CR_EAX = 0,
+       CR_ECX,
+       CR_EDX,
+       CR_EBX
+};
+
+static u32 cpuid_cache[4 * PT_CPUID_LEAVES];
+static int pt_cap_initialized;
+
+#define PT_CAP(_n, _l, _r, _m)                                         \
+       [PT_CAP_ ## _n] = { .name = __stringify(_n), .leaf = _l,        \
+                           .reg = _r, .mask = _m }
+
+static struct pt_cap_desc {
+       const char      *name;
+       u32             leaf;
+       u8              reg;
+       u32             mask;
+} pt_caps[] = {
+       PT_CAP(max_subleaf,             0, CR_EAX, 0xffffffff),
+       PT_CAP(cr3_filtering,           0, CR_EBX, BIT(0)),
+       PT_CAP(topa_output,             0, CR_ECX, BIT(0)),
+       PT_CAP(topa_multiple_entries,   0, CR_ECX, BIT(1)),
+       PT_CAP(payloads_lip,            0, CR_ECX, BIT(31)),
+};
+
+u32 pt_cap_get(enum pt_capabilities cap)
+{
+       struct pt_cap_desc *cd = &pt_caps[cap];
+       u32 c = cpuid_cache[cd->leaf * 4 + cd->reg];
+       unsigned int shift = __ffs(cd->mask);
+
+       return (c & cd->mask) >> shift;
+}
+
+const char *pt_cap_name(enum pt_capabilities cap)
+{
+       return pt_caps[cap].name;
+}
+
+int pt_cap_num(void)
+{
+       return ARRAY_SIZE(pt_caps);
+}
+
+void __init pt_cap_init(void)
+{
+       int i;
+
+       if (pt_cap_initialized)
+               return;
+
+       for (i = 0; i < PT_CPUID_LEAVES; i++) {
+               cpuid_count(20, i,
+                           &cpuid_cache[CR_EAX + i*4],
+                           &cpuid_cache[CR_EBX + i*4],
+                           &cpuid_cache[CR_ECX + i*4],
+                           &cpuid_cache[CR_EDX + i*4]);
+       }
+
+       pt_cap_initialized = 1;
+}
+
diff --git a/arch/x86/kernel/cpu/intel_pt_perf.h 
b/arch/x86/kernel/cpu/intel_pt_perf.h
new file mode 100644
index 0000000..1e77646
--- /dev/null
+++ b/arch/x86/kernel/cpu/intel_pt_perf.h
@@ -0,0 +1,78 @@
+/*
+ * Intel(R) Processor Trace PMU driver for perf
+ * Copyright (c) 2013-2014, Intel Corporation.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * Intel PT is specified in the Intel Architecture Instruction Set Extensions
+ * Programming Reference:
+ * http://software.intel.com/en-us/intel-isa-extensions
+ */
+
+#ifndef __INTEL_PT_PERF_H__
+#define __INTEL_PT_PERF_H__
+
+/*
+ * Single-entry ToPA: when this close to region boundary, switch
+ * buffers to avoid losing data.
+ */
+#define TOPA_PMI_MARGIN 512
+
+struct pt_pmu {
+       struct pmu              pmu;
+};
+
+/**
+ * struct pt_buffer - buffer configuration; one buffer per task_struct or
+ *             cpu, depending on perf event configuration
+ * @cpu:       cpu for per-cpu allocation
+ * @tables:    list of ToPA tables in this buffer
+ * @first:     shorthand for first topa table
+ * @last:      shorthand for last topa table
+ * @cur:       current topa table
+ * @nr_pages:  buffer size in pages
+ * @cur_idx:   current output region's index within @cur table
+ * @output_off:        offset within the current output region
+ * @data_size: running total of the amount of data in this buffer
+ * @lost:      if data was lost/truncated
+ * @head:      logical write offset inside the buffer
+ * @snapshot:  if this is for a snapshot/overwrite counter
+ * @stop_pos:  STOP topa entry in the buffer
+ * @intr_pos:  INT topa entry in the buffer
+ * @data_pages:        array of pages from perf
+ * @topa_index:        table of topa entries indexed by page offset
+ */
+struct pt_buffer {
+       int                     cpu;
+       struct list_head        tables;
+       struct topa             *first, *last, *cur;
+       unsigned int            cur_idx;
+       size_t                  output_off;
+       unsigned long           nr_pages;
+       local_t                 data_size;
+       local_t                 lost;
+       local64_t               head;
+       bool                    snapshot;
+       unsigned long           stop_pos, intr_pos;
+       void                    **data_pages;
+       struct topa_entry       *topa_index[0];
+};
+
+/**
+ * struct pt - per-cpu pt context
+ * @handle:    perf output handle
+ * @handle_nmi:        do handle PT PMI on this cpu, there's an active event
+ */
+struct pt {
+       struct perf_output_handle handle;
+       int                     handle_nmi;
+};
+
+#endif /* __INTEL_PT_PERF_H__ */
diff --git a/arch/x86/kernel/cpu/perf_event_intel_pt.c 
b/arch/x86/kernel/cpu/perf_event_intel_pt.c
index 183de71..c3aec2c 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_pt.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_pt.c
@@ -27,21 +27,15 @@
 #include <asm/perf_event.h>
 #include <asm/insn.h>
 #include <asm/io.h>
+#include <asm/intel_pt.h>
 
 #include "perf_event.h"
-#include "intel_pt.h"
+#include "intel_pt_perf.h"
 
 static DEFINE_PER_CPU(struct pt, pt_ctx);
 
 static struct pt_pmu pt_pmu;
 
-enum cpuid_regs {
-       CR_EAX = 0,
-       CR_ECX,
-       CR_EDX,
-       CR_EBX
-};
-
 /*
  * Capabilities of Intel PT hardware, such as number of address bits or
  * supported output schemes, are cached and exported to userspace as "caps"
@@ -53,32 +47,6 @@ enum cpuid_regs {
  * width encoded in IP-related packets), and event configuration (bitmasks with
  * permitted values for certain bit fields).
  */
-#define PT_CAP(_n, _l, _r, _m)                                         \
-       [PT_CAP_ ## _n] = { .name = __stringify(_n), .leaf = _l,        \
-                           .reg = _r, .mask = _m }
-
-static struct pt_cap_desc {
-       const char      *name;
-       u32             leaf;
-       u8              reg;
-       u32             mask;
-} pt_caps[] = {
-       PT_CAP(max_subleaf,             0, CR_EAX, 0xffffffff),
-       PT_CAP(cr3_filtering,           0, CR_EBX, BIT(0)),
-       PT_CAP(topa_output,             0, CR_ECX, BIT(0)),
-       PT_CAP(topa_multiple_entries,   0, CR_ECX, BIT(1)),
-       PT_CAP(payloads_lip,            0, CR_ECX, BIT(31)),
-};
-
-static u32 pt_cap_get(enum pt_capabilities cap)
-{
-       struct pt_cap_desc *cd = &pt_caps[cap];
-       u32 c = pt_pmu.caps[cd->leaf * 4 + cd->reg];
-       unsigned int shift = __ffs(cd->mask);
-
-       return (c & cd->mask) >> shift;
-}
-
 static ssize_t pt_cap_show(struct device *cdev,
                           struct device_attribute *attr,
                           char *buf)
@@ -121,35 +89,31 @@ static int __init pt_pmu_hw_init(void)
        size_t size;
        int ret;
        long i;
+       int cap_num;
 
        attrs = NULL;
        ret = -ENODEV;
        if (!test_cpu_cap(&boot_cpu_data, X86_FEATURE_INTEL_PT))
                goto fail;
 
-       for (i = 0; i < PT_CPUID_LEAVES; i++) {
-               cpuid_count(20, i,
-                           &pt_pmu.caps[CR_EAX + i*4],
-                           &pt_pmu.caps[CR_EBX + i*4],
-                           &pt_pmu.caps[CR_ECX + i*4],
-                           &pt_pmu.caps[CR_EDX + i*4]);
-       }
+       pt_cap_init();
+       cap_num = pt_cap_num();
 
        ret = -ENOMEM;
-       size = sizeof(struct attribute *) * (ARRAY_SIZE(pt_caps)+1);
+       size = sizeof(struct attribute *) * (cap_num+1);
        attrs = kzalloc(size, GFP_KERNEL);
        if (!attrs)
                goto fail;
 
-       size = sizeof(struct dev_ext_attribute) * (ARRAY_SIZE(pt_caps)+1);
+       size = sizeof(struct dev_ext_attribute) * (cap_num+1);
        de_attrs = kzalloc(size, GFP_KERNEL);
        if (!de_attrs)
                goto fail;
 
-       for (i = 0; i < ARRAY_SIZE(pt_caps); i++) {
+       for (i = 0; i < cap_num; i++) {
                struct dev_ext_attribute *de_attr = de_attrs + i;
 
-               de_attr->attr.attr.name = pt_caps[i].name;
+               de_attr->attr.attr.name = pt_cap_name(i);
 
                sysfs_attr_init(&de_attr->attr.attr);
 
-- 
1.7.1


--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to