Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar: "A couple of kernel side fixes: - Fix the Intel uncore driver on certain hardware configurations - Fix a CPU hotplug related memory allocation bug - Remove a spurious WARN() ... plus also a handful of perf tooling fixes" * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf script python: Add Python3 support to tests/attr.py perf trace: Support multiple "vfs_getname" probes perf symbols: Filter out hidden symbols from labels perf symbols: Add fallback definitions for GELF_ST_VISIBILITY() tools headers uapi: Sync linux/in.h copy from the kernel sources perf clang: Do not use 'return std::move(something)' perf mem/c2c: Fix perf_mem_events to support powerpc perf tests evsel-tp-sched: Fix bitwise operator perf/core: Don't WARN() for impossible ring-buffer sizes perf/x86/intel: Delay memory deallocation until x86_pmu_dead_cpu() perf/x86/intel/uncore: Add Node ID mask
This commit is contained in:
Коммит
212146f080
|
@ -3558,6 +3558,14 @@ static void free_excl_cntrs(int cpu)
|
|||
}
|
||||
|
||||
static void intel_pmu_cpu_dying(int cpu)
|
||||
{
|
||||
fini_debug_store_on_cpu(cpu);
|
||||
|
||||
if (x86_pmu.counter_freezing)
|
||||
disable_counter_freeze();
|
||||
}
|
||||
|
||||
static void intel_pmu_cpu_dead(int cpu)
|
||||
{
|
||||
struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
|
||||
struct intel_shared_regs *pc;
|
||||
|
@ -3570,11 +3578,6 @@ static void intel_pmu_cpu_dying(int cpu)
|
|||
}
|
||||
|
||||
free_excl_cntrs(cpu);
|
||||
|
||||
fini_debug_store_on_cpu(cpu);
|
||||
|
||||
if (x86_pmu.counter_freezing)
|
||||
disable_counter_freeze();
|
||||
}
|
||||
|
||||
static void intel_pmu_sched_task(struct perf_event_context *ctx,
|
||||
|
@ -3663,6 +3666,7 @@ static __initconst const struct x86_pmu core_pmu = {
|
|||
.cpu_prepare = intel_pmu_cpu_prepare,
|
||||
.cpu_starting = intel_pmu_cpu_starting,
|
||||
.cpu_dying = intel_pmu_cpu_dying,
|
||||
.cpu_dead = intel_pmu_cpu_dead,
|
||||
};
|
||||
|
||||
static struct attribute *intel_pmu_attrs[];
|
||||
|
@ -3703,6 +3707,8 @@ static __initconst const struct x86_pmu intel_pmu = {
|
|||
.cpu_prepare = intel_pmu_cpu_prepare,
|
||||
.cpu_starting = intel_pmu_cpu_starting,
|
||||
.cpu_dying = intel_pmu_cpu_dying,
|
||||
.cpu_dead = intel_pmu_cpu_dead,
|
||||
|
||||
.guest_get_msrs = intel_guest_get_msrs,
|
||||
.sched_task = intel_pmu_sched_task,
|
||||
};
|
||||
|
|
|
@ -1222,6 +1222,8 @@ static struct pci_driver snbep_uncore_pci_driver = {
|
|||
.id_table = snbep_uncore_pci_ids,
|
||||
};
|
||||
|
||||
#define NODE_ID_MASK 0x7
|
||||
|
||||
/*
|
||||
* build pci bus to socket mapping
|
||||
*/
|
||||
|
@ -1243,7 +1245,7 @@ static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool
|
|||
err = pci_read_config_dword(ubox_dev, nodeid_loc, &config);
|
||||
if (err)
|
||||
break;
|
||||
nodeid = config;
|
||||
nodeid = config & NODE_ID_MASK;
|
||||
/* get the Node ID mapping */
|
||||
err = pci_read_config_dword(ubox_dev, idmap_loc, &config);
|
||||
if (err)
|
||||
|
|
|
@ -734,6 +734,9 @@ struct ring_buffer *rb_alloc(int nr_pages, long watermark, int cpu, int flags)
|
|||
size = sizeof(struct ring_buffer);
|
||||
size += nr_pages * sizeof(void *);
|
||||
|
||||
if (order_base_2(size) >= MAX_ORDER)
|
||||
goto fail;
|
||||
|
||||
rb = kzalloc(size, GFP_KERNEL);
|
||||
if (!rb)
|
||||
goto fail;
|
||||
|
|
|
@ -268,7 +268,7 @@ struct sockaddr_in {
|
|||
#define IN_MULTICAST(a) IN_CLASSD(a)
|
||||
#define IN_MULTICAST_NET 0xe0000000
|
||||
|
||||
#define IN_BADCLASS(a) ((((long int) (a) ) == 0xffffffff)
|
||||
#define IN_BADCLASS(a) (((long int) (a) ) == (long int)0xffffffff)
|
||||
#define IN_EXPERIMENTAL(a) IN_BADCLASS((a))
|
||||
|
||||
#define IN_CLASSE(a) ((((long int) (a)) & 0xf0000000) == 0xf0000000)
|
||||
|
|
|
@ -19,8 +19,11 @@ C2C stands for Cache To Cache.
|
|||
The perf c2c tool provides means for Shared Data C2C/HITM analysis. It allows
|
||||
you to track down the cacheline contentions.
|
||||
|
||||
The tool is based on x86's load latency and precise store facility events
|
||||
provided by Intel CPUs. These events provide:
|
||||
On x86, the tool is based on load latency and precise store facility events
|
||||
provided by Intel CPUs. On PowerPC, the tool uses random instruction sampling
|
||||
with thresholding feature.
|
||||
|
||||
These events provide:
|
||||
- memory address of the access
|
||||
- type of the access (load and store details)
|
||||
- latency (in cycles) of the load access
|
||||
|
@ -46,7 +49,7 @@ RECORD OPTIONS
|
|||
|
||||
-l::
|
||||
--ldlat::
|
||||
Configure mem-loads latency.
|
||||
Configure mem-loads latency. (x86 only)
|
||||
|
||||
-k::
|
||||
--all-kernel::
|
||||
|
@ -119,11 +122,16 @@ Following perf record options are configured by default:
|
|||
-W,-d,--phys-data,--sample-cpu
|
||||
|
||||
Unless specified otherwise with '-e' option, following events are monitored by
|
||||
default:
|
||||
default on x86:
|
||||
|
||||
cpu/mem-loads,ldlat=30/P
|
||||
cpu/mem-stores/P
|
||||
|
||||
and following on PowerPC:
|
||||
|
||||
cpu/mem-loads/
|
||||
cpu/mem-stores/
|
||||
|
||||
User can pass any 'perf record' option behind '--' mark, like (to enable
|
||||
callchains and system wide monitoring):
|
||||
|
||||
|
|
|
@ -82,7 +82,7 @@ RECORD OPTIONS
|
|||
Be more verbose (show counter open errors, etc)
|
||||
|
||||
--ldlat <n>::
|
||||
Specify desired latency for loads event.
|
||||
Specify desired latency for loads event. (x86 only)
|
||||
|
||||
In addition, for report all perf report options are valid, and for record
|
||||
all perf record options.
|
||||
|
|
|
@ -2,6 +2,7 @@ libperf-y += header.o
|
|||
libperf-y += sym-handling.o
|
||||
libperf-y += kvm-stat.o
|
||||
libperf-y += perf_regs.o
|
||||
libperf-y += mem-events.o
|
||||
|
||||
libperf-$(CONFIG_DWARF) += dwarf-regs.o
|
||||
libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
#include "mem-events.h"
|
||||
|
||||
/* PowerPC does not support 'ldlat' parameter. */
|
||||
char *perf_mem_events__name(int i)
|
||||
{
|
||||
if (i == PERF_MEM_EVENTS__LOAD)
|
||||
return (char *) "cpu/mem-loads/";
|
||||
|
||||
return (char *) "cpu/mem-stores/";
|
||||
}
|
|
@ -2514,19 +2514,30 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
|
|||
|
||||
static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
|
||||
{
|
||||
struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
|
||||
bool found = false;
|
||||
struct perf_evsel *evsel, *tmp;
|
||||
struct parse_events_error err = { .idx = 0, };
|
||||
int ret = parse_events(evlist, "probe:vfs_getname*", &err);
|
||||
|
||||
if (IS_ERR(evsel))
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
if (perf_evsel__field(evsel, "pathname") == NULL) {
|
||||
evlist__for_each_entry_safe(evlist, evsel, tmp) {
|
||||
if (!strstarts(perf_evsel__name(evsel), "probe:vfs_getname"))
|
||||
continue;
|
||||
|
||||
if (perf_evsel__field(evsel, "pathname")) {
|
||||
evsel->handler = trace__vfs_getname;
|
||||
found = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
list_del_init(&evsel->node);
|
||||
evsel->evlist = NULL;
|
||||
perf_evsel__delete(evsel);
|
||||
return false;
|
||||
}
|
||||
|
||||
evsel->handler = trace__vfs_getname;
|
||||
perf_evlist__add(evlist, evsel);
|
||||
return true;
|
||||
return found;
|
||||
}
|
||||
|
||||
static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#! /usr/bin/python
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
|
||||
from __future__ import print_function
|
||||
|
||||
import os
|
||||
import sys
|
||||
import glob
|
||||
|
@ -8,7 +10,11 @@ import optparse
|
|||
import tempfile
|
||||
import logging
|
||||
import shutil
|
||||
import ConfigParser
|
||||
|
||||
try:
|
||||
import configparser
|
||||
except ImportError:
|
||||
import ConfigParser as configparser
|
||||
|
||||
def data_equal(a, b):
|
||||
# Allow multiple values in assignment separated by '|'
|
||||
|
@ -100,20 +106,20 @@ class Event(dict):
|
|||
def equal(self, other):
|
||||
for t in Event.terms:
|
||||
log.debug(" [%s] %s %s" % (t, self[t], other[t]));
|
||||
if not self.has_key(t) or not other.has_key(t):
|
||||
if t not in self or t not in other:
|
||||
return False
|
||||
if not data_equal(self[t], other[t]):
|
||||
return False
|
||||
return True
|
||||
|
||||
def optional(self):
|
||||
if self.has_key('optional') and self['optional'] == '1':
|
||||
if 'optional' in self and self['optional'] == '1':
|
||||
return True
|
||||
return False
|
||||
|
||||
def diff(self, other):
|
||||
for t in Event.terms:
|
||||
if not self.has_key(t) or not other.has_key(t):
|
||||
if t not in self or t not in other:
|
||||
continue
|
||||
if not data_equal(self[t], other[t]):
|
||||
log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))
|
||||
|
@ -134,7 +140,7 @@ class Event(dict):
|
|||
# - expected values assignments
|
||||
class Test(object):
|
||||
def __init__(self, path, options):
|
||||
parser = ConfigParser.SafeConfigParser()
|
||||
parser = configparser.SafeConfigParser()
|
||||
parser.read(path)
|
||||
|
||||
log.warning("running '%s'" % path)
|
||||
|
@ -193,7 +199,7 @@ class Test(object):
|
|||
return True
|
||||
|
||||
def load_events(self, path, events):
|
||||
parser_event = ConfigParser.SafeConfigParser()
|
||||
parser_event = configparser.SafeConfigParser()
|
||||
parser_event.read(path)
|
||||
|
||||
# The event record section header contains 'event' word,
|
||||
|
@ -207,7 +213,7 @@ class Test(object):
|
|||
# Read parent event if there's any
|
||||
if (':' in section):
|
||||
base = section[section.index(':') + 1:]
|
||||
parser_base = ConfigParser.SafeConfigParser()
|
||||
parser_base = configparser.SafeConfigParser()
|
||||
parser_base.read(self.test_dir + '/' + base)
|
||||
base_items = parser_base.items('event')
|
||||
|
||||
|
@ -322,9 +328,9 @@ def run_tests(options):
|
|||
for f in glob.glob(options.test_dir + '/' + options.test):
|
||||
try:
|
||||
Test(f, options).run()
|
||||
except Unsup, obj:
|
||||
except Unsup as obj:
|
||||
log.warning("unsupp %s" % obj.getMsg())
|
||||
except Notest, obj:
|
||||
except Notest as obj:
|
||||
log.warning("skipped %s" % obj.getMsg())
|
||||
|
||||
def setup_log(verbose):
|
||||
|
@ -363,7 +369,7 @@ def main():
|
|||
parser.add_option("-p", "--perf",
|
||||
action="store", type="string", dest="perf")
|
||||
parser.add_option("-v", "--verbose",
|
||||
action="count", dest="verbose")
|
||||
default=0, action="count", dest="verbose")
|
||||
|
||||
options, args = parser.parse_args()
|
||||
if args:
|
||||
|
@ -373,7 +379,7 @@ def main():
|
|||
setup_log(options.verbose)
|
||||
|
||||
if not options.test_dir:
|
||||
print 'FAILED no -d option specified'
|
||||
print('FAILED no -d option specified')
|
||||
sys.exit(-1)
|
||||
|
||||
if not options.test:
|
||||
|
@ -382,8 +388,8 @@ def main():
|
|||
try:
|
||||
run_tests(options)
|
||||
|
||||
except Fail, obj:
|
||||
print "FAILED %s" % obj.getMsg();
|
||||
except Fail as obj:
|
||||
print("FAILED %s" % obj.getMsg())
|
||||
sys.exit(-1)
|
||||
|
||||
sys.exit(0)
|
||||
|
|
|
@ -17,7 +17,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
|
|||
return -1;
|
||||
}
|
||||
|
||||
is_signed = !!(field->flags | TEP_FIELD_IS_SIGNED);
|
||||
is_signed = !!(field->flags & TEP_FIELD_IS_SIGNED);
|
||||
if (should_be_signed && !is_signed) {
|
||||
pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n",
|
||||
evsel->name, name, is_signed, should_be_signed);
|
||||
|
|
|
@ -160,7 +160,7 @@ getBPFObjectFromModule(llvm::Module *Module)
|
|||
}
|
||||
PM.run(*Module);
|
||||
|
||||
return std::move(Buffer);
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
|
|||
static char mem_loads_name[100];
|
||||
static bool mem_loads_name__init;
|
||||
|
||||
char *perf_mem_events__name(int i)
|
||||
char * __weak perf_mem_events__name(int i)
|
||||
{
|
||||
if (i == PERF_MEM_EVENTS__LOAD) {
|
||||
if (!mem_loads_name__init) {
|
||||
|
|
|
@ -19,6 +19,20 @@
|
|||
#define EM_AARCH64 183 /* ARM 64 bit */
|
||||
#endif
|
||||
|
||||
#ifndef ELF32_ST_VISIBILITY
|
||||
#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
|
||||
#endif
|
||||
|
||||
/* For ELF64 the definitions are the same. */
|
||||
#ifndef ELF64_ST_VISIBILITY
|
||||
#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
|
||||
#endif
|
||||
|
||||
/* How to extract information held in the st_other field. */
|
||||
#ifndef GELF_ST_VISIBILITY
|
||||
#define GELF_ST_VISIBILITY(val) ELF64_ST_VISIBILITY (val)
|
||||
#endif
|
||||
|
||||
typedef Elf64_Nhdr GElf_Nhdr;
|
||||
|
||||
#ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
|
||||
|
@ -87,6 +101,11 @@ static inline uint8_t elf_sym__type(const GElf_Sym *sym)
|
|||
return GELF_ST_TYPE(sym->st_info);
|
||||
}
|
||||
|
||||
static inline uint8_t elf_sym__visibility(const GElf_Sym *sym)
|
||||
{
|
||||
return GELF_ST_VISIBILITY(sym->st_other);
|
||||
}
|
||||
|
||||
#ifndef STT_GNU_IFUNC
|
||||
#define STT_GNU_IFUNC 10
|
||||
#endif
|
||||
|
@ -111,7 +130,9 @@ static inline int elf_sym__is_label(const GElf_Sym *sym)
|
|||
return elf_sym__type(sym) == STT_NOTYPE &&
|
||||
sym->st_name != 0 &&
|
||||
sym->st_shndx != SHN_UNDEF &&
|
||||
sym->st_shndx != SHN_ABS;
|
||||
sym->st_shndx != SHN_ABS &&
|
||||
elf_sym__visibility(sym) != STV_HIDDEN &&
|
||||
elf_sym__visibility(sym) != STV_INTERNAL;
|
||||
}
|
||||
|
||||
static bool elf_sym__filter(GElf_Sym *sym)
|
||||
|
|
Загрузка…
Ссылка в новой задаче