Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751851AbbG2EwP (ORCPT ); Wed, 29 Jul 2015 00:52:15 -0400 Received: from mgwkm01.jp.fujitsu.com ([202.219.69.168]:65228 "EHLO mgwkm01.jp.fujitsu.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751676AbbG2EwK (ORCPT ); Wed, 29 Jul 2015 00:52:10 -0400 X-SecurityPolicyCheck: OK by SHieldMailChecker v2.2.3 X-SHieldMailCheckerPolicyVersion: FJ-ISEC-20140219-2 From: Takao Indoh To: Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , Peter Zijlstra , Arnaldo Carvalho de Melo , Alexander Shishkin , Vivek Goyal CC: , Subject: [PATCH RFC 1/3] x86: Add Intel PT common files Date: Wed, 29 Jul 2015 13:51:34 +0900 Message-ID: <1438145496-5932-2-git-send-email-indou.takao@jp.fujitsu.com> X-Mailer: git-send-email 2.4.5 In-Reply-To: <1438145496-5932-1-git-send-email-indou.takao@jp.fujitsu.com> References: <1438145496-5932-1-git-send-email-indou.takao@jp.fujitsu.com> MIME-Version: 1.0 Content-Type: text/plain X-SecurityPolicyCheck-GC: OK by FENCE-Mail X-TM-AS-MML: disable Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 14201 Lines: 527 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 --- 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 +#include + +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 #include #include +#include #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 majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/