Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar: "Kernel side changes: - Add branch type profiling/tracing support. (Jin Yao) - Add the PERF_SAMPLE_PHYS_ADDR ABI to allow the tracing/profiling of physical memory addresses, where the PMU supports it. (Kan Liang) - Export some PMU capability details in the new /sys/bus/event_source/devices/cpu/caps/ sysfs directory. (Andi Kleen) - Aux data fixes and updates (Will Deacon) - kprobes fixes and updates (Masami Hiramatsu) - AMD uncore PMU driver fixes and updates (Janakarajan Natarajan) On the tooling side, here's a (limited!) list of highlights - there were many other changes that I could not list, see the shortlog and git history for details: UI improvements: - Implement a visual marker for fused x86 instructions in the annotate TUI browser, available now in 'perf report', more work needed to have it available as well in 'perf top' (Jin Yao) Further explanation from one of Jin's patches: │ ┌──cmpl $0x0,argp_program_version_hook 81.93 │ ├──je 20 │ │ lock cmpxchg %esi,0x38a9a4(%rip) │ │↓ jne 29 │ │↓ jmp 43 11.47 │20:└─→cmpxch %esi,0x38a999(%rip) That means the cmpl+je is a fused instruction pair and they should be considered together. - Record the branch type and then show statistics and info about in callchain entries (Jin Yao) Example from one of Jin's patches: # perf record -g -j any,save_type # perf report --branch-history --stdio --no-children 38.50% div.c:45 [.] main div | ---main div.c:42 (RET CROSS_2M cycles:2) compute_flag div.c:28 (cycles:2) compute_flag div.c:27 (RET CROSS_2M cycles:1) rand rand.c:28 (cycles:1) rand rand.c:28 (RET CROSS_2M cycles:1) __random random.c:298 (cycles:1) __random random.c:297 (COND_BWD CROSS_2M cycles:1) __random random.c:295 (cycles:1) __random random.c:295 (COND_BWD CROSS_2M cycles:1) __random random.c:295 (cycles:1) __random random.c:295 (RET CROSS_2M cycles:9) namespaces support: - Add initial support for namespaces, using setns to access files in namespaces, grabbing their build-ids, etc. (Krister Johansen) perf trace enhancements: - Beautify pkey_{alloc,free,mprotect} arguments in 'perf trace' (Arnaldo Carvalho de Melo) - Add initial 'clone' syscall args beautifier in 'perf trace' (Arnaldo Carvalho de Melo) - Ignore 'fd' and 'offset' args for MAP_ANONYMOUS in 'perf trace' (Arnaldo Carvalho de Melo) - Beautifiers for the 'cmd' arg of several ioctl types, including: sound, DRM, KVM, vhost virtio and perf_events. (Arnaldo Carvalho de Melo) - Add PERF_SAMPLE_CALLCHAIN and PERF_RECORD_MMAP[2] to 'perf data' CTF conversion, allowing CTF trace visualization tools to show callchains and to resolve symbols (Geneviève Bastien) - Beautify the fcntl syscall, which is an interesting one in the sense that infrastructure had to be put in place to change the formatters of some arguments according to the value in a previous one, i.e. cmd dictates how arg and the syscall return will be formatted. (Arnaldo Carvalho de Melo perf stat enhancements: - Use group read for event groups in 'perf stat', reducing overhead when groups are defined in the event specification, i.e. when using {} to enclose a list of events, asking them to be read at the same time, e.g.: "perf stat -e '{cycles,instructions}'" (Jiri Olsa) pipe mode improvements: - Process tracing data in 'perf annotate' pipe mode (David Carrillo-Cisneros) - Add header record types to pipe-mode, now this command: $ perf record -o - -e cycles sleep 1 | perf report --stdio --header Will show the same as in non-pipe mode, i.e. involving a perf.data file (David Carrillo-Cisneros) Vendor specific hardware event support updates/enhancements: - Update POWER9 vendor events tables (Sukadev Bhattiprolu) - Add POWER9 PMU events Sukadev (Bhattiprolu) - Support additional POWER8+ PVR in PMU mapfile (Shriya) - Add Skylake server uncore JSON vendor events (Andi Kleen) - Support exporting Intel PT data to sqlite3 with python perf scripts, this is in addition to the postgresql support that was already there (Adrian Hunter)" * 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (253 commits) perf symbols: Fix plt entry calculation for ARM and AARCH64 perf probe: Fix kprobe blacklist checking condition perf/x86: Fix caps/ for !Intel perf/core, x86: Add PERF_SAMPLE_PHYS_ADDR perf/core, pt, bts: Get rid of itrace_started perf trace beauty: Beautify pkey_{alloc,free,mprotect} arguments tools headers: Sync cpu features kernel ABI headers with tooling headers perf tools: Pass full path of FEATURES_DUMP perf tools: Robustify detection of clang binary tools lib: Allow external definition of CC, AR and LD perf tools: Allow external definition of flex and bison binary names tools build tests: Don't hardcode gcc name perf report: Group stat values on global event id perf values: Zero value buffers perf values: Fix allocation check perf values: Fix thread index bug perf report: Add dump_read function perf record: Set read_format for inherit_stat perf c2c: Fix remote HITM detection for Skylake perf tools: Fix static build with newer toolchains ...
This commit is contained in:
commit
9657752cb5
|
@ -61,6 +61,7 @@ show up in /proc/sys/kernel:
|
|||
- perf_cpu_time_max_percent
|
||||
- perf_event_paranoid
|
||||
- perf_event_max_stack
|
||||
- perf_event_mlock_kb
|
||||
- perf_event_max_contexts_per_stack
|
||||
- pid_max
|
||||
- powersave-nap [ PPC only ]
|
||||
|
@ -654,7 +655,9 @@ Controls use of the performance events system by unprivileged
|
|||
users (without CAP_SYS_ADMIN). The default value is 2.
|
||||
|
||||
-1: Allow use of (almost) all events by all users
|
||||
>=0: Disallow raw tracepoint access by users without CAP_IOC_LOCK
|
||||
Ignore mlock limit after perf_event_mlock_kb without CAP_IPC_LOCK
|
||||
>=0: Disallow ftrace function tracepoint by users without CAP_SYS_ADMIN
|
||||
Disallow raw tracepoint access by users without CAP_SYS_ADMIN
|
||||
>=1: Disallow CPU event access by users without CAP_SYS_ADMIN
|
||||
>=2: Disallow kernel profiling by users without CAP_SYS_ADMIN
|
||||
|
||||
|
@ -673,6 +676,14 @@ The default value is 127.
|
|||
|
||||
==============================================================
|
||||
|
||||
perf_event_mlock_kb:
|
||||
|
||||
Control size of per-cpu ring buffer not counted agains mlock limit.
|
||||
|
||||
The default value is 512 + 1 page
|
||||
|
||||
==============================================================
|
||||
|
||||
perf_event_max_contexts_per_stack:
|
||||
|
||||
Controls maximum number of stack frame context entries for
|
||||
|
|
|
@ -18,7 +18,6 @@ struct undef_hook {
|
|||
void register_undef_hook(struct undef_hook *hook);
|
||||
void unregister_undef_hook(struct undef_hook *hook);
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
static inline int __in_irqentry_text(unsigned long ptr)
|
||||
{
|
||||
extern char __irqentry_text_start[];
|
||||
|
@ -27,12 +26,6 @@ static inline int __in_irqentry_text(unsigned long ptr)
|
|||
return ptr >= (unsigned long)&__irqentry_text_start &&
|
||||
ptr < (unsigned long)&__irqentry_text_end;
|
||||
}
|
||||
#else
|
||||
static inline int __in_irqentry_text(unsigned long ptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int in_exception_text(unsigned long ptr)
|
||||
{
|
||||
|
|
|
@ -37,18 +37,11 @@ void unregister_undef_hook(struct undef_hook *hook);
|
|||
|
||||
void arm64_notify_segfault(struct pt_regs *regs, unsigned long addr);
|
||||
|
||||
#ifdef CONFIG_FUNCTION_GRAPH_TRACER
|
||||
static inline int __in_irqentry_text(unsigned long ptr)
|
||||
{
|
||||
return ptr >= (unsigned long)&__irqentry_text_start &&
|
||||
ptr < (unsigned long)&__irqentry_text_end;
|
||||
}
|
||||
#else
|
||||
static inline int __in_irqentry_text(unsigned long ptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline int in_exception_text(unsigned long ptr)
|
||||
{
|
||||
|
|
|
@ -227,7 +227,7 @@ static void crisv32_arbiter_config(int arbiter, int region, int unused_slots)
|
|||
}
|
||||
}
|
||||
|
||||
extern char _stext, _etext;
|
||||
extern char _stext[], _etext[];
|
||||
|
||||
static void crisv32_arbiter_init(void)
|
||||
{
|
||||
|
@ -265,7 +265,7 @@ static void crisv32_arbiter_init(void)
|
|||
|
||||
#ifndef CONFIG_ETRAX_KGDB
|
||||
/* Global watch for writes to kernel text segment. */
|
||||
crisv32_arbiter_watch(virt_to_phys(&_stext), &_etext - &_stext,
|
||||
crisv32_arbiter_watch(virt_to_phys(_stext), _etext - _stext,
|
||||
MARB_CLIENTS(arbiter_all_clients, arbiter_bar_all_clients),
|
||||
arbiter_all_write, NULL);
|
||||
#endif
|
||||
|
|
|
@ -158,7 +158,7 @@ static void crisv32_arbiter_config(int region, int unused_slots)
|
|||
}
|
||||
}
|
||||
|
||||
extern char _stext, _etext;
|
||||
extern char _stext[], _etext[];
|
||||
|
||||
static void crisv32_arbiter_init(void)
|
||||
{
|
||||
|
@ -190,7 +190,7 @@ static void crisv32_arbiter_init(void)
|
|||
|
||||
#ifndef CONFIG_ETRAX_KGDB
|
||||
/* Global watch for writes to kernel text segment. */
|
||||
crisv32_arbiter_watch(virt_to_phys(&_stext), &_etext - &_stext,
|
||||
crisv32_arbiter_watch(virt_to_phys(_stext), _etext - _stext,
|
||||
arbiter_all_clients, arbiter_all_write, NULL);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ void (*nmi_handler)(struct pt_regs *);
|
|||
void show_trace(unsigned long *stack)
|
||||
{
|
||||
unsigned long addr, module_start, module_end;
|
||||
extern char _stext, _etext;
|
||||
extern char _stext[], _etext[];
|
||||
int i;
|
||||
|
||||
pr_err("\nCall Trace: ");
|
||||
|
@ -69,8 +69,8 @@ void show_trace(unsigned long *stack)
|
|||
* down the cause of the crash will be able to figure
|
||||
* out the call path that was taken.
|
||||
*/
|
||||
if (((addr >= (unsigned long)&_stext) &&
|
||||
(addr <= (unsigned long)&_etext)) ||
|
||||
if (((addr >= (unsigned long)_stext) &&
|
||||
(addr <= (unsigned long)_etext)) ||
|
||||
((addr >= module_start) && (addr <= module_end))) {
|
||||
#ifdef CONFIG_KALLSYMS
|
||||
print_ip_sym(addr);
|
||||
|
|
|
@ -33,9 +33,9 @@ extern unsigned long *_interrupt_redirect_table;
|
|||
#define TRAP2_VEC 10
|
||||
#define TRAP3_VEC 11
|
||||
|
||||
extern char _start, _etext;
|
||||
extern char _start[], _etext[];
|
||||
#define check_kernel_text(addr) \
|
||||
((addr >= (unsigned long)(&_start)) && \
|
||||
(addr < (unsigned long)(&_etext)) && !(addr & 1))
|
||||
((addr >= (unsigned long)(_start)) && \
|
||||
(addr < (unsigned long)(_etext)) && !(addr & 1))
|
||||
|
||||
#endif /* _H8300_TRAPS_H */
|
||||
|
|
|
@ -2039,7 +2039,8 @@ static void record_and_restart(struct perf_event *event, unsigned long val,
|
|||
|
||||
perf_sample_data_init(&data, ~0ULL, event->hw.last_period);
|
||||
|
||||
if (event->attr.sample_type & PERF_SAMPLE_ADDR)
|
||||
if (event->attr.sample_type &
|
||||
(PERF_SAMPLE_ADDR | PERF_SAMPLE_PHYS_ADDR))
|
||||
perf_get_data_addr(regs, &data.addr);
|
||||
|
||||
if (event->attr.sample_type & PERF_SAMPLE_BRANCH_STACK) {
|
||||
|
|
|
@ -675,13 +675,8 @@ apicinterrupt3 \num trace(\sym) smp_trace(\sym)
|
|||
#endif
|
||||
|
||||
/* Make sure APIC interrupt handlers end up in the irqentry section: */
|
||||
#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN)
|
||||
# define PUSH_SECTION_IRQENTRY .pushsection .irqentry.text, "ax"
|
||||
# define POP_SECTION_IRQENTRY .popsection
|
||||
#else
|
||||
# define PUSH_SECTION_IRQENTRY
|
||||
# define POP_SECTION_IRQENTRY
|
||||
#endif
|
||||
#define PUSH_SECTION_IRQENTRY .pushsection .irqentry.text, "ax"
|
||||
#define POP_SECTION_IRQENTRY .popsection
|
||||
|
||||
.macro apicinterrupt num sym do_sym
|
||||
PUSH_SECTION_IRQENTRY
|
||||
|
|
|
@ -400,11 +400,24 @@ static int amd_uncore_cpu_starting(unsigned int cpu)
|
|||
|
||||
if (amd_uncore_llc) {
|
||||
unsigned int apicid = cpu_data(cpu).apicid;
|
||||
unsigned int nshared;
|
||||
unsigned int nshared, subleaf, prev_eax = 0;
|
||||
|
||||
uncore = *per_cpu_ptr(amd_uncore_llc, cpu);
|
||||
cpuid_count(0x8000001d, 2, &eax, &ebx, &ecx, &edx);
|
||||
nshared = ((eax >> 14) & 0xfff) + 1;
|
||||
/*
|
||||
* Iterate over Cache Topology Definition leaves until no
|
||||
* more cache descriptions are available.
|
||||
*/
|
||||
for (subleaf = 0; subleaf < 5; subleaf++) {
|
||||
cpuid_count(0x8000001d, subleaf, &eax, &ebx, &ecx, &edx);
|
||||
|
||||
/* EAX[0:4] gives type of cache */
|
||||
if (!(eax & 0x1f))
|
||||
break;
|
||||
|
||||
prev_eax = eax;
|
||||
}
|
||||
nshared = ((prev_eax >> 14) & 0xfff) + 1;
|
||||
|
||||
uncore->id = apicid - (apicid % nshared);
|
||||
|
||||
uncore = amd_uncore_find_online_sibling(uncore, amd_uncore_llc);
|
||||
|
@ -555,7 +568,7 @@ static int __init amd_uncore_init(void)
|
|||
ret = 0;
|
||||
}
|
||||
|
||||
if (boot_cpu_has(X86_FEATURE_PERFCTR_L2)) {
|
||||
if (boot_cpu_has(X86_FEATURE_PERFCTR_LLC)) {
|
||||
amd_uncore_llc = alloc_percpu(struct amd_uncore *);
|
||||
if (!amd_uncore_llc) {
|
||||
ret = -ENOMEM;
|
||||
|
|
|
@ -487,22 +487,28 @@ static inline int precise_br_compat(struct perf_event *event)
|
|||
return m == b;
|
||||
}
|
||||
|
||||
int x86_pmu_max_precise(void)
|
||||
{
|
||||
int precise = 0;
|
||||
|
||||
/* Support for constant skid */
|
||||
if (x86_pmu.pebs_active && !x86_pmu.pebs_broken) {
|
||||
precise++;
|
||||
|
||||
/* Support for IP fixup */
|
||||
if (x86_pmu.lbr_nr || x86_pmu.intel_cap.pebs_format >= 2)
|
||||
precise++;
|
||||
|
||||
if (x86_pmu.pebs_prec_dist)
|
||||
precise++;
|
||||
}
|
||||
return precise;
|
||||
}
|
||||
|
||||
int x86_pmu_hw_config(struct perf_event *event)
|
||||
{
|
||||
if (event->attr.precise_ip) {
|
||||
int precise = 0;
|
||||
|
||||
/* Support for constant skid */
|
||||
if (x86_pmu.pebs_active && !x86_pmu.pebs_broken) {
|
||||
precise++;
|
||||
|
||||
/* Support for IP fixup */
|
||||
if (x86_pmu.lbr_nr || x86_pmu.intel_cap.pebs_format >= 2)
|
||||
precise++;
|
||||
|
||||
if (x86_pmu.pebs_prec_dist)
|
||||
precise++;
|
||||
}
|
||||
int precise = x86_pmu_max_precise();
|
||||
|
||||
if (event->attr.precise_ip > precise)
|
||||
return -EOPNOTSUPP;
|
||||
|
@ -1751,6 +1757,7 @@ ssize_t x86_event_sysfs_show(char *page, u64 config, u64 event)
|
|||
}
|
||||
|
||||
static struct attribute_group x86_pmu_attr_group;
|
||||
static struct attribute_group x86_pmu_caps_group;
|
||||
|
||||
static int __init init_hw_perf_events(void)
|
||||
{
|
||||
|
@ -1799,6 +1806,14 @@ static int __init init_hw_perf_events(void)
|
|||
|
||||
x86_pmu_format_group.attrs = x86_pmu.format_attrs;
|
||||
|
||||
if (x86_pmu.caps_attrs) {
|
||||
struct attribute **tmp;
|
||||
|
||||
tmp = merge_attr(x86_pmu_caps_group.attrs, x86_pmu.caps_attrs);
|
||||
if (!WARN_ON(!tmp))
|
||||
x86_pmu_caps_group.attrs = tmp;
|
||||
}
|
||||
|
||||
if (x86_pmu.event_attrs)
|
||||
x86_pmu_events_group.attrs = x86_pmu.event_attrs;
|
||||
|
||||
|
@ -2213,10 +2228,30 @@ static struct attribute_group x86_pmu_attr_group = {
|
|||
.attrs = x86_pmu_attrs,
|
||||
};
|
||||
|
||||
static ssize_t max_precise_show(struct device *cdev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", x86_pmu_max_precise());
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(max_precise);
|
||||
|
||||
static struct attribute *x86_pmu_caps_attrs[] = {
|
||||
&dev_attr_max_precise.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group x86_pmu_caps_group = {
|
||||
.name = "caps",
|
||||
.attrs = x86_pmu_caps_attrs,
|
||||
};
|
||||
|
||||
static const struct attribute_group *x86_pmu_attr_groups[] = {
|
||||
&x86_pmu_attr_group,
|
||||
&x86_pmu_format_group,
|
||||
&x86_pmu_events_group,
|
||||
&x86_pmu_caps_group,
|
||||
NULL,
|
||||
};
|
||||
|
||||
|
|
|
@ -268,7 +268,7 @@ static void bts_event_start(struct perf_event *event, int flags)
|
|||
bts->ds_back.bts_absolute_maximum = cpuc->ds->bts_absolute_maximum;
|
||||
bts->ds_back.bts_interrupt_threshold = cpuc->ds->bts_interrupt_threshold;
|
||||
|
||||
event->hw.itrace_started = 1;
|
||||
perf_event_itrace_started(event);
|
||||
event->hw.state = 0;
|
||||
|
||||
__bts_event_start(event);
|
||||
|
|
|
@ -3415,12 +3415,26 @@ static struct attribute *intel_arch3_formats_attr[] = {
|
|||
&format_attr_any.attr,
|
||||
&format_attr_inv.attr,
|
||||
&format_attr_cmask.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static struct attribute *hsw_format_attr[] = {
|
||||
&format_attr_in_tx.attr,
|
||||
&format_attr_in_tx_cp.attr,
|
||||
&format_attr_offcore_rsp.attr,
|
||||
&format_attr_ldlat.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
&format_attr_offcore_rsp.attr, /* XXX do NHM/WSM + SNB breakout */
|
||||
&format_attr_ldlat.attr, /* PEBS load latency */
|
||||
NULL,
|
||||
static struct attribute *nhm_format_attr[] = {
|
||||
&format_attr_offcore_rsp.attr,
|
||||
&format_attr_ldlat.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute *slm_format_attr[] = {
|
||||
&format_attr_offcore_rsp.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute *skl_format_attr[] = {
|
||||
|
@ -3781,6 +3795,36 @@ static ssize_t freeze_on_smi_store(struct device *cdev,
|
|||
|
||||
static DEVICE_ATTR_RW(freeze_on_smi);
|
||||
|
||||
static ssize_t branches_show(struct device *cdev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", x86_pmu.lbr_nr);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(branches);
|
||||
|
||||
static struct attribute *lbr_attrs[] = {
|
||||
&dev_attr_branches.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static char pmu_name_str[30];
|
||||
|
||||
static ssize_t pmu_name_show(struct device *cdev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%s\n", pmu_name_str);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(pmu_name);
|
||||
|
||||
static struct attribute *intel_pmu_caps_attrs[] = {
|
||||
&dev_attr_pmu_name.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute *intel_pmu_attrs[] = {
|
||||
&dev_attr_freeze_on_smi.attr,
|
||||
NULL,
|
||||
|
@ -3795,6 +3839,8 @@ __init int intel_pmu_init(void)
|
|||
unsigned int unused;
|
||||
struct extra_reg *er;
|
||||
int version, i;
|
||||
struct attribute **extra_attr = NULL;
|
||||
char *name;
|
||||
|
||||
if (!cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON)) {
|
||||
switch (boot_cpu_data.x86) {
|
||||
|
@ -3862,6 +3908,7 @@ __init int intel_pmu_init(void)
|
|||
switch (boot_cpu_data.x86_model) {
|
||||
case INTEL_FAM6_CORE_YONAH:
|
||||
pr_cont("Core events, ");
|
||||
name = "core";
|
||||
break;
|
||||
|
||||
case INTEL_FAM6_CORE2_MEROM:
|
||||
|
@ -3877,6 +3924,7 @@ __init int intel_pmu_init(void)
|
|||
x86_pmu.event_constraints = intel_core2_event_constraints;
|
||||
x86_pmu.pebs_constraints = intel_core2_pebs_event_constraints;
|
||||
pr_cont("Core2 events, ");
|
||||
name = "core2";
|
||||
break;
|
||||
|
||||
case INTEL_FAM6_NEHALEM:
|
||||
|
@ -3905,8 +3953,11 @@ __init int intel_pmu_init(void)
|
|||
|
||||
intel_pmu_pebs_data_source_nhm();
|
||||
x86_add_quirk(intel_nehalem_quirk);
|
||||
x86_pmu.pebs_no_tlb = 1;
|
||||
extra_attr = nhm_format_attr;
|
||||
|
||||
pr_cont("Nehalem events, ");
|
||||
name = "nehalem";
|
||||
break;
|
||||
|
||||
case INTEL_FAM6_ATOM_PINEVIEW:
|
||||
|
@ -3923,6 +3974,7 @@ __init int intel_pmu_init(void)
|
|||
x86_pmu.pebs_constraints = intel_atom_pebs_event_constraints;
|
||||
x86_pmu.pebs_aliases = intel_pebs_aliases_core2;
|
||||
pr_cont("Atom events, ");
|
||||
name = "bonnell";
|
||||
break;
|
||||
|
||||
case INTEL_FAM6_ATOM_SILVERMONT1:
|
||||
|
@ -3940,7 +3992,9 @@ __init int intel_pmu_init(void)
|
|||
x86_pmu.extra_regs = intel_slm_extra_regs;
|
||||
x86_pmu.flags |= PMU_FL_HAS_RSP_1;
|
||||
x86_pmu.cpu_events = slm_events_attrs;
|
||||
extra_attr = slm_format_attr;
|
||||
pr_cont("Silvermont events, ");
|
||||
name = "silvermont";
|
||||
break;
|
||||
|
||||
case INTEL_FAM6_ATOM_GOLDMONT:
|
||||
|
@ -3965,7 +4019,9 @@ __init int intel_pmu_init(void)
|
|||
x86_pmu.lbr_pt_coexist = true;
|
||||
x86_pmu.flags |= PMU_FL_HAS_RSP_1;
|
||||
x86_pmu.cpu_events = glm_events_attrs;
|
||||
extra_attr = slm_format_attr;
|
||||
pr_cont("Goldmont events, ");
|
||||
name = "goldmont";
|
||||
break;
|
||||
|
||||
case INTEL_FAM6_ATOM_GEMINI_LAKE:
|
||||
|
@ -3991,7 +4047,9 @@ __init int intel_pmu_init(void)
|
|||
x86_pmu.cpu_events = glm_events_attrs;
|
||||
/* Goldmont Plus has 4-wide pipeline */
|
||||
event_attr_td_total_slots_scale_glm.event_str = "4";
|
||||
extra_attr = slm_format_attr;
|
||||
pr_cont("Goldmont plus events, ");
|
||||
name = "goldmont_plus";
|
||||
break;
|
||||
|
||||
case INTEL_FAM6_WESTMERE:
|
||||
|
@ -4020,7 +4078,9 @@ __init int intel_pmu_init(void)
|
|||
X86_CONFIG(.event=0xb1, .umask=0x3f, .inv=1, .cmask=1);
|
||||
|
||||
intel_pmu_pebs_data_source_nhm();
|
||||
extra_attr = nhm_format_attr;
|
||||
pr_cont("Westmere events, ");
|
||||
name = "westmere";
|
||||
break;
|
||||
|
||||
case INTEL_FAM6_SANDYBRIDGE:
|
||||
|
@ -4056,7 +4116,10 @@ __init int intel_pmu_init(void)
|
|||
intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =
|
||||
X86_CONFIG(.event=0xb1, .umask=0x01, .inv=1, .cmask=1);
|
||||
|
||||
extra_attr = nhm_format_attr;
|
||||
|
||||
pr_cont("SandyBridge events, ");
|
||||
name = "sandybridge";
|
||||
break;
|
||||
|
||||
case INTEL_FAM6_IVYBRIDGE:
|
||||
|
@ -4090,7 +4153,10 @@ __init int intel_pmu_init(void)
|
|||
intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =
|
||||
X86_CONFIG(.event=0x0e, .umask=0x01, .inv=1, .cmask=1);
|
||||
|
||||
extra_attr = nhm_format_attr;
|
||||
|
||||
pr_cont("IvyBridge events, ");
|
||||
name = "ivybridge";
|
||||
break;
|
||||
|
||||
|
||||
|
@ -4118,7 +4184,10 @@ __init int intel_pmu_init(void)
|
|||
x86_pmu.get_event_constraints = hsw_get_event_constraints;
|
||||
x86_pmu.cpu_events = hsw_events_attrs;
|
||||
x86_pmu.lbr_double_abort = true;
|
||||
extra_attr = boot_cpu_has(X86_FEATURE_RTM) ?
|
||||
hsw_format_attr : nhm_format_attr;
|
||||
pr_cont("Haswell events, ");
|
||||
name = "haswell";
|
||||
break;
|
||||
|
||||
case INTEL_FAM6_BROADWELL_CORE:
|
||||
|
@ -4154,7 +4223,10 @@ __init int intel_pmu_init(void)
|
|||
x86_pmu.get_event_constraints = hsw_get_event_constraints;
|
||||
x86_pmu.cpu_events = hsw_events_attrs;
|
||||
x86_pmu.limit_period = bdw_limit_period;
|
||||
extra_attr = boot_cpu_has(X86_FEATURE_RTM) ?
|
||||
hsw_format_attr : nhm_format_attr;
|
||||
pr_cont("Broadwell events, ");
|
||||
name = "broadwell";
|
||||
break;
|
||||
|
||||
case INTEL_FAM6_XEON_PHI_KNL:
|
||||
|
@ -4172,8 +4244,9 @@ __init int intel_pmu_init(void)
|
|||
/* all extra regs are per-cpu when HT is on */
|
||||
x86_pmu.flags |= PMU_FL_HAS_RSP_1;
|
||||
x86_pmu.flags |= PMU_FL_NO_HT_SHARING;
|
||||
|
||||
extra_attr = slm_format_attr;
|
||||
pr_cont("Knights Landing/Mill events, ");
|
||||
name = "knights-landing";
|
||||
break;
|
||||
|
||||
case INTEL_FAM6_SKYLAKE_MOBILE:
|
||||
|
@ -4203,11 +4276,14 @@ __init int intel_pmu_init(void)
|
|||
|
||||
x86_pmu.hw_config = hsw_hw_config;
|
||||
x86_pmu.get_event_constraints = hsw_get_event_constraints;
|
||||
x86_pmu.format_attrs = merge_attr(intel_arch3_formats_attr,
|
||||
skl_format_attr);
|
||||
WARN_ON(!x86_pmu.format_attrs);
|
||||
extra_attr = boot_cpu_has(X86_FEATURE_RTM) ?
|
||||
hsw_format_attr : nhm_format_attr;
|
||||
extra_attr = merge_attr(extra_attr, skl_format_attr);
|
||||
x86_pmu.cpu_events = hsw_events_attrs;
|
||||
intel_pmu_pebs_data_source_skl(
|
||||
boot_cpu_data.x86_model == INTEL_FAM6_SKYLAKE_X);
|
||||
pr_cont("Skylake events, ");
|
||||
name = "skylake";
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -4215,6 +4291,7 @@ __init int intel_pmu_init(void)
|
|||
case 1:
|
||||
x86_pmu.event_constraints = intel_v1_event_constraints;
|
||||
pr_cont("generic architected perfmon v1, ");
|
||||
name = "generic_arch_v1";
|
||||
break;
|
||||
default:
|
||||
/*
|
||||
|
@ -4222,10 +4299,19 @@ __init int intel_pmu_init(void)
|
|||
*/
|
||||
x86_pmu.event_constraints = intel_gen_event_constraints;
|
||||
pr_cont("generic architected perfmon, ");
|
||||
name = "generic_arch_v2+";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
snprintf(pmu_name_str, sizeof pmu_name_str, "%s", name);
|
||||
|
||||
if (version >= 2 && extra_attr) {
|
||||
x86_pmu.format_attrs = merge_attr(intel_arch3_formats_attr,
|
||||
extra_attr);
|
||||
WARN_ON(!x86_pmu.format_attrs);
|
||||
}
|
||||
|
||||
if (x86_pmu.num_counters > INTEL_PMC_MAX_GENERIC) {
|
||||
WARN(1, KERN_ERR "hw perf events %d > max(%d), clipping!",
|
||||
x86_pmu.num_counters, INTEL_PMC_MAX_GENERIC);
|
||||
|
@ -4272,8 +4358,13 @@ __init int intel_pmu_init(void)
|
|||
x86_pmu.lbr_nr = 0;
|
||||
}
|
||||
|
||||
if (x86_pmu.lbr_nr)
|
||||
x86_pmu.caps_attrs = intel_pmu_caps_attrs;
|
||||
|
||||
if (x86_pmu.lbr_nr) {
|
||||
x86_pmu.caps_attrs = merge_attr(x86_pmu.caps_attrs, lbr_attrs);
|
||||
pr_cont("%d-deep LBR, ", x86_pmu.lbr_nr);
|
||||
}
|
||||
|
||||
/*
|
||||
* Access extra MSR may cause #GP under certain circumstances.
|
||||
* E.g. KVM doesn't support offcore event
|
||||
|
|
|
@ -49,34 +49,47 @@ union intel_x86_pebs_dse {
|
|||
*/
|
||||
#define P(a, b) PERF_MEM_S(a, b)
|
||||
#define OP_LH (P(OP, LOAD) | P(LVL, HIT))
|
||||
#define LEVEL(x) P(LVLNUM, x)
|
||||
#define REM P(REMOTE, REMOTE)
|
||||
#define SNOOP_NONE_MISS (P(SNOOP, NONE) | P(SNOOP, MISS))
|
||||
|
||||
/* Version for Sandy Bridge and later */
|
||||
static u64 pebs_data_source[] = {
|
||||
P(OP, LOAD) | P(LVL, MISS) | P(LVL, L3) | P(SNOOP, NA),/* 0x00:ukn L3 */
|
||||
OP_LH | P(LVL, L1) | P(SNOOP, NONE), /* 0x01: L1 local */
|
||||
OP_LH | P(LVL, LFB) | P(SNOOP, NONE), /* 0x02: LFB hit */
|
||||
OP_LH | P(LVL, L2) | P(SNOOP, NONE), /* 0x03: L2 hit */
|
||||
OP_LH | P(LVL, L3) | P(SNOOP, NONE), /* 0x04: L3 hit */
|
||||
OP_LH | P(LVL, L3) | P(SNOOP, MISS), /* 0x05: L3 hit, snoop miss */
|
||||
OP_LH | P(LVL, L3) | P(SNOOP, HIT), /* 0x06: L3 hit, snoop hit */
|
||||
OP_LH | P(LVL, L3) | P(SNOOP, HITM), /* 0x07: L3 hit, snoop hitm */
|
||||
OP_LH | P(LVL, REM_CCE1) | P(SNOOP, HIT), /* 0x08: L3 miss snoop hit */
|
||||
OP_LH | P(LVL, REM_CCE1) | P(SNOOP, HITM), /* 0x09: L3 miss snoop hitm*/
|
||||
OP_LH | P(LVL, LOC_RAM) | P(SNOOP, HIT), /* 0x0a: L3 miss, shared */
|
||||
OP_LH | P(LVL, REM_RAM1) | P(SNOOP, HIT), /* 0x0b: L3 miss, shared */
|
||||
OP_LH | P(LVL, LOC_RAM) | SNOOP_NONE_MISS,/* 0x0c: L3 miss, excl */
|
||||
OP_LH | P(LVL, REM_RAM1) | SNOOP_NONE_MISS,/* 0x0d: L3 miss, excl */
|
||||
OP_LH | P(LVL, IO) | P(SNOOP, NONE), /* 0x0e: I/O */
|
||||
OP_LH | P(LVL, UNC) | P(SNOOP, NONE), /* 0x0f: uncached */
|
||||
P(OP, LOAD) | P(LVL, MISS) | LEVEL(L3) | P(SNOOP, NA),/* 0x00:ukn L3 */
|
||||
OP_LH | P(LVL, L1) | LEVEL(L1) | P(SNOOP, NONE), /* 0x01: L1 local */
|
||||
OP_LH | P(LVL, LFB) | LEVEL(LFB) | P(SNOOP, NONE), /* 0x02: LFB hit */
|
||||
OP_LH | P(LVL, L2) | LEVEL(L2) | P(SNOOP, NONE), /* 0x03: L2 hit */
|
||||
OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, NONE), /* 0x04: L3 hit */
|
||||
OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, MISS), /* 0x05: L3 hit, snoop miss */
|
||||
OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, HIT), /* 0x06: L3 hit, snoop hit */
|
||||
OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, HITM), /* 0x07: L3 hit, snoop hitm */
|
||||
OP_LH | P(LVL, REM_CCE1) | REM | LEVEL(L3) | P(SNOOP, HIT), /* 0x08: L3 miss snoop hit */
|
||||
OP_LH | P(LVL, REM_CCE1) | REM | LEVEL(L3) | P(SNOOP, HITM), /* 0x09: L3 miss snoop hitm*/
|
||||
OP_LH | P(LVL, LOC_RAM) | LEVEL(RAM) | P(SNOOP, HIT), /* 0x0a: L3 miss, shared */
|
||||
OP_LH | P(LVL, REM_RAM1) | REM | LEVEL(L3) | P(SNOOP, HIT), /* 0x0b: L3 miss, shared */
|
||||
OP_LH | P(LVL, LOC_RAM) | LEVEL(RAM) | SNOOP_NONE_MISS, /* 0x0c: L3 miss, excl */
|
||||
OP_LH | P(LVL, REM_RAM1) | LEVEL(RAM) | REM | SNOOP_NONE_MISS, /* 0x0d: L3 miss, excl */
|
||||
OP_LH | P(LVL, IO) | LEVEL(NA) | P(SNOOP, NONE), /* 0x0e: I/O */
|
||||
OP_LH | P(LVL, UNC) | LEVEL(NA) | P(SNOOP, NONE), /* 0x0f: uncached */
|
||||
};
|
||||
|
||||
/* Patch up minor differences in the bits */
|
||||
void __init intel_pmu_pebs_data_source_nhm(void)
|
||||
{
|
||||
pebs_data_source[0x05] = OP_LH | P(LVL, L3) | P(SNOOP, HIT);
|
||||
pebs_data_source[0x06] = OP_LH | P(LVL, L3) | P(SNOOP, HITM);
|
||||
pebs_data_source[0x07] = OP_LH | P(LVL, L3) | P(SNOOP, HITM);
|
||||
pebs_data_source[0x05] = OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, HIT);
|
||||
pebs_data_source[0x06] = OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, HITM);
|
||||
pebs_data_source[0x07] = OP_LH | P(LVL, L3) | LEVEL(L3) | P(SNOOP, HITM);
|
||||
}
|
||||
|
||||
void __init intel_pmu_pebs_data_source_skl(bool pmem)
|
||||
{
|
||||
u64 pmem_or_l4 = pmem ? LEVEL(PMEM) : LEVEL(L4);
|
||||
|
||||
pebs_data_source[0x08] = OP_LH | pmem_or_l4 | P(SNOOP, HIT);
|
||||
pebs_data_source[0x09] = OP_LH | pmem_or_l4 | REM | P(SNOOP, HIT);
|
||||
pebs_data_source[0x0b] = OP_LH | LEVEL(RAM) | REM | P(SNOOP, NONE);
|
||||
pebs_data_source[0x0c] = OP_LH | LEVEL(ANY_CACHE) | REM | P(SNOOPX, FWD);
|
||||
pebs_data_source[0x0d] = OP_LH | LEVEL(ANY_CACHE) | REM | P(SNOOP, HITM);
|
||||
}
|
||||
|
||||
static u64 precise_store_data(u64 status)
|
||||
|
@ -149,8 +162,6 @@ static u64 load_latency_data(u64 status)
|
|||
{
|
||||
union intel_x86_pebs_dse dse;
|
||||
u64 val;
|
||||
int model = boot_cpu_data.x86_model;
|
||||
int fam = boot_cpu_data.x86;
|
||||
|
||||
dse.val = status;
|
||||
|
||||
|
@ -162,8 +173,7 @@ static u64 load_latency_data(u64 status)
|
|||
/*
|
||||
* Nehalem models do not support TLB, Lock infos
|
||||
*/
|
||||
if (fam == 0x6 && (model == 26 || model == 30
|
||||
|| model == 31 || model == 46)) {
|
||||
if (x86_pmu.pebs_no_tlb) {
|
||||
val |= P(TLB, NA) | P(LOCK, NA);
|
||||
return val;
|
||||
}
|
||||
|
@ -1175,7 +1185,7 @@ static void setup_pebs_sample_data(struct perf_event *event,
|
|||
else
|
||||
regs->flags &= ~PERF_EFLAGS_EXACT;
|
||||
|
||||
if ((sample_type & PERF_SAMPLE_ADDR) &&
|
||||
if ((sample_type & (PERF_SAMPLE_ADDR | PERF_SAMPLE_PHYS_ADDR)) &&
|
||||
x86_pmu.intel_cap.pebs_format >= 1)
|
||||
data->addr = pebs->dla;
|
||||
|
||||
|
|
|
@ -109,6 +109,9 @@ enum {
|
|||
X86_BR_ZERO_CALL = 1 << 15,/* zero length call */
|
||||
X86_BR_CALL_STACK = 1 << 16,/* call stack */
|
||||
X86_BR_IND_JMP = 1 << 17,/* indirect jump */
|
||||
|
||||
X86_BR_TYPE_SAVE = 1 << 18,/* indicate to save branch type */
|
||||
|
||||
};
|
||||
|
||||
#define X86_BR_PLM (X86_BR_USER | X86_BR_KERNEL)
|
||||
|
@ -514,6 +517,7 @@ static void intel_pmu_lbr_read_32(struct cpu_hw_events *cpuc)
|
|||
cpuc->lbr_entries[i].in_tx = 0;
|
||||
cpuc->lbr_entries[i].abort = 0;
|
||||
cpuc->lbr_entries[i].cycles = 0;
|
||||
cpuc->lbr_entries[i].type = 0;
|
||||
cpuc->lbr_entries[i].reserved = 0;
|
||||
}
|
||||
cpuc->lbr_stack.nr = i;
|
||||
|
@ -600,6 +604,7 @@ static void intel_pmu_lbr_read_64(struct cpu_hw_events *cpuc)
|
|||
cpuc->lbr_entries[out].in_tx = in_tx;
|
||||
cpuc->lbr_entries[out].abort = abort;
|
||||
cpuc->lbr_entries[out].cycles = cycles;
|
||||
cpuc->lbr_entries[out].type = 0;
|
||||
cpuc->lbr_entries[out].reserved = 0;
|
||||
out++;
|
||||
}
|
||||
|
@ -677,6 +682,10 @@ static int intel_pmu_setup_sw_lbr_filter(struct perf_event *event)
|
|||
|
||||
if (br_type & PERF_SAMPLE_BRANCH_CALL)
|
||||
mask |= X86_BR_CALL | X86_BR_ZERO_CALL;
|
||||
|
||||
if (br_type & PERF_SAMPLE_BRANCH_TYPE_SAVE)
|
||||
mask |= X86_BR_TYPE_SAVE;
|
||||
|
||||
/*
|
||||
* stash actual user request into reg, it may
|
||||
* be used by fixup code for some CPU
|
||||
|
@ -930,6 +939,43 @@ static int branch_type(unsigned long from, unsigned long to, int abort)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#define X86_BR_TYPE_MAP_MAX 16
|
||||
|
||||
static int branch_map[X86_BR_TYPE_MAP_MAX] = {
|
||||
PERF_BR_CALL, /* X86_BR_CALL */
|
||||
PERF_BR_RET, /* X86_BR_RET */
|
||||
PERF_BR_SYSCALL, /* X86_BR_SYSCALL */
|
||||
PERF_BR_SYSRET, /* X86_BR_SYSRET */
|
||||
PERF_BR_UNKNOWN, /* X86_BR_INT */
|
||||
PERF_BR_UNKNOWN, /* X86_BR_IRET */
|
||||
PERF_BR_COND, /* X86_BR_JCC */
|
||||
PERF_BR_UNCOND, /* X86_BR_JMP */
|
||||
PERF_BR_UNKNOWN, /* X86_BR_IRQ */
|
||||
PERF_BR_IND_CALL, /* X86_BR_IND_CALL */
|
||||
PERF_BR_UNKNOWN, /* X86_BR_ABORT */
|
||||
PERF_BR_UNKNOWN, /* X86_BR_IN_TX */
|
||||
PERF_BR_UNKNOWN, /* X86_BR_NO_TX */
|
||||
PERF_BR_CALL, /* X86_BR_ZERO_CALL */
|
||||
PERF_BR_UNKNOWN, /* X86_BR_CALL_STACK */
|
||||
PERF_BR_IND, /* X86_BR_IND_JMP */
|
||||
};
|
||||
|
||||
static int
|
||||
common_branch_type(int type)
|
||||
{
|
||||
int i;
|
||||
|
||||
type >>= 2; /* skip X86_BR_USER and X86_BR_KERNEL */
|
||||
|
||||
if (type) {
|
||||
i = __ffs(type);
|
||||
if (i < X86_BR_TYPE_MAP_MAX)
|
||||
return branch_map[i];
|
||||
}
|
||||
|
||||
return PERF_BR_UNKNOWN;
|
||||
}
|
||||
|
||||
/*
|
||||
* implement actual branch filter based on user demand.
|
||||
* Hardware may not exactly satisfy that request, thus
|
||||
|
@ -946,7 +992,8 @@ intel_pmu_lbr_filter(struct cpu_hw_events *cpuc)
|
|||
bool compress = false;
|
||||
|
||||
/* if sampling all branches, then nothing to filter */
|
||||
if ((br_sel & X86_BR_ALL) == X86_BR_ALL)
|
||||
if (((br_sel & X86_BR_ALL) == X86_BR_ALL) &&
|
||||
((br_sel & X86_BR_TYPE_SAVE) != X86_BR_TYPE_SAVE))
|
||||
return;
|
||||
|
||||
for (i = 0; i < cpuc->lbr_stack.nr; i++) {
|
||||
|
@ -967,6 +1014,9 @@ intel_pmu_lbr_filter(struct cpu_hw_events *cpuc)
|
|||
cpuc->lbr_entries[i].from = 0;
|
||||
compress = true;
|
||||
}
|
||||
|
||||
if ((br_sel & X86_BR_TYPE_SAVE) == X86_BR_TYPE_SAVE)
|
||||
cpuc->lbr_entries[i].type = common_branch_type(type);
|
||||
}
|
||||
|
||||
if (!compress)
|
||||
|
|
|
@ -471,8 +471,9 @@ static void pt_config(struct perf_event *event)
|
|||
struct pt *pt = this_cpu_ptr(&pt_ctx);
|
||||
u64 reg;
|
||||
|
||||
if (!event->hw.itrace_started) {
|
||||
event->hw.itrace_started = 1;
|
||||
/* First round: clear STATUS, in particular the PSB byte counter. */
|
||||
if (!event->hw.config) {
|
||||
perf_event_itrace_started(event);
|
||||
wrmsrl(MSR_IA32_RTIT_STATUS, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ struct amd_nb {
|
|||
(PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_ADDR | \
|
||||
PERF_SAMPLE_ID | PERF_SAMPLE_CPU | PERF_SAMPLE_STREAM_ID | \
|
||||
PERF_SAMPLE_DATA_SRC | PERF_SAMPLE_IDENTIFIER | \
|
||||
PERF_SAMPLE_TRANSACTION)
|
||||
PERF_SAMPLE_TRANSACTION | PERF_SAMPLE_PHYS_ADDR)
|
||||
|
||||
/*
|
||||
* A debug store configuration.
|
||||
|
@ -558,6 +558,7 @@ struct x86_pmu {
|
|||
int attr_rdpmc;
|
||||
struct attribute **format_attrs;
|
||||
struct attribute **event_attrs;
|
||||
struct attribute **caps_attrs;
|
||||
|
||||
ssize_t (*events_sysfs_show)(char *page, u64 config);
|
||||
struct attribute **cpu_events;
|
||||
|
@ -591,7 +592,8 @@ struct x86_pmu {
|
|||
pebs :1,
|
||||
pebs_active :1,
|
||||
pebs_broken :1,
|
||||
pebs_prec_dist :1;
|
||||
pebs_prec_dist :1,
|
||||
pebs_no_tlb :1;
|
||||
int pebs_record_size;
|
||||
int pebs_buffer_size;
|
||||
void (*drain_pebs)(struct pt_regs *regs);
|
||||
|
@ -741,6 +743,8 @@ int x86_reserve_hardware(void);
|
|||
|
||||
void x86_release_hardware(void);
|
||||
|
||||
int x86_pmu_max_precise(void);
|
||||
|
||||
void hw_perf_lbr_event_destroy(struct perf_event *event);
|
||||
|
||||
int x86_setup_perfctr(struct perf_event *event);
|
||||
|
@ -947,6 +951,8 @@ void intel_pmu_lbr_init_knl(void);
|
|||
|
||||
void intel_pmu_pebs_data_source_nhm(void);
|
||||
|
||||
void intel_pmu_pebs_data_source_skl(bool pmem);
|
||||
|
||||
int intel_pmu_setup_lbr_filter(struct perf_event *event);
|
||||
|
||||
void intel_pt_interrupt(void);
|
||||
|
|
|
@ -177,7 +177,7 @@
|
|||
#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */
|
||||
#define X86_FEATURE_BPEXT (6*32+26) /* data breakpoint extension */
|
||||
#define X86_FEATURE_PTSC ( 6*32+27) /* performance time-stamp counter */
|
||||
#define X86_FEATURE_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */
|
||||
#define X86_FEATURE_PERFCTR_LLC ( 6*32+28) /* Last Level Cache performance counter extensions */
|
||||
#define X86_FEATURE_MWAITX ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */
|
||||
|
||||
/*
|
||||
|
|
|
@ -39,6 +39,7 @@
|
|||
#include <asm/insn.h>
|
||||
#include <asm/debugreg.h>
|
||||
#include <asm/set_memory.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
@ -251,10 +252,12 @@ static int can_optimize(unsigned long paddr)
|
|||
|
||||
/*
|
||||
* Do not optimize in the entry code due to the unstable
|
||||
* stack handling.
|
||||
* stack handling and registers setup.
|
||||
*/
|
||||
if ((paddr >= (unsigned long)__entry_text_start) &&
|
||||
(paddr < (unsigned long)__entry_text_end))
|
||||
if (((paddr >= (unsigned long)__entry_text_start) &&
|
||||
(paddr < (unsigned long)__entry_text_end)) ||
|
||||
((paddr >= (unsigned long)__irqentry_text_start) &&
|
||||
(paddr < (unsigned long)__irqentry_text_end)))
|
||||
return 0;
|
||||
|
||||
/* Check there is enough space for a relative jump. */
|
||||
|
|
|
@ -91,10 +91,8 @@ static bool in_entry_code(unsigned long ip)
|
|||
if (addr >= __entry_text_start && addr < __entry_text_end)
|
||||
return true;
|
||||
|
||||
#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN)
|
||||
if (addr >= __irqentry_text_start && addr < __irqentry_text_end)
|
||||
return true;
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -273,8 +273,8 @@ void __init init_arch(bp_tag_t *bp_start)
|
|||
* Initialize system. Setup memory and reserve regions.
|
||||
*/
|
||||
|
||||
extern char _end;
|
||||
extern char _stext;
|
||||
extern char _end[];
|
||||
extern char _stext[];
|
||||
extern char _WindowVectors_text_start;
|
||||
extern char _WindowVectors_text_end;
|
||||
extern char _DebugInterruptVector_literal_start;
|
||||
|
@ -333,7 +333,7 @@ void __init setup_arch(char **cmdline_p)
|
|||
}
|
||||
#endif
|
||||
|
||||
mem_reserve(__pa(&_stext), __pa(&_end));
|
||||
mem_reserve(__pa(_stext), __pa(_end));
|
||||
|
||||
#ifdef CONFIG_VECTORS_OFFSET
|
||||
mem_reserve(__pa(&_WindowVectors_text_start),
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
* __kprobes_text_start, __kprobes_text_end
|
||||
* __entry_text_start, __entry_text_end
|
||||
* __ctors_start, __ctors_end
|
||||
* __irqentry_text_start, __irqentry_text_end
|
||||
* __softirqentry_text_start, __softirqentry_text_end
|
||||
*/
|
||||
extern char _text[], _stext[], _etext[];
|
||||
extern char _data[], _sdata[], _edata[];
|
||||
|
@ -39,6 +41,8 @@ extern char __per_cpu_load[], __per_cpu_start[], __per_cpu_end[];
|
|||
extern char __kprobes_text_start[], __kprobes_text_end[];
|
||||
extern char __entry_text_start[], __entry_text_end[];
|
||||
extern char __start_rodata[], __end_rodata[];
|
||||
extern char __irqentry_text_start[], __irqentry_text_end[];
|
||||
extern char __softirqentry_text_start[], __softirqentry_text_end[];
|
||||
|
||||
/* Start and end of .ctors section - used for constructor calls. */
|
||||
extern char __ctors_start[], __ctors_end[];
|
||||
|
|
|
@ -497,25 +497,17 @@
|
|||
*(.entry.text) \
|
||||
VMLINUX_SYMBOL(__entry_text_end) = .;
|
||||
|
||||
#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN)
|
||||
#define IRQENTRY_TEXT \
|
||||
ALIGN_FUNCTION(); \
|
||||
VMLINUX_SYMBOL(__irqentry_text_start) = .; \
|
||||
*(.irqentry.text) \
|
||||
VMLINUX_SYMBOL(__irqentry_text_end) = .;
|
||||
#else
|
||||
#define IRQENTRY_TEXT
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN)
|
||||
#define SOFTIRQENTRY_TEXT \
|
||||
ALIGN_FUNCTION(); \
|
||||
VMLINUX_SYMBOL(__softirqentry_text_start) = .; \
|
||||
*(.softirqentry.text) \
|
||||
VMLINUX_SYMBOL(__softirqentry_text_end) = .;
|
||||
#else
|
||||
#define SOFTIRQENTRY_TEXT
|
||||
#endif
|
||||
|
||||
/* Section used for early init (in .S files) */
|
||||
#define HEAD_TEXT *(.head.text)
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <linux/atomic.h>
|
||||
#include <asm/ptrace.h>
|
||||
#include <asm/irq.h>
|
||||
#include <asm/sections.h>
|
||||
|
||||
/*
|
||||
* These correspond to the IORESOURCE_IRQ_* defines in
|
||||
|
@ -726,7 +727,6 @@ extern int early_irq_init(void);
|
|||
extern int arch_probe_nr_irqs(void);
|
||||
extern int arch_early_irq_init(void);
|
||||
|
||||
#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN)
|
||||
/*
|
||||
* We want to know which function is an entrypoint of a hardirq or a softirq.
|
||||
*/
|
||||
|
@ -734,16 +734,4 @@ extern int arch_early_irq_init(void);
|
|||
#define __softirq_entry \
|
||||
__attribute__((__section__(".softirqentry.text")))
|
||||
|
||||
/* Limits of hardirq entrypoints */
|
||||
extern char __irqentry_text_start[];
|
||||
extern char __irqentry_text_end[];
|
||||
/* Limits of softirq entrypoints */
|
||||
extern char __softirqentry_text_start[];
|
||||
extern char __softirqentry_text_end[];
|
||||
|
||||
#else
|
||||
#define __irq_entry
|
||||
#define __softirq_entry
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -147,9 +147,6 @@ struct hw_perf_event {
|
|||
struct list_head cqm_groups_entry;
|
||||
struct list_head cqm_group_entry;
|
||||
};
|
||||
struct { /* itrace */
|
||||
int itrace_started;
|
||||
};
|
||||
struct { /* amd_power */
|
||||
u64 pwr_acc;
|
||||
u64 ptsc;
|
||||
|
@ -541,6 +538,7 @@ struct swevent_hlist {
|
|||
#define PERF_ATTACH_GROUP 0x02
|
||||
#define PERF_ATTACH_TASK 0x04
|
||||
#define PERF_ATTACH_TASK_DATA 0x08
|
||||
#define PERF_ATTACH_ITRACE 0x10
|
||||
|
||||
struct perf_cgroup;
|
||||
struct ring_buffer;
|
||||
|
@ -864,6 +862,7 @@ extern int perf_aux_output_skip(struct perf_output_handle *handle,
|
|||
unsigned long size);
|
||||
extern void *perf_get_aux(struct perf_output_handle *handle);
|
||||
extern void perf_aux_output_flag(struct perf_output_handle *handle, u64 flags);
|
||||
extern void perf_event_itrace_started(struct perf_event *event);
|
||||
|
||||
extern int perf_pmu_register(struct pmu *pmu, const char *name, int type);
|
||||
extern void perf_pmu_unregister(struct pmu *pmu);
|
||||
|
@ -944,6 +943,8 @@ struct perf_sample_data {
|
|||
|
||||
struct perf_regs regs_intr;
|
||||
u64 stack_user_size;
|
||||
|
||||
u64 phys_addr;
|
||||
} ____cacheline_aligned;
|
||||
|
||||
/* default value for data source */
|
||||
|
|
|
@ -139,8 +139,9 @@ enum perf_event_sample_format {
|
|||
PERF_SAMPLE_IDENTIFIER = 1U << 16,
|
||||
PERF_SAMPLE_TRANSACTION = 1U << 17,
|
||||
PERF_SAMPLE_REGS_INTR = 1U << 18,
|
||||
PERF_SAMPLE_PHYS_ADDR = 1U << 19,
|
||||
|
||||
PERF_SAMPLE_MAX = 1U << 19, /* non-ABI */
|
||||
PERF_SAMPLE_MAX = 1U << 20, /* non-ABI */
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -174,6 +175,8 @@ enum perf_branch_sample_type_shift {
|
|||
PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 14, /* no flags */
|
||||
PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 15, /* no cycles */
|
||||
|
||||
PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 16, /* save branch type */
|
||||
|
||||
PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */
|
||||
};
|
||||
|
||||
|
@ -198,9 +201,30 @@ enum perf_branch_sample_type {
|
|||
PERF_SAMPLE_BRANCH_NO_FLAGS = 1U << PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT,
|
||||
PERF_SAMPLE_BRANCH_NO_CYCLES = 1U << PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT,
|
||||
|
||||
PERF_SAMPLE_BRANCH_TYPE_SAVE =
|
||||
1U << PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT,
|
||||
|
||||
PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT,
|
||||
};
|
||||
|
||||
/*
|
||||
* Common flow change classification
|
||||
*/
|
||||
enum {
|
||||
PERF_BR_UNKNOWN = 0, /* unknown */
|
||||
PERF_BR_COND = 1, /* conditional */
|
||||
PERF_BR_UNCOND = 2, /* unconditional */
|
||||
PERF_BR_IND = 3, /* indirect */
|
||||
PERF_BR_CALL = 4, /* function call */
|
||||
PERF_BR_IND_CALL = 5, /* indirect function call */
|
||||
PERF_BR_RET = 6, /* function return */
|
||||
PERF_BR_SYSCALL = 7, /* syscall */
|
||||
PERF_BR_SYSRET = 8, /* syscall return */
|
||||
PERF_BR_COND_CALL = 9, /* conditional function call */
|
||||
PERF_BR_COND_RET = 10, /* conditional function return */
|
||||
PERF_BR_MAX,
|
||||
};
|
||||
|
||||
#define PERF_SAMPLE_BRANCH_PLM_ALL \
|
||||
(PERF_SAMPLE_BRANCH_USER|\
|
||||
PERF_SAMPLE_BRANCH_KERNEL|\
|
||||
|
@ -791,6 +815,7 @@ enum perf_event_type {
|
|||
* { u64 transaction; } && PERF_SAMPLE_TRANSACTION
|
||||
* { u64 abi; # enum perf_sample_regs_abi
|
||||
* u64 regs[weight(mask)]; } && PERF_SAMPLE_REGS_INTR
|
||||
* { u64 phys_addr;} && PERF_SAMPLE_PHYS_ADDR
|
||||
* };
|
||||
*/
|
||||
PERF_RECORD_SAMPLE = 9,
|
||||
|
@ -931,14 +956,20 @@ union perf_mem_data_src {
|
|||
mem_snoop:5, /* snoop mode */
|
||||
mem_lock:2, /* lock instr */
|
||||
mem_dtlb:7, /* tlb access */
|
||||
mem_rsvd:31;
|
||||
mem_lvl_num:4, /* memory hierarchy level number */
|
||||
mem_remote:1, /* remote */
|
||||
mem_snoopx:2, /* snoop mode, ext */
|
||||
mem_rsvd:24;
|
||||
};
|
||||
};
|
||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
union perf_mem_data_src {
|
||||
__u64 val;
|
||||
struct {
|
||||
__u64 mem_rsvd:31,
|
||||
__u64 mem_rsvd:24,
|
||||
mem_snoopx:2, /* snoop mode, ext */
|
||||
mem_remote:1, /* remote */
|
||||
mem_lvl_num:4, /* memory hierarchy level number */
|
||||
mem_dtlb:7, /* tlb access */
|
||||
mem_lock:2, /* lock instr */
|
||||
mem_snoop:5, /* snoop mode */
|
||||
|
@ -975,6 +1006,22 @@ union perf_mem_data_src {
|
|||
#define PERF_MEM_LVL_UNC 0x2000 /* Uncached memory */
|
||||
#define PERF_MEM_LVL_SHIFT 5
|
||||
|
||||
#define PERF_MEM_REMOTE_REMOTE 0x01 /* Remote */
|
||||
#define PERF_MEM_REMOTE_SHIFT 37
|
||||
|
||||
#define PERF_MEM_LVLNUM_L1 0x01 /* L1 */
|
||||
#define PERF_MEM_LVLNUM_L2 0x02 /* L2 */
|
||||
#define PERF_MEM_LVLNUM_L3 0x03 /* L3 */
|
||||
#define PERF_MEM_LVLNUM_L4 0x04 /* L4 */
|
||||
/* 5-0xa available */
|
||||
#define PERF_MEM_LVLNUM_ANY_CACHE 0x0b /* Any cache */
|
||||
#define PERF_MEM_LVLNUM_LFB 0x0c /* LFB */
|
||||
#define PERF_MEM_LVLNUM_RAM 0x0d /* RAM */
|
||||
#define PERF_MEM_LVLNUM_PMEM 0x0e /* PMEM */
|
||||
#define PERF_MEM_LVLNUM_NA 0x0f /* N/A */
|
||||
|
||||
#define PERF_MEM_LVLNUM_SHIFT 33
|
||||
|
||||
/* snoop mode */
|
||||
#define PERF_MEM_SNOOP_NA 0x01 /* not available */
|
||||
#define PERF_MEM_SNOOP_NONE 0x02 /* no snoop */
|
||||
|
@ -983,6 +1030,10 @@ union perf_mem_data_src {
|
|||
#define PERF_MEM_SNOOP_HITM 0x10 /* snoop hit modified */
|
||||
#define PERF_MEM_SNOOP_SHIFT 19
|
||||
|
||||
#define PERF_MEM_SNOOPX_FWD 0x01 /* forward */
|
||||
/* 1 free */
|
||||
#define PERF_MEM_SNOOPX_SHIFT 37
|
||||
|
||||
/* locked instruction */
|
||||
#define PERF_MEM_LOCK_NA 0x01 /* not available */
|
||||
#define PERF_MEM_LOCK_LOCKED 0x02 /* locked transaction */
|
||||
|
@ -1015,6 +1066,7 @@ union perf_mem_data_src {
|
|||
* in_tx: running in a hardware transaction
|
||||
* abort: aborting a hardware transaction
|
||||
* cycles: cycles from last branch (or 0 if not supported)
|
||||
* type: branch type
|
||||
*/
|
||||
struct perf_branch_entry {
|
||||
__u64 from;
|
||||
|
@ -1024,7 +1076,8 @@ struct perf_branch_entry {
|
|||
in_tx:1, /* in transaction */
|
||||
abort:1, /* transaction abort */
|
||||
cycles:16, /* cycle count to last branch */
|
||||
reserved:44;
|
||||
type:4, /* branch type */
|
||||
reserved:40;
|
||||
};
|
||||
|
||||
#endif /* _UAPI_LINUX_PERF_EVENT_H */
|
||||
|
|
|
@ -1249,26 +1249,31 @@ unclone_ctx(struct perf_event_context *ctx)
|
|||
return parent_ctx;
|
||||
}
|
||||
|
||||
static u32 perf_event_pid(struct perf_event *event, struct task_struct *p)
|
||||
static u32 perf_event_pid_type(struct perf_event *event, struct task_struct *p,
|
||||
enum pid_type type)
|
||||
{
|
||||
u32 nr;
|
||||
/*
|
||||
* only top level events have the pid namespace they were created in
|
||||
*/
|
||||
if (event->parent)
|
||||
event = event->parent;
|
||||
|
||||
return task_tgid_nr_ns(p, event->ns);
|
||||
nr = __task_pid_nr_ns(p, type, event->ns);
|
||||
/* avoid -1 if it is idle thread or runs in another ns */
|
||||
if (!nr && !pid_alive(p))
|
||||
nr = -1;
|
||||
return nr;
|
||||
}
|
||||
|
||||
static u32 perf_event_pid(struct perf_event *event, struct task_struct *p)
|
||||
{
|
||||
return perf_event_pid_type(event, p, __PIDTYPE_TGID);
|
||||
}
|
||||
|
||||
static u32 perf_event_tid(struct perf_event *event, struct task_struct *p)
|
||||
{
|
||||
/*
|
||||
* only top level events have the pid namespace they were created in
|
||||
*/
|
||||
if (event->parent)
|
||||
event = event->parent;
|
||||
|
||||
return task_pid_nr_ns(p, event->ns);
|
||||
return perf_event_pid_type(event, p, PIDTYPE_PID);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1570,6 +1575,9 @@ static void __perf_event_header_size(struct perf_event *event, u64 sample_type)
|
|||
if (sample_type & PERF_SAMPLE_TRANSACTION)
|
||||
size += sizeof(data->txn);
|
||||
|
||||
if (sample_type & PERF_SAMPLE_PHYS_ADDR)
|
||||
size += sizeof(data->phys_addr);
|
||||
|
||||
event->header_size = size;
|
||||
}
|
||||
|
||||
|
@ -3211,6 +3219,13 @@ static void perf_event_context_sched_in(struct perf_event_context *ctx,
|
|||
return;
|
||||
|
||||
perf_ctx_lock(cpuctx, ctx);
|
||||
/*
|
||||
* We must check ctx->nr_events while holding ctx->lock, such
|
||||
* that we serialize against perf_install_in_context().
|
||||
*/
|
||||
if (!ctx->nr_events)
|
||||
goto unlock;
|
||||
|
||||
perf_pmu_disable(ctx->pmu);
|
||||
/*
|
||||
* We want to keep the following priority order:
|
||||
|
@ -3224,6 +3239,8 @@ static void perf_event_context_sched_in(struct perf_event_context *ctx,
|
|||
cpu_ctx_sched_out(cpuctx, EVENT_FLEXIBLE);
|
||||
perf_event_sched_in(cpuctx, ctx, task);
|
||||
perf_pmu_enable(ctx->pmu);
|
||||
|
||||
unlock:
|
||||
perf_ctx_unlock(cpuctx, ctx);
|
||||
}
|
||||
|
||||
|
@ -6003,6 +6020,9 @@ void perf_output_sample(struct perf_output_handle *handle,
|
|||
}
|
||||
}
|
||||
|
||||
if (sample_type & PERF_SAMPLE_PHYS_ADDR)
|
||||
perf_output_put(handle, data->phys_addr);
|
||||
|
||||
if (!event->attr.watermark) {
|
||||
int wakeup_events = event->attr.wakeup_events;
|
||||
|
||||
|
@ -6018,6 +6038,38 @@ void perf_output_sample(struct perf_output_handle *handle,
|
|||
}
|
||||
}
|
||||
|
||||
static u64 perf_virt_to_phys(u64 virt)
|
||||
{
|
||||
u64 phys_addr = 0;
|
||||
struct page *p = NULL;
|
||||
|
||||
if (!virt)
|
||||
return 0;
|
||||
|
||||
if (virt >= TASK_SIZE) {
|
||||
/* If it's vmalloc()d memory, leave phys_addr as 0 */
|
||||
if (virt_addr_valid((void *)(uintptr_t)virt) &&
|
||||
!(virt >= VMALLOC_START && virt < VMALLOC_END))
|
||||
phys_addr = (u64)virt_to_phys((void *)(uintptr_t)virt);
|
||||
} else {
|
||||
/*
|
||||
* Walking the pages tables for user address.
|
||||
* Interrupts are disabled, so it prevents any tear down
|
||||
* of the page tables.
|
||||
* Try IRQ-safe __get_user_pages_fast first.
|
||||
* If failed, leave phys_addr as 0.
|
||||
*/
|
||||
if ((current->mm != NULL) &&
|
||||
(__get_user_pages_fast(virt, 1, 0, &p) == 1))
|
||||
phys_addr = page_to_phys(p) + virt % PAGE_SIZE;
|
||||
|
||||
if (p)
|
||||
put_page(p);
|
||||
}
|
||||
|
||||
return phys_addr;
|
||||
}
|
||||
|
||||
void perf_prepare_sample(struct perf_event_header *header,
|
||||
struct perf_sample_data *data,
|
||||
struct perf_event *event,
|
||||
|
@ -6136,6 +6188,9 @@ void perf_prepare_sample(struct perf_event_header *header,
|
|||
|
||||
header->size += size;
|
||||
}
|
||||
|
||||
if (sample_type & PERF_SAMPLE_PHYS_ADDR)
|
||||
data->phys_addr = perf_virt_to_phys(data->addr);
|
||||
}
|
||||
|
||||
static void __always_inline
|
||||
|
@ -7287,6 +7342,11 @@ static void perf_log_throttle(struct perf_event *event, int enable)
|
|||
perf_output_end(&handle);
|
||||
}
|
||||
|
||||
void perf_event_itrace_started(struct perf_event *event)
|
||||
{
|
||||
event->attach_state |= PERF_ATTACH_ITRACE;
|
||||
}
|
||||
|
||||
static void perf_log_itrace_start(struct perf_event *event)
|
||||
{
|
||||
struct perf_output_handle handle;
|
||||
|
@ -7302,7 +7362,7 @@ static void perf_log_itrace_start(struct perf_event *event)
|
|||
event = event->parent;
|
||||
|
||||
if (!(event->pmu->capabilities & PERF_PMU_CAP_ITRACE) ||
|
||||
event->hw.itrace_started)
|
||||
event->attach_state & PERF_ATTACH_ITRACE)
|
||||
return;
|
||||
|
||||
rec.header.type = PERF_RECORD_ITRACE_START;
|
||||
|
@ -9890,6 +9950,11 @@ SYSCALL_DEFINE5(perf_event_open,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Only privileged users can get physical addresses */
|
||||
if ((attr.sample_type & PERF_SAMPLE_PHYS_ADDR) &&
|
||||
perf_paranoid_kernel() && !capable(CAP_SYS_ADMIN))
|
||||
return -EACCES;
|
||||
|
||||
if (!attr.sample_max_stack)
|
||||
attr.sample_max_stack = sysctl_perf_event_max_stack;
|
||||
|
||||
|
|
|
@ -38,9 +38,9 @@ struct ring_buffer {
|
|||
struct user_struct *mmap_user;
|
||||
|
||||
/* AUX area */
|
||||
local_t aux_head;
|
||||
long aux_head;
|
||||
local_t aux_nest;
|
||||
local_t aux_wakeup;
|
||||
long aux_wakeup; /* last aux_watermark boundary crossed by aux_head */
|
||||
unsigned long aux_pgoff;
|
||||
int aux_nr_pages;
|
||||
int aux_overwrite;
|
||||
|
@ -208,7 +208,7 @@ static inline int get_recursion_context(int *recursion)
|
|||
{
|
||||
int rctx;
|
||||
|
||||
if (in_nmi())
|
||||
if (unlikely(in_nmi()))
|
||||
rctx = 3;
|
||||
else if (in_irq())
|
||||
rctx = 2;
|
||||
|
|
|
@ -367,7 +367,7 @@ void *perf_aux_output_begin(struct perf_output_handle *handle,
|
|||
if (WARN_ON_ONCE(local_xchg(&rb->aux_nest, 1)))
|
||||
goto err_put;
|
||||
|
||||
aux_head = local_read(&rb->aux_head);
|
||||
aux_head = rb->aux_head;
|
||||
|
||||
handle->rb = rb;
|
||||
handle->event = event;
|
||||
|
@ -382,7 +382,7 @@ void *perf_aux_output_begin(struct perf_output_handle *handle,
|
|||
*/
|
||||
if (!rb->aux_overwrite) {
|
||||
aux_tail = ACCESS_ONCE(rb->user_page->aux_tail);
|
||||
handle->wakeup = local_read(&rb->aux_wakeup) + rb->aux_watermark;
|
||||
handle->wakeup = rb->aux_wakeup + rb->aux_watermark;
|
||||
if (aux_head - aux_tail < perf_aux_size(rb))
|
||||
handle->size = CIRC_SPACE(aux_head, aux_tail, perf_aux_size(rb));
|
||||
|
||||
|
@ -433,12 +433,12 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size)
|
|||
handle->aux_flags |= PERF_AUX_FLAG_OVERWRITE;
|
||||
|
||||
aux_head = handle->head;
|
||||
local_set(&rb->aux_head, aux_head);
|
||||
rb->aux_head = aux_head;
|
||||
} else {
|
||||
handle->aux_flags &= ~PERF_AUX_FLAG_OVERWRITE;
|
||||
|
||||
aux_head = local_read(&rb->aux_head);
|
||||
local_add(size, &rb->aux_head);
|
||||
aux_head = rb->aux_head;
|
||||
rb->aux_head += size;
|
||||
}
|
||||
|
||||
if (size || handle->aux_flags) {
|
||||
|
@ -450,11 +450,10 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size)
|
|||
handle->aux_flags);
|
||||
}
|
||||
|
||||
aux_head = rb->user_page->aux_head = local_read(&rb->aux_head);
|
||||
|
||||
if (aux_head - local_read(&rb->aux_wakeup) >= rb->aux_watermark) {
|
||||
rb->user_page->aux_head = rb->aux_head;
|
||||
if (rb->aux_head - rb->aux_wakeup >= rb->aux_watermark) {
|
||||
wakeup = true;
|
||||
local_add(rb->aux_watermark, &rb->aux_wakeup);
|
||||
rb->aux_wakeup = rounddown(rb->aux_head, rb->aux_watermark);
|
||||
}
|
||||
|
||||
if (wakeup) {
|
||||
|
@ -478,22 +477,20 @@ void perf_aux_output_end(struct perf_output_handle *handle, unsigned long size)
|
|||
int perf_aux_output_skip(struct perf_output_handle *handle, unsigned long size)
|
||||
{
|
||||
struct ring_buffer *rb = handle->rb;
|
||||
unsigned long aux_head;
|
||||
|
||||
if (size > handle->size)
|
||||
return -ENOSPC;
|
||||
|
||||
local_add(size, &rb->aux_head);
|
||||
rb->aux_head += size;
|
||||
|
||||
aux_head = rb->user_page->aux_head = local_read(&rb->aux_head);
|
||||
if (aux_head - local_read(&rb->aux_wakeup) >= rb->aux_watermark) {
|
||||
rb->user_page->aux_head = rb->aux_head;
|
||||
if (rb->aux_head - rb->aux_wakeup >= rb->aux_watermark) {
|
||||
perf_output_wakeup(handle);
|
||||
local_add(rb->aux_watermark, &rb->aux_wakeup);
|
||||
handle->wakeup = local_read(&rb->aux_wakeup) +
|
||||
rb->aux_watermark;
|
||||
rb->aux_wakeup = rounddown(rb->aux_head, rb->aux_watermark);
|
||||
handle->wakeup = rb->aux_wakeup + rb->aux_watermark;
|
||||
}
|
||||
|
||||
handle->head = aux_head;
|
||||
handle->head = rb->aux_head;
|
||||
handle->size -= size;
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -203,6 +203,14 @@ struct kvm_arch_memory_slot {
|
|||
#define KVM_DEV_ARM_VGIC_LINE_LEVEL_INTID_MASK 0x3ff
|
||||
#define VGIC_LEVEL_INFO_LINE_LEVEL 0
|
||||
|
||||
/* Device Control API on vcpu fd */
|
||||
#define KVM_ARM_VCPU_PMU_V3_CTRL 0
|
||||
#define KVM_ARM_VCPU_PMU_V3_IRQ 0
|
||||
#define KVM_ARM_VCPU_PMU_V3_INIT 1
|
||||
#define KVM_ARM_VCPU_TIMER_CTRL 1
|
||||
#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
|
||||
#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
|
||||
|
||||
#define KVM_DEV_ARM_VGIC_CTRL_INIT 0
|
||||
#define KVM_DEV_ARM_ITS_SAVE_TABLES 1
|
||||
#define KVM_DEV_ARM_ITS_RESTORE_TABLES 2
|
||||
|
|
|
@ -232,6 +232,9 @@ struct kvm_arch_memory_slot {
|
|||
#define KVM_ARM_VCPU_PMU_V3_CTRL 0
|
||||
#define KVM_ARM_VCPU_PMU_V3_IRQ 0
|
||||
#define KVM_ARM_VCPU_PMU_V3_INIT 1
|
||||
#define KVM_ARM_VCPU_TIMER_CTRL 1
|
||||
#define KVM_ARM_VCPU_TIMER_IRQ_VTIMER 0
|
||||
#define KVM_ARM_VCPU_TIMER_IRQ_PTIMER 1
|
||||
|
||||
/* KVM_IRQ_LINE irq field index values */
|
||||
#define KVM_ARM_IRQ_TYPE_SHIFT 24
|
||||
|
|
|
@ -60,6 +60,12 @@ struct kvm_regs {
|
|||
|
||||
#define KVM_SREGS_E_FSL_PIDn (1 << 0) /* PID1/PID2 */
|
||||
|
||||
/* flags for kvm_run.flags */
|
||||
#define KVM_RUN_PPC_NMI_DISP_MASK (3 << 0)
|
||||
#define KVM_RUN_PPC_NMI_DISP_FULLY_RECOV (1 << 0)
|
||||
#define KVM_RUN_PPC_NMI_DISP_LIMITED_RECOV (2 << 0)
|
||||
#define KVM_RUN_PPC_NMI_DISP_NOT_RECOV (3 << 0)
|
||||
|
||||
/*
|
||||
* Feature bits indicate which sections of the sregs struct are valid,
|
||||
* both in KVM_GET_SREGS and KVM_SET_SREGS. On KVM_SET_SREGS, registers
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
#define KVM_DEV_FLIC_CLEAR_IO_IRQ 8
|
||||
#define KVM_DEV_FLIC_AISM 9
|
||||
#define KVM_DEV_FLIC_AIRQ_INJECT 10
|
||||
#define KVM_DEV_FLIC_AISM_ALL 11
|
||||
/*
|
||||
* We can have up to 4*64k pending subchannels + 8 adapter interrupts,
|
||||
* as well as up to ASYNC_PF_PER_VCPU*KVM_MAX_VCPUS pfault done interrupts.
|
||||
|
@ -53,6 +54,11 @@ struct kvm_s390_ais_req {
|
|||
__u16 mode;
|
||||
};
|
||||
|
||||
struct kvm_s390_ais_all {
|
||||
__u8 simm;
|
||||
__u8 nimm;
|
||||
};
|
||||
|
||||
#define KVM_S390_IO_ADAPTER_MASK 1
|
||||
#define KVM_S390_IO_ADAPTER_MAP 2
|
||||
#define KVM_S390_IO_ADAPTER_UNMAP 3
|
||||
|
@ -70,6 +76,7 @@ struct kvm_s390_io_adapter_req {
|
|||
#define KVM_S390_VM_TOD 1
|
||||
#define KVM_S390_VM_CRYPTO 2
|
||||
#define KVM_S390_VM_CPU_MODEL 3
|
||||
#define KVM_S390_VM_MIGRATION 4
|
||||
|
||||
/* kvm attributes for mem_ctrl */
|
||||
#define KVM_S390_VM_MEM_ENABLE_CMMA 0
|
||||
|
@ -151,6 +158,11 @@ struct kvm_s390_vm_cpu_subfunc {
|
|||
#define KVM_S390_VM_CRYPTO_DISABLE_AES_KW 2
|
||||
#define KVM_S390_VM_CRYPTO_DISABLE_DEA_KW 3
|
||||
|
||||
/* kvm attributes for migration mode */
|
||||
#define KVM_S390_VM_MIGRATION_STOP 0
|
||||
#define KVM_S390_VM_MIGRATION_START 1
|
||||
#define KVM_S390_VM_MIGRATION_STATUS 2
|
||||
|
||||
/* for KVM_GET_REGS and KVM_SET_REGS */
|
||||
struct kvm_regs {
|
||||
/* general purpose regs for s390 */
|
||||
|
|
|
@ -177,7 +177,7 @@
|
|||
#define X86_FEATURE_PERFCTR_NB ( 6*32+24) /* NB performance counter extensions */
|
||||
#define X86_FEATURE_BPEXT (6*32+26) /* data breakpoint extension */
|
||||
#define X86_FEATURE_PTSC ( 6*32+27) /* performance time-stamp counter */
|
||||
#define X86_FEATURE_PERFCTR_L2 ( 6*32+28) /* L2 performance counter extensions */
|
||||
#define X86_FEATURE_PERFCTR_LLC ( 6*32+28) /* Last Level Cache performance counter extensions */
|
||||
#define X86_FEATURE_MWAITX ( 6*32+29) /* MWAIT extension (MONITORX/MWAITX) */
|
||||
|
||||
/*
|
||||
|
@ -286,6 +286,7 @@
|
|||
#define X86_FEATURE_PAUSEFILTER (15*32+10) /* filtered pause intercept */
|
||||
#define X86_FEATURE_PFTHRESHOLD (15*32+12) /* pause filter threshold */
|
||||
#define X86_FEATURE_AVIC (15*32+13) /* Virtual Interrupt Controller */
|
||||
#define X86_FEATURE_V_VMSAVE_VMLOAD (15*32+15) /* Virtual VMSAVE VMLOAD */
|
||||
|
||||
/* Intel-defined CPU features, CPUID level 0x00000007:0 (ecx), word 16 */
|
||||
#define X86_FEATURE_AVX512VBMI (16*32+ 1) /* AVX512 Vector Bit Manipulation instructions*/
|
||||
|
|
|
@ -10,3 +10,6 @@
|
|||
#ifndef __NR_getcpu
|
||||
# define __NR_getcpu 318
|
||||
#endif
|
||||
#ifndef __NR_setns
|
||||
# define __NR_setns 346
|
||||
#endif
|
||||
|
|
|
@ -10,3 +10,6 @@
|
|||
#ifndef __NR_getcpu
|
||||
# define __NR_getcpu 309
|
||||
#endif
|
||||
#ifndef __NR_setns
|
||||
#define __NR_setns 308
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef _UAPI_ASM_X86_UNISTD_H
|
||||
#define _UAPI_ASM_X86_UNISTD_H
|
||||
|
||||
/* x32 syscall flag bit */
|
||||
#define __X32_SYSCALL_BIT 0x40000000
|
||||
|
||||
#ifndef __KERNEL__
|
||||
# ifdef __i386__
|
||||
# include <asm/unistd_32.h>
|
||||
# elif defined(__ILP32__)
|
||||
# include <asm/unistd_x32.h>
|
||||
# else
|
||||
# include <asm/unistd_64.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* _UAPI_ASM_X86_UNISTD_H */
|
|
@ -64,7 +64,8 @@ FEATURE_TESTS_BASIC := \
|
|||
get_cpuid \
|
||||
bpf \
|
||||
sched_getcpu \
|
||||
sdt
|
||||
sdt \
|
||||
setns
|
||||
|
||||
# FEATURE_TESTS_BASIC + FEATURE_TESTS_EXTRA is the complete list
|
||||
# of all feature tests
|
||||
|
|
|
@ -49,7 +49,8 @@ FILES= \
|
|||
test-sdt.bin \
|
||||
test-cxx.bin \
|
||||
test-jvmti.bin \
|
||||
test-sched_getcpu.bin
|
||||
test-sched_getcpu.bin \
|
||||
test-setns.bin
|
||||
|
||||
FILES := $(addprefix $(OUTPUT),$(FILES))
|
||||
|
||||
|
@ -95,6 +96,9 @@ $(OUTPUT)test-glibc.bin:
|
|||
$(OUTPUT)test-sched_getcpu.bin:
|
||||
$(BUILD)
|
||||
|
||||
$(OUTPUT)test-setns.bin:
|
||||
$(BUILD)
|
||||
|
||||
DWARFLIBS := -ldw
|
||||
ifeq ($(findstring -static,${LDFLAGS}),-static)
|
||||
DWARFLIBS += -lelf -lebl -lz -llzma -lbz2
|
||||
|
|
|
@ -153,6 +153,10 @@
|
|||
# include "test-sdt.c"
|
||||
#undef main
|
||||
|
||||
#define main main_test_setns
|
||||
# include "test-setns.c"
|
||||
#undef main
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
main_test_libpython();
|
||||
|
@ -188,6 +192,7 @@ int main(int argc, char *argv[])
|
|||
main_test_libcrypto();
|
||||
main_test_sched_getcpu();
|
||||
main_test_sdt();
|
||||
main_test_setns();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <sched.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
return setns(0, 0);
|
||||
}
|
|
@ -8,7 +8,7 @@ ex:
|
|||
include $(srctree)/tools/build/Makefile.include
|
||||
|
||||
ex: ex-in.o libex-in.o
|
||||
gcc -o $@ $^
|
||||
$(CC) -o $@ $^
|
||||
|
||||
ex.%: fixdep FORCE
|
||||
make -f $(srctree)/tools/build/Makefile.build dir=. $@
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef _TOOLS_LINUX_STRING_H_
|
||||
#define _TOOLS_LINUX_STRING_H_
|
||||
|
||||
|
||||
#include <linux/types.h> /* for size_t */
|
||||
#include <string.h>
|
||||
|
||||
void *memdup(const void *src, size_t len);
|
||||
|
||||
|
@ -18,6 +18,14 @@ extern size_t strlcpy(char *dest, const char *src, size_t size);
|
|||
|
||||
char *str_error_r(int errnum, char *buf, size_t buflen);
|
||||
|
||||
int prefixcmp(const char *str, const char *prefix);
|
||||
/**
|
||||
* strstarts - does @str start with @prefix?
|
||||
* @str: string to examine
|
||||
* @prefix: prefix to look for.
|
||||
*/
|
||||
static inline bool strstarts(const char *str, const char *prefix)
|
||||
{
|
||||
return strncmp(str, prefix, strlen(prefix)) == 0;
|
||||
}
|
||||
|
||||
#endif /* _LINUX_STRING_H_ */
|
||||
|
|
|
@ -0,0 +1,220 @@
|
|||
#ifndef _ASM_GENERIC_FCNTL_H
|
||||
#define _ASM_GENERIC_FCNTL_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
/*
|
||||
* FMODE_EXEC is 0x20
|
||||
* FMODE_NONOTIFY is 0x4000000
|
||||
* These cannot be used by userspace O_* until internal and external open
|
||||
* flags are split.
|
||||
* -Eric Paris
|
||||
*/
|
||||
|
||||
/*
|
||||
* When introducing new O_* bits, please check its uniqueness in fcntl_init().
|
||||
*/
|
||||
|
||||
#define O_ACCMODE 00000003
|
||||
#define O_RDONLY 00000000
|
||||
#define O_WRONLY 00000001
|
||||
#define O_RDWR 00000002
|
||||
#ifndef O_CREAT
|
||||
#define O_CREAT 00000100 /* not fcntl */
|
||||
#endif
|
||||
#ifndef O_EXCL
|
||||
#define O_EXCL 00000200 /* not fcntl */
|
||||
#endif
|
||||
#ifndef O_NOCTTY
|
||||
#define O_NOCTTY 00000400 /* not fcntl */
|
||||
#endif
|
||||
#ifndef O_TRUNC
|
||||
#define O_TRUNC 00001000 /* not fcntl */
|
||||
#endif
|
||||
#ifndef O_APPEND
|
||||
#define O_APPEND 00002000
|
||||
#endif
|
||||
#ifndef O_NONBLOCK
|
||||
#define O_NONBLOCK 00004000
|
||||
#endif
|
||||
#ifndef O_DSYNC
|
||||
#define O_DSYNC 00010000 /* used to be O_SYNC, see below */
|
||||
#endif
|
||||
#ifndef FASYNC
|
||||
#define FASYNC 00020000 /* fcntl, for BSD compatibility */
|
||||
#endif
|
||||
#ifndef O_DIRECT
|
||||
#define O_DIRECT 00040000 /* direct disk access hint */
|
||||
#endif
|
||||
#ifndef O_LARGEFILE
|
||||
#define O_LARGEFILE 00100000
|
||||
#endif
|
||||
#ifndef O_DIRECTORY
|
||||
#define O_DIRECTORY 00200000 /* must be a directory */
|
||||
#endif
|
||||
#ifndef O_NOFOLLOW
|
||||
#define O_NOFOLLOW 00400000 /* don't follow links */
|
||||
#endif
|
||||
#ifndef O_NOATIME
|
||||
#define O_NOATIME 01000000
|
||||
#endif
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 02000000 /* set close_on_exec */
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Before Linux 2.6.33 only O_DSYNC semantics were implemented, but using
|
||||
* the O_SYNC flag. We continue to use the existing numerical value
|
||||
* for O_DSYNC semantics now, but using the correct symbolic name for it.
|
||||
* This new value is used to request true Posix O_SYNC semantics. It is
|
||||
* defined in this strange way to make sure applications compiled against
|
||||
* new headers get at least O_DSYNC semantics on older kernels.
|
||||
*
|
||||
* This has the nice side-effect that we can simply test for O_DSYNC
|
||||
* wherever we do not care if O_DSYNC or O_SYNC is used.
|
||||
*
|
||||
* Note: __O_SYNC must never be used directly.
|
||||
*/
|
||||
#ifndef O_SYNC
|
||||
#define __O_SYNC 04000000
|
||||
#define O_SYNC (__O_SYNC|O_DSYNC)
|
||||
#endif
|
||||
|
||||
#ifndef O_PATH
|
||||
#define O_PATH 010000000
|
||||
#endif
|
||||
|
||||
#ifndef __O_TMPFILE
|
||||
#define __O_TMPFILE 020000000
|
||||
#endif
|
||||
|
||||
/* a horrid kludge trying to make sure that this will fail on old kernels */
|
||||
#define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
|
||||
#define O_TMPFILE_MASK (__O_TMPFILE | O_DIRECTORY | O_CREAT)
|
||||
|
||||
#ifndef O_NDELAY
|
||||
#define O_NDELAY O_NONBLOCK
|
||||
#endif
|
||||
|
||||
#define F_DUPFD 0 /* dup */
|
||||
#define F_GETFD 1 /* get close_on_exec */
|
||||
#define F_SETFD 2 /* set/clear close_on_exec */
|
||||
#define F_GETFL 3 /* get file->f_flags */
|
||||
#define F_SETFL 4 /* set file->f_flags */
|
||||
#ifndef F_GETLK
|
||||
#define F_GETLK 5
|
||||
#define F_SETLK 6
|
||||
#define F_SETLKW 7
|
||||
#endif
|
||||
#ifndef F_SETOWN
|
||||
#define F_SETOWN 8 /* for sockets. */
|
||||
#define F_GETOWN 9 /* for sockets. */
|
||||
#endif
|
||||
#ifndef F_SETSIG
|
||||
#define F_SETSIG 10 /* for sockets. */
|
||||
#define F_GETSIG 11 /* for sockets. */
|
||||
#endif
|
||||
|
||||
#ifndef CONFIG_64BIT
|
||||
#ifndef F_GETLK64
|
||||
#define F_GETLK64 12 /* using 'struct flock64' */
|
||||
#define F_SETLK64 13
|
||||
#define F_SETLKW64 14
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef F_SETOWN_EX
|
||||
#define F_SETOWN_EX 15
|
||||
#define F_GETOWN_EX 16
|
||||
#endif
|
||||
|
||||
#ifndef F_GETOWNER_UIDS
|
||||
#define F_GETOWNER_UIDS 17
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Open File Description Locks
|
||||
*
|
||||
* Usually record locks held by a process are released on *any* close and are
|
||||
* not inherited across a fork().
|
||||
*
|
||||
* These cmd values will set locks that conflict with process-associated
|
||||
* record locks, but are "owned" by the open file description, not the
|
||||
* process. This means that they are inherited across fork() like BSD (flock)
|
||||
* locks, and they are only released automatically when the last reference to
|
||||
* the the open file against which they were acquired is put.
|
||||
*/
|
||||
#define F_OFD_GETLK 36
|
||||
#define F_OFD_SETLK 37
|
||||
#define F_OFD_SETLKW 38
|
||||
|
||||
#define F_OWNER_TID 0
|
||||
#define F_OWNER_PID 1
|
||||
#define F_OWNER_PGRP 2
|
||||
|
||||
struct f_owner_ex {
|
||||
int type;
|
||||
__kernel_pid_t pid;
|
||||
};
|
||||
|
||||
/* for F_[GET|SET]FL */
|
||||
#define FD_CLOEXEC 1 /* actually anything with low bit set goes */
|
||||
|
||||
/* for posix fcntl() and lockf() */
|
||||
#ifndef F_RDLCK
|
||||
#define F_RDLCK 0
|
||||
#define F_WRLCK 1
|
||||
#define F_UNLCK 2
|
||||
#endif
|
||||
|
||||
/* for old implementation of bsd flock () */
|
||||
#ifndef F_EXLCK
|
||||
#define F_EXLCK 4 /* or 3 */
|
||||
#define F_SHLCK 8 /* or 4 */
|
||||
#endif
|
||||
|
||||
/* operations for bsd flock(), also used by the kernel implementation */
|
||||
#define LOCK_SH 1 /* shared lock */
|
||||
#define LOCK_EX 2 /* exclusive lock */
|
||||
#define LOCK_NB 4 /* or'd with one of the above to prevent
|
||||
blocking */
|
||||
#define LOCK_UN 8 /* remove lock */
|
||||
|
||||
#define LOCK_MAND 32 /* This is a mandatory flock ... */
|
||||
#define LOCK_READ 64 /* which allows concurrent read operations */
|
||||
#define LOCK_WRITE 128 /* which allows concurrent write operations */
|
||||
#define LOCK_RW 192 /* which allows concurrent read & write ops */
|
||||
|
||||
#define F_LINUX_SPECIFIC_BASE 1024
|
||||
|
||||
#ifndef HAVE_ARCH_STRUCT_FLOCK
|
||||
#ifndef __ARCH_FLOCK_PAD
|
||||
#define __ARCH_FLOCK_PAD
|
||||
#endif
|
||||
|
||||
struct flock {
|
||||
short l_type;
|
||||
short l_whence;
|
||||
__kernel_off_t l_start;
|
||||
__kernel_off_t l_len;
|
||||
__kernel_pid_t l_pid;
|
||||
__ARCH_FLOCK_PAD
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ARCH_STRUCT_FLOCK64
|
||||
#ifndef __ARCH_FLOCK64_PAD
|
||||
#define __ARCH_FLOCK64_PAD
|
||||
#endif
|
||||
|
||||
struct flock64 {
|
||||
short l_type;
|
||||
short l_whence;
|
||||
__kernel_loff_t l_start;
|
||||
__kernel_loff_t l_len;
|
||||
__kernel_pid_t l_pid;
|
||||
__ARCH_FLOCK64_PAD
|
||||
};
|
||||
#endif
|
||||
|
||||
#endif /* _ASM_GENERIC_FCNTL_H */
|
|
@ -0,0 +1,118 @@
|
|||
#ifndef __ASM_GENERIC_IOCTLS_H
|
||||
#define __ASM_GENERIC_IOCTLS_H
|
||||
|
||||
#include <linux/ioctl.h>
|
||||
|
||||
/*
|
||||
* These are the most common definitions for tty ioctl numbers.
|
||||
* Most of them do not use the recommended _IOC(), but there is
|
||||
* probably some source code out there hardcoding the number,
|
||||
* so we might as well use them for all new platforms.
|
||||
*
|
||||
* The architectures that use different values here typically
|
||||
* try to be compatible with some Unix variants for the same
|
||||
* architecture.
|
||||
*/
|
||||
|
||||
/* 0x54 is just a magic number to make these relatively unique ('T') */
|
||||
|
||||
#define TCGETS 0x5401
|
||||
#define TCSETS 0x5402
|
||||
#define TCSETSW 0x5403
|
||||
#define TCSETSF 0x5404
|
||||
#define TCGETA 0x5405
|
||||
#define TCSETA 0x5406
|
||||
#define TCSETAW 0x5407
|
||||
#define TCSETAF 0x5408
|
||||
#define TCSBRK 0x5409
|
||||
#define TCXONC 0x540A
|
||||
#define TCFLSH 0x540B
|
||||
#define TIOCEXCL 0x540C
|
||||
#define TIOCNXCL 0x540D
|
||||
#define TIOCSCTTY 0x540E
|
||||
#define TIOCGPGRP 0x540F
|
||||
#define TIOCSPGRP 0x5410
|
||||
#define TIOCOUTQ 0x5411
|
||||
#define TIOCSTI 0x5412
|
||||
#define TIOCGWINSZ 0x5413
|
||||
#define TIOCSWINSZ 0x5414
|
||||
#define TIOCMGET 0x5415
|
||||
#define TIOCMBIS 0x5416
|
||||
#define TIOCMBIC 0x5417
|
||||
#define TIOCMSET 0x5418
|
||||
#define TIOCGSOFTCAR 0x5419
|
||||
#define TIOCSSOFTCAR 0x541A
|
||||
#define FIONREAD 0x541B
|
||||
#define TIOCINQ FIONREAD
|
||||
#define TIOCLINUX 0x541C
|
||||
#define TIOCCONS 0x541D
|
||||
#define TIOCGSERIAL 0x541E
|
||||
#define TIOCSSERIAL 0x541F
|
||||
#define TIOCPKT 0x5420
|
||||
#define FIONBIO 0x5421
|
||||
#define TIOCNOTTY 0x5422
|
||||
#define TIOCSETD 0x5423
|
||||
#define TIOCGETD 0x5424
|
||||
#define TCSBRKP 0x5425 /* Needed for POSIX tcsendbreak() */
|
||||
#define TIOCSBRK 0x5427 /* BSD compatibility */
|
||||
#define TIOCCBRK 0x5428 /* BSD compatibility */
|
||||
#define TIOCGSID 0x5429 /* Return the session ID of FD */
|
||||
#define TCGETS2 _IOR('T', 0x2A, struct termios2)
|
||||
#define TCSETS2 _IOW('T', 0x2B, struct termios2)
|
||||
#define TCSETSW2 _IOW('T', 0x2C, struct termios2)
|
||||
#define TCSETSF2 _IOW('T', 0x2D, struct termios2)
|
||||
#define TIOCGRS485 0x542E
|
||||
#ifndef TIOCSRS485
|
||||
#define TIOCSRS485 0x542F
|
||||
#endif
|
||||
#define TIOCGPTN _IOR('T', 0x30, unsigned int) /* Get Pty Number (of pty-mux device) */
|
||||
#define TIOCSPTLCK _IOW('T', 0x31, int) /* Lock/unlock Pty */
|
||||
#define TIOCGDEV _IOR('T', 0x32, unsigned int) /* Get primary device node of /dev/console */
|
||||
#define TCGETX 0x5432 /* SYS5 TCGETX compatibility */
|
||||
#define TCSETX 0x5433
|
||||
#define TCSETXF 0x5434
|
||||
#define TCSETXW 0x5435
|
||||
#define TIOCSIG _IOW('T', 0x36, int) /* pty: generate signal */
|
||||
#define TIOCVHANGUP 0x5437
|
||||
#define TIOCGPKT _IOR('T', 0x38, int) /* Get packet mode state */
|
||||
#define TIOCGPTLCK _IOR('T', 0x39, int) /* Get Pty lock state */
|
||||
#define TIOCGEXCL _IOR('T', 0x40, int) /* Get exclusive mode state */
|
||||
#define TIOCGPTPEER _IO('T', 0x41) /* Safely open the slave */
|
||||
|
||||
#define FIONCLEX 0x5450
|
||||
#define FIOCLEX 0x5451
|
||||
#define FIOASYNC 0x5452
|
||||
#define TIOCSERCONFIG 0x5453
|
||||
#define TIOCSERGWILD 0x5454
|
||||
#define TIOCSERSWILD 0x5455
|
||||
#define TIOCGLCKTRMIOS 0x5456
|
||||
#define TIOCSLCKTRMIOS 0x5457
|
||||
#define TIOCSERGSTRUCT 0x5458 /* For debugging only */
|
||||
#define TIOCSERGETLSR 0x5459 /* Get line status register */
|
||||
#define TIOCSERGETMULTI 0x545A /* Get multiport config */
|
||||
#define TIOCSERSETMULTI 0x545B /* Set multiport config */
|
||||
|
||||
#define TIOCMIWAIT 0x545C /* wait for a change on serial input line(s) */
|
||||
#define TIOCGICOUNT 0x545D /* read serial port inline interrupt counts */
|
||||
|
||||
/*
|
||||
* Some arches already define FIOQSIZE due to a historical
|
||||
* conflict with a Hayes modem-specific ioctl value.
|
||||
*/
|
||||
#ifndef FIOQSIZE
|
||||
# define FIOQSIZE 0x5460
|
||||
#endif
|
||||
|
||||
/* Used for packet mode */
|
||||
#define TIOCPKT_DATA 0
|
||||
#define TIOCPKT_FLUSHREAD 1
|
||||
#define TIOCPKT_FLUSHWRITE 2
|
||||
#define TIOCPKT_STOP 4
|
||||
#define TIOCPKT_START 8
|
||||
#define TIOCPKT_NOSTOP 16
|
||||
#define TIOCPKT_DOSTOP 32
|
||||
#define TIOCPKT_IOCTL 64
|
||||
|
||||
#define TIOCSER_TEMT 0x01 /* Transmitter physically empty */
|
||||
|
||||
#endif /* __ASM_GENERIC_IOCTLS_H */
|
|
@ -0,0 +1,933 @@
|
|||
/**
|
||||
* \file drm.h
|
||||
* Header for the Direct Rendering Manager
|
||||
*
|
||||
* \author Rickard E. (Rik) Faith <faith@valinux.com>
|
||||
*
|
||||
* \par Acknowledgments:
|
||||
* Dec 1999, Richard Henderson <rth@twiddle.net>, move to generic \c cmpxchg.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
|
||||
* Copyright 2000 VA Linux Systems, Inc., Sunnyvale, California.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the next
|
||||
* paragraph) shall be included in all copies or substantial portions of the
|
||||
* Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
|
||||
* VA LINUX SYSTEMS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
|
||||
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
|
||||
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
||||
* OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _DRM_H_
|
||||
#define _DRM_H_
|
||||
|
||||
#if defined(__KERNEL__)
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <asm/ioctl.h>
|
||||
typedef unsigned int drm_handle_t;
|
||||
|
||||
#elif defined(__linux__)
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <asm/ioctl.h>
|
||||
typedef unsigned int drm_handle_t;
|
||||
|
||||
#else /* One of the BSDs */
|
||||
|
||||
#include <sys/ioccom.h>
|
||||
#include <sys/types.h>
|
||||
typedef int8_t __s8;
|
||||
typedef uint8_t __u8;
|
||||
typedef int16_t __s16;
|
||||
typedef uint16_t __u16;
|
||||
typedef int32_t __s32;
|
||||
typedef uint32_t __u32;
|
||||
typedef int64_t __s64;
|
||||
typedef uint64_t __u64;
|
||||
typedef size_t __kernel_size_t;
|
||||
typedef unsigned long drm_handle_t;
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DRM_NAME "drm" /**< Name in kernel, /dev, and /proc */
|
||||
#define DRM_MIN_ORDER 5 /**< At least 2^5 bytes = 32 bytes */
|
||||
#define DRM_MAX_ORDER 22 /**< Up to 2^22 bytes = 4MB */
|
||||
#define DRM_RAM_PERCENT 10 /**< How much system ram can we lock? */
|
||||
|
||||
#define _DRM_LOCK_HELD 0x80000000U /**< Hardware lock is held */
|
||||
#define _DRM_LOCK_CONT 0x40000000U /**< Hardware lock is contended */
|
||||
#define _DRM_LOCK_IS_HELD(lock) ((lock) & _DRM_LOCK_HELD)
|
||||
#define _DRM_LOCK_IS_CONT(lock) ((lock) & _DRM_LOCK_CONT)
|
||||
#define _DRM_LOCKING_CONTEXT(lock) ((lock) & ~(_DRM_LOCK_HELD|_DRM_LOCK_CONT))
|
||||
|
||||
typedef unsigned int drm_context_t;
|
||||
typedef unsigned int drm_drawable_t;
|
||||
typedef unsigned int drm_magic_t;
|
||||
|
||||
/**
|
||||
* Cliprect.
|
||||
*
|
||||
* \warning: If you change this structure, make sure you change
|
||||
* XF86DRIClipRectRec in the server as well
|
||||
*
|
||||
* \note KW: Actually it's illegal to change either for
|
||||
* backwards-compatibility reasons.
|
||||
*/
|
||||
struct drm_clip_rect {
|
||||
unsigned short x1;
|
||||
unsigned short y1;
|
||||
unsigned short x2;
|
||||
unsigned short y2;
|
||||
};
|
||||
|
||||
/**
|
||||
* Drawable information.
|
||||
*/
|
||||
struct drm_drawable_info {
|
||||
unsigned int num_rects;
|
||||
struct drm_clip_rect *rects;
|
||||
};
|
||||
|
||||
/**
|
||||
* Texture region,
|
||||
*/
|
||||
struct drm_tex_region {
|
||||
unsigned char next;
|
||||
unsigned char prev;
|
||||
unsigned char in_use;
|
||||
unsigned char padding;
|
||||
unsigned int age;
|
||||
};
|
||||
|
||||
/**
|
||||
* Hardware lock.
|
||||
*
|
||||
* The lock structure is a simple cache-line aligned integer. To avoid
|
||||
* processor bus contention on a multiprocessor system, there should not be any
|
||||
* other data stored in the same cache line.
|
||||
*/
|
||||
struct drm_hw_lock {
|
||||
__volatile__ unsigned int lock; /**< lock variable */
|
||||
char padding[60]; /**< Pad to cache line */
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_VERSION ioctl argument type.
|
||||
*
|
||||
* \sa drmGetVersion().
|
||||
*/
|
||||
struct drm_version {
|
||||
int version_major; /**< Major version */
|
||||
int version_minor; /**< Minor version */
|
||||
int version_patchlevel; /**< Patch level */
|
||||
__kernel_size_t name_len; /**< Length of name buffer */
|
||||
char __user *name; /**< Name of driver */
|
||||
__kernel_size_t date_len; /**< Length of date buffer */
|
||||
char __user *date; /**< User-space buffer to hold date */
|
||||
__kernel_size_t desc_len; /**< Length of desc buffer */
|
||||
char __user *desc; /**< User-space buffer to hold desc */
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_GET_UNIQUE ioctl argument type.
|
||||
*
|
||||
* \sa drmGetBusid() and drmSetBusId().
|
||||
*/
|
||||
struct drm_unique {
|
||||
__kernel_size_t unique_len; /**< Length of unique */
|
||||
char __user *unique; /**< Unique name for driver instantiation */
|
||||
};
|
||||
|
||||
struct drm_list {
|
||||
int count; /**< Length of user-space structures */
|
||||
struct drm_version __user *version;
|
||||
};
|
||||
|
||||
struct drm_block {
|
||||
int unused;
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_CONTROL ioctl argument type.
|
||||
*
|
||||
* \sa drmCtlInstHandler() and drmCtlUninstHandler().
|
||||
*/
|
||||
struct drm_control {
|
||||
enum {
|
||||
DRM_ADD_COMMAND,
|
||||
DRM_RM_COMMAND,
|
||||
DRM_INST_HANDLER,
|
||||
DRM_UNINST_HANDLER
|
||||
} func;
|
||||
int irq;
|
||||
};
|
||||
|
||||
/**
|
||||
* Type of memory to map.
|
||||
*/
|
||||
enum drm_map_type {
|
||||
_DRM_FRAME_BUFFER = 0, /**< WC (no caching), no core dump */
|
||||
_DRM_REGISTERS = 1, /**< no caching, no core dump */
|
||||
_DRM_SHM = 2, /**< shared, cached */
|
||||
_DRM_AGP = 3, /**< AGP/GART */
|
||||
_DRM_SCATTER_GATHER = 4, /**< Scatter/gather memory for PCI DMA */
|
||||
_DRM_CONSISTENT = 5 /**< Consistent memory for PCI DMA */
|
||||
};
|
||||
|
||||
/**
|
||||
* Memory mapping flags.
|
||||
*/
|
||||
enum drm_map_flags {
|
||||
_DRM_RESTRICTED = 0x01, /**< Cannot be mapped to user-virtual */
|
||||
_DRM_READ_ONLY = 0x02,
|
||||
_DRM_LOCKED = 0x04, /**< shared, cached, locked */
|
||||
_DRM_KERNEL = 0x08, /**< kernel requires access */
|
||||
_DRM_WRITE_COMBINING = 0x10, /**< use write-combining if available */
|
||||
_DRM_CONTAINS_LOCK = 0x20, /**< SHM page that contains lock */
|
||||
_DRM_REMOVABLE = 0x40, /**< Removable mapping */
|
||||
_DRM_DRIVER = 0x80 /**< Managed by driver */
|
||||
};
|
||||
|
||||
struct drm_ctx_priv_map {
|
||||
unsigned int ctx_id; /**< Context requesting private mapping */
|
||||
void *handle; /**< Handle of map */
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_GET_MAP, DRM_IOCTL_ADD_MAP and DRM_IOCTL_RM_MAP ioctls
|
||||
* argument type.
|
||||
*
|
||||
* \sa drmAddMap().
|
||||
*/
|
||||
struct drm_map {
|
||||
unsigned long offset; /**< Requested physical address (0 for SAREA)*/
|
||||
unsigned long size; /**< Requested physical size (bytes) */
|
||||
enum drm_map_type type; /**< Type of memory to map */
|
||||
enum drm_map_flags flags; /**< Flags */
|
||||
void *handle; /**< User-space: "Handle" to pass to mmap() */
|
||||
/**< Kernel-space: kernel-virtual address */
|
||||
int mtrr; /**< MTRR slot used */
|
||||
/* Private data */
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_GET_CLIENT ioctl argument type.
|
||||
*/
|
||||
struct drm_client {
|
||||
int idx; /**< Which client desired? */
|
||||
int auth; /**< Is client authenticated? */
|
||||
unsigned long pid; /**< Process ID */
|
||||
unsigned long uid; /**< User ID */
|
||||
unsigned long magic; /**< Magic */
|
||||
unsigned long iocs; /**< Ioctl count */
|
||||
};
|
||||
|
||||
enum drm_stat_type {
|
||||
_DRM_STAT_LOCK,
|
||||
_DRM_STAT_OPENS,
|
||||
_DRM_STAT_CLOSES,
|
||||
_DRM_STAT_IOCTLS,
|
||||
_DRM_STAT_LOCKS,
|
||||
_DRM_STAT_UNLOCKS,
|
||||
_DRM_STAT_VALUE, /**< Generic value */
|
||||
_DRM_STAT_BYTE, /**< Generic byte counter (1024bytes/K) */
|
||||
_DRM_STAT_COUNT, /**< Generic non-byte counter (1000/k) */
|
||||
|
||||
_DRM_STAT_IRQ, /**< IRQ */
|
||||
_DRM_STAT_PRIMARY, /**< Primary DMA bytes */
|
||||
_DRM_STAT_SECONDARY, /**< Secondary DMA bytes */
|
||||
_DRM_STAT_DMA, /**< DMA */
|
||||
_DRM_STAT_SPECIAL, /**< Special DMA (e.g., priority or polled) */
|
||||
_DRM_STAT_MISSED /**< Missed DMA opportunity */
|
||||
/* Add to the *END* of the list */
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_GET_STATS ioctl argument type.
|
||||
*/
|
||||
struct drm_stats {
|
||||
unsigned long count;
|
||||
struct {
|
||||
unsigned long value;
|
||||
enum drm_stat_type type;
|
||||
} data[15];
|
||||
};
|
||||
|
||||
/**
|
||||
* Hardware locking flags.
|
||||
*/
|
||||
enum drm_lock_flags {
|
||||
_DRM_LOCK_READY = 0x01, /**< Wait until hardware is ready for DMA */
|
||||
_DRM_LOCK_QUIESCENT = 0x02, /**< Wait until hardware quiescent */
|
||||
_DRM_LOCK_FLUSH = 0x04, /**< Flush this context's DMA queue first */
|
||||
_DRM_LOCK_FLUSH_ALL = 0x08, /**< Flush all DMA queues first */
|
||||
/* These *HALT* flags aren't supported yet
|
||||
-- they will be used to support the
|
||||
full-screen DGA-like mode. */
|
||||
_DRM_HALT_ALL_QUEUES = 0x10, /**< Halt all current and future queues */
|
||||
_DRM_HALT_CUR_QUEUES = 0x20 /**< Halt all current queues */
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_LOCK, DRM_IOCTL_UNLOCK and DRM_IOCTL_FINISH ioctl argument type.
|
||||
*
|
||||
* \sa drmGetLock() and drmUnlock().
|
||||
*/
|
||||
struct drm_lock {
|
||||
int context;
|
||||
enum drm_lock_flags flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* DMA flags
|
||||
*
|
||||
* \warning
|
||||
* These values \e must match xf86drm.h.
|
||||
*
|
||||
* \sa drm_dma.
|
||||
*/
|
||||
enum drm_dma_flags {
|
||||
/* Flags for DMA buffer dispatch */
|
||||
_DRM_DMA_BLOCK = 0x01, /**<
|
||||
* Block until buffer dispatched.
|
||||
*
|
||||
* \note The buffer may not yet have
|
||||
* been processed by the hardware --
|
||||
* getting a hardware lock with the
|
||||
* hardware quiescent will ensure
|
||||
* that the buffer has been
|
||||
* processed.
|
||||
*/
|
||||
_DRM_DMA_WHILE_LOCKED = 0x02, /**< Dispatch while lock held */
|
||||
_DRM_DMA_PRIORITY = 0x04, /**< High priority dispatch */
|
||||
|
||||
/* Flags for DMA buffer request */
|
||||
_DRM_DMA_WAIT = 0x10, /**< Wait for free buffers */
|
||||
_DRM_DMA_SMALLER_OK = 0x20, /**< Smaller-than-requested buffers OK */
|
||||
_DRM_DMA_LARGER_OK = 0x40 /**< Larger-than-requested buffers OK */
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_ADD_BUFS and DRM_IOCTL_MARK_BUFS ioctl argument type.
|
||||
*
|
||||
* \sa drmAddBufs().
|
||||
*/
|
||||
struct drm_buf_desc {
|
||||
int count; /**< Number of buffers of this size */
|
||||
int size; /**< Size in bytes */
|
||||
int low_mark; /**< Low water mark */
|
||||
int high_mark; /**< High water mark */
|
||||
enum {
|
||||
_DRM_PAGE_ALIGN = 0x01, /**< Align on page boundaries for DMA */
|
||||
_DRM_AGP_BUFFER = 0x02, /**< Buffer is in AGP space */
|
||||
_DRM_SG_BUFFER = 0x04, /**< Scatter/gather memory buffer */
|
||||
_DRM_FB_BUFFER = 0x08, /**< Buffer is in frame buffer */
|
||||
_DRM_PCI_BUFFER_RO = 0x10 /**< Map PCI DMA buffer read-only */
|
||||
} flags;
|
||||
unsigned long agp_start; /**<
|
||||
* Start address of where the AGP buffers are
|
||||
* in the AGP aperture
|
||||
*/
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_INFO_BUFS ioctl argument type.
|
||||
*/
|
||||
struct drm_buf_info {
|
||||
int count; /**< Entries in list */
|
||||
struct drm_buf_desc __user *list;
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_FREE_BUFS ioctl argument type.
|
||||
*/
|
||||
struct drm_buf_free {
|
||||
int count;
|
||||
int __user *list;
|
||||
};
|
||||
|
||||
/**
|
||||
* Buffer information
|
||||
*
|
||||
* \sa drm_buf_map.
|
||||
*/
|
||||
struct drm_buf_pub {
|
||||
int idx; /**< Index into the master buffer list */
|
||||
int total; /**< Buffer size */
|
||||
int used; /**< Amount of buffer in use (for DMA) */
|
||||
void __user *address; /**< Address of buffer */
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_MAP_BUFS ioctl argument type.
|
||||
*/
|
||||
struct drm_buf_map {
|
||||
int count; /**< Length of the buffer list */
|
||||
#ifdef __cplusplus
|
||||
void __user *virt;
|
||||
#else
|
||||
void __user *virtual; /**< Mmap'd area in user-virtual */
|
||||
#endif
|
||||
struct drm_buf_pub __user *list; /**< Buffer information */
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_DMA ioctl argument type.
|
||||
*
|
||||
* Indices here refer to the offset into the buffer list in drm_buf_get.
|
||||
*
|
||||
* \sa drmDMA().
|
||||
*/
|
||||
struct drm_dma {
|
||||
int context; /**< Context handle */
|
||||
int send_count; /**< Number of buffers to send */
|
||||
int __user *send_indices; /**< List of handles to buffers */
|
||||
int __user *send_sizes; /**< Lengths of data to send */
|
||||
enum drm_dma_flags flags; /**< Flags */
|
||||
int request_count; /**< Number of buffers requested */
|
||||
int request_size; /**< Desired size for buffers */
|
||||
int __user *request_indices; /**< Buffer information */
|
||||
int __user *request_sizes;
|
||||
int granted_count; /**< Number of buffers granted */
|
||||
};
|
||||
|
||||
enum drm_ctx_flags {
|
||||
_DRM_CONTEXT_PRESERVED = 0x01,
|
||||
_DRM_CONTEXT_2DONLY = 0x02
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_ADD_CTX ioctl argument type.
|
||||
*
|
||||
* \sa drmCreateContext() and drmDestroyContext().
|
||||
*/
|
||||
struct drm_ctx {
|
||||
drm_context_t handle;
|
||||
enum drm_ctx_flags flags;
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_RES_CTX ioctl argument type.
|
||||
*/
|
||||
struct drm_ctx_res {
|
||||
int count;
|
||||
struct drm_ctx __user *contexts;
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_ADD_DRAW and DRM_IOCTL_RM_DRAW ioctl argument type.
|
||||
*/
|
||||
struct drm_draw {
|
||||
drm_drawable_t handle;
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_UPDATE_DRAW ioctl argument type.
|
||||
*/
|
||||
typedef enum {
|
||||
DRM_DRAWABLE_CLIPRECTS
|
||||
} drm_drawable_info_type_t;
|
||||
|
||||
struct drm_update_draw {
|
||||
drm_drawable_t handle;
|
||||
unsigned int type;
|
||||
unsigned int num;
|
||||
unsigned long long data;
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_GET_MAGIC and DRM_IOCTL_AUTH_MAGIC ioctl argument type.
|
||||
*/
|
||||
struct drm_auth {
|
||||
drm_magic_t magic;
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_IRQ_BUSID ioctl argument type.
|
||||
*
|
||||
* \sa drmGetInterruptFromBusID().
|
||||
*/
|
||||
struct drm_irq_busid {
|
||||
int irq; /**< IRQ number */
|
||||
int busnum; /**< bus number */
|
||||
int devnum; /**< device number */
|
||||
int funcnum; /**< function number */
|
||||
};
|
||||
|
||||
enum drm_vblank_seq_type {
|
||||
_DRM_VBLANK_ABSOLUTE = 0x0, /**< Wait for specific vblank sequence number */
|
||||
_DRM_VBLANK_RELATIVE = 0x1, /**< Wait for given number of vblanks */
|
||||
/* bits 1-6 are reserved for high crtcs */
|
||||
_DRM_VBLANK_HIGH_CRTC_MASK = 0x0000003e,
|
||||
_DRM_VBLANK_EVENT = 0x4000000, /**< Send event instead of blocking */
|
||||
_DRM_VBLANK_FLIP = 0x8000000, /**< Scheduled buffer swap should flip */
|
||||
_DRM_VBLANK_NEXTONMISS = 0x10000000, /**< If missed, wait for next vblank */
|
||||
_DRM_VBLANK_SECONDARY = 0x20000000, /**< Secondary display controller */
|
||||
_DRM_VBLANK_SIGNAL = 0x40000000 /**< Send signal instead of blocking, unsupported */
|
||||
};
|
||||
#define _DRM_VBLANK_HIGH_CRTC_SHIFT 1
|
||||
|
||||
#define _DRM_VBLANK_TYPES_MASK (_DRM_VBLANK_ABSOLUTE | _DRM_VBLANK_RELATIVE)
|
||||
#define _DRM_VBLANK_FLAGS_MASK (_DRM_VBLANK_EVENT | _DRM_VBLANK_SIGNAL | \
|
||||
_DRM_VBLANK_SECONDARY | _DRM_VBLANK_NEXTONMISS)
|
||||
|
||||
struct drm_wait_vblank_request {
|
||||
enum drm_vblank_seq_type type;
|
||||
unsigned int sequence;
|
||||
unsigned long signal;
|
||||
};
|
||||
|
||||
struct drm_wait_vblank_reply {
|
||||
enum drm_vblank_seq_type type;
|
||||
unsigned int sequence;
|
||||
long tval_sec;
|
||||
long tval_usec;
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_WAIT_VBLANK ioctl argument type.
|
||||
*
|
||||
* \sa drmWaitVBlank().
|
||||
*/
|
||||
union drm_wait_vblank {
|
||||
struct drm_wait_vblank_request request;
|
||||
struct drm_wait_vblank_reply reply;
|
||||
};
|
||||
|
||||
#define _DRM_PRE_MODESET 1
|
||||
#define _DRM_POST_MODESET 2
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_MODESET_CTL ioctl argument type
|
||||
*
|
||||
* \sa drmModesetCtl().
|
||||
*/
|
||||
struct drm_modeset_ctl {
|
||||
__u32 crtc;
|
||||
__u32 cmd;
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_AGP_ENABLE ioctl argument type.
|
||||
*
|
||||
* \sa drmAgpEnable().
|
||||
*/
|
||||
struct drm_agp_mode {
|
||||
unsigned long mode; /**< AGP mode */
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_AGP_ALLOC and DRM_IOCTL_AGP_FREE ioctls argument type.
|
||||
*
|
||||
* \sa drmAgpAlloc() and drmAgpFree().
|
||||
*/
|
||||
struct drm_agp_buffer {
|
||||
unsigned long size; /**< In bytes -- will round to page boundary */
|
||||
unsigned long handle; /**< Used for binding / unbinding */
|
||||
unsigned long type; /**< Type of memory to allocate */
|
||||
unsigned long physical; /**< Physical used by i810 */
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_AGP_BIND and DRM_IOCTL_AGP_UNBIND ioctls argument type.
|
||||
*
|
||||
* \sa drmAgpBind() and drmAgpUnbind().
|
||||
*/
|
||||
struct drm_agp_binding {
|
||||
unsigned long handle; /**< From drm_agp_buffer */
|
||||
unsigned long offset; /**< In bytes -- will round to page boundary */
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_AGP_INFO ioctl argument type.
|
||||
*
|
||||
* \sa drmAgpVersionMajor(), drmAgpVersionMinor(), drmAgpGetMode(),
|
||||
* drmAgpBase(), drmAgpSize(), drmAgpMemoryUsed(), drmAgpMemoryAvail(),
|
||||
* drmAgpVendorId() and drmAgpDeviceId().
|
||||
*/
|
||||
struct drm_agp_info {
|
||||
int agp_version_major;
|
||||
int agp_version_minor;
|
||||
unsigned long mode;
|
||||
unsigned long aperture_base; /* physical address */
|
||||
unsigned long aperture_size; /* bytes */
|
||||
unsigned long memory_allowed; /* bytes */
|
||||
unsigned long memory_used;
|
||||
|
||||
/* PCI information */
|
||||
unsigned short id_vendor;
|
||||
unsigned short id_device;
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_SG_ALLOC ioctl argument type.
|
||||
*/
|
||||
struct drm_scatter_gather {
|
||||
unsigned long size; /**< In bytes -- will round to page boundary */
|
||||
unsigned long handle; /**< Used for mapping / unmapping */
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_IOCTL_SET_VERSION ioctl argument type.
|
||||
*/
|
||||
struct drm_set_version {
|
||||
int drm_di_major;
|
||||
int drm_di_minor;
|
||||
int drm_dd_major;
|
||||
int drm_dd_minor;
|
||||
};
|
||||
|
||||
/** DRM_IOCTL_GEM_CLOSE ioctl argument type */
|
||||
struct drm_gem_close {
|
||||
/** Handle of the object to be closed. */
|
||||
__u32 handle;
|
||||
__u32 pad;
|
||||
};
|
||||
|
||||
/** DRM_IOCTL_GEM_FLINK ioctl argument type */
|
||||
struct drm_gem_flink {
|
||||
/** Handle for the object being named */
|
||||
__u32 handle;
|
||||
|
||||
/** Returned global name */
|
||||
__u32 name;
|
||||
};
|
||||
|
||||
/** DRM_IOCTL_GEM_OPEN ioctl argument type */
|
||||
struct drm_gem_open {
|
||||
/** Name of object being opened */
|
||||
__u32 name;
|
||||
|
||||
/** Returned handle for the object */
|
||||
__u32 handle;
|
||||
|
||||
/** Returned size of the object */
|
||||
__u64 size;
|
||||
};
|
||||
|
||||
#define DRM_CAP_DUMB_BUFFER 0x1
|
||||
#define DRM_CAP_VBLANK_HIGH_CRTC 0x2
|
||||
#define DRM_CAP_DUMB_PREFERRED_DEPTH 0x3
|
||||
#define DRM_CAP_DUMB_PREFER_SHADOW 0x4
|
||||
#define DRM_CAP_PRIME 0x5
|
||||
#define DRM_PRIME_CAP_IMPORT 0x1
|
||||
#define DRM_PRIME_CAP_EXPORT 0x2
|
||||
#define DRM_CAP_TIMESTAMP_MONOTONIC 0x6
|
||||
#define DRM_CAP_ASYNC_PAGE_FLIP 0x7
|
||||
/*
|
||||
* The CURSOR_WIDTH and CURSOR_HEIGHT capabilities return a valid widthxheight
|
||||
* combination for the hardware cursor. The intention is that a hardware
|
||||
* agnostic userspace can query a cursor plane size to use.
|
||||
*
|
||||
* Note that the cross-driver contract is to merely return a valid size;
|
||||
* drivers are free to attach another meaning on top, eg. i915 returns the
|
||||
* maximum plane size.
|
||||
*/
|
||||
#define DRM_CAP_CURSOR_WIDTH 0x8
|
||||
#define DRM_CAP_CURSOR_HEIGHT 0x9
|
||||
#define DRM_CAP_ADDFB2_MODIFIERS 0x10
|
||||
#define DRM_CAP_PAGE_FLIP_TARGET 0x11
|
||||
#define DRM_CAP_CRTC_IN_VBLANK_EVENT 0x12
|
||||
#define DRM_CAP_SYNCOBJ 0x13
|
||||
|
||||
/** DRM_IOCTL_GET_CAP ioctl argument type */
|
||||
struct drm_get_cap {
|
||||
__u64 capability;
|
||||
__u64 value;
|
||||
};
|
||||
|
||||
/**
|
||||
* DRM_CLIENT_CAP_STEREO_3D
|
||||
*
|
||||
* if set to 1, the DRM core will expose the stereo 3D capabilities of the
|
||||
* monitor by advertising the supported 3D layouts in the flags of struct
|
||||
* drm_mode_modeinfo.
|
||||
*/
|
||||
#define DRM_CLIENT_CAP_STEREO_3D 1
|
||||
|
||||
/**
|
||||
* DRM_CLIENT_CAP_UNIVERSAL_PLANES
|
||||
*
|
||||
* If set to 1, the DRM core will expose all planes (overlay, primary, and
|
||||
* cursor) to userspace.
|
||||
*/
|
||||
#define DRM_CLIENT_CAP_UNIVERSAL_PLANES 2
|
||||
|
||||
/**
|
||||
* DRM_CLIENT_CAP_ATOMIC
|
||||
*
|
||||
* If set to 1, the DRM core will expose atomic properties to userspace
|
||||
*/
|
||||
#define DRM_CLIENT_CAP_ATOMIC 3
|
||||
|
||||
/** DRM_IOCTL_SET_CLIENT_CAP ioctl argument type */
|
||||
struct drm_set_client_cap {
|
||||
__u64 capability;
|
||||
__u64 value;
|
||||
};
|
||||
|
||||
#define DRM_RDWR O_RDWR
|
||||
#define DRM_CLOEXEC O_CLOEXEC
|
||||
struct drm_prime_handle {
|
||||
__u32 handle;
|
||||
|
||||
/** Flags.. only applicable for handle->fd */
|
||||
__u32 flags;
|
||||
|
||||
/** Returned dmabuf file descriptor */
|
||||
__s32 fd;
|
||||
};
|
||||
|
||||
struct drm_syncobj_create {
|
||||
__u32 handle;
|
||||
__u32 flags;
|
||||
};
|
||||
|
||||
struct drm_syncobj_destroy {
|
||||
__u32 handle;
|
||||
__u32 pad;
|
||||
};
|
||||
|
||||
#define DRM_SYNCOBJ_FD_TO_HANDLE_FLAGS_IMPORT_SYNC_FILE (1 << 0)
|
||||
#define DRM_SYNCOBJ_HANDLE_TO_FD_FLAGS_EXPORT_SYNC_FILE (1 << 0)
|
||||
struct drm_syncobj_handle {
|
||||
__u32 handle;
|
||||
__u32 flags;
|
||||
|
||||
__s32 fd;
|
||||
__u32 pad;
|
||||
};
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#include "drm_mode.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define DRM_IOCTL_BASE 'd'
|
||||
#define DRM_IO(nr) _IO(DRM_IOCTL_BASE,nr)
|
||||
#define DRM_IOR(nr,type) _IOR(DRM_IOCTL_BASE,nr,type)
|
||||
#define DRM_IOW(nr,type) _IOW(DRM_IOCTL_BASE,nr,type)
|
||||
#define DRM_IOWR(nr,type) _IOWR(DRM_IOCTL_BASE,nr,type)
|
||||
|
||||
#define DRM_IOCTL_VERSION DRM_IOWR(0x00, struct drm_version)
|
||||
#define DRM_IOCTL_GET_UNIQUE DRM_IOWR(0x01, struct drm_unique)
|
||||
#define DRM_IOCTL_GET_MAGIC DRM_IOR( 0x02, struct drm_auth)
|
||||
#define DRM_IOCTL_IRQ_BUSID DRM_IOWR(0x03, struct drm_irq_busid)
|
||||
#define DRM_IOCTL_GET_MAP DRM_IOWR(0x04, struct drm_map)
|
||||
#define DRM_IOCTL_GET_CLIENT DRM_IOWR(0x05, struct drm_client)
|
||||
#define DRM_IOCTL_GET_STATS DRM_IOR( 0x06, struct drm_stats)
|
||||
#define DRM_IOCTL_SET_VERSION DRM_IOWR(0x07, struct drm_set_version)
|
||||
#define DRM_IOCTL_MODESET_CTL DRM_IOW(0x08, struct drm_modeset_ctl)
|
||||
#define DRM_IOCTL_GEM_CLOSE DRM_IOW (0x09, struct drm_gem_close)
|
||||
#define DRM_IOCTL_GEM_FLINK DRM_IOWR(0x0a, struct drm_gem_flink)
|
||||
#define DRM_IOCTL_GEM_OPEN DRM_IOWR(0x0b, struct drm_gem_open)
|
||||
#define DRM_IOCTL_GET_CAP DRM_IOWR(0x0c, struct drm_get_cap)
|
||||
#define DRM_IOCTL_SET_CLIENT_CAP DRM_IOW( 0x0d, struct drm_set_client_cap)
|
||||
|
||||
#define DRM_IOCTL_SET_UNIQUE DRM_IOW( 0x10, struct drm_unique)
|
||||
#define DRM_IOCTL_AUTH_MAGIC DRM_IOW( 0x11, struct drm_auth)
|
||||
#define DRM_IOCTL_BLOCK DRM_IOWR(0x12, struct drm_block)
|
||||
#define DRM_IOCTL_UNBLOCK DRM_IOWR(0x13, struct drm_block)
|
||||
#define DRM_IOCTL_CONTROL DRM_IOW( 0x14, struct drm_control)
|
||||
#define DRM_IOCTL_ADD_MAP DRM_IOWR(0x15, struct drm_map)
|
||||
#define DRM_IOCTL_ADD_BUFS DRM_IOWR(0x16, struct drm_buf_desc)
|
||||
#define DRM_IOCTL_MARK_BUFS DRM_IOW( 0x17, struct drm_buf_desc)
|
||||
#define DRM_IOCTL_INFO_BUFS DRM_IOWR(0x18, struct drm_buf_info)
|
||||
#define DRM_IOCTL_MAP_BUFS DRM_IOWR(0x19, struct drm_buf_map)
|
||||
#define DRM_IOCTL_FREE_BUFS DRM_IOW( 0x1a, struct drm_buf_free)
|
||||
|
||||
#define DRM_IOCTL_RM_MAP DRM_IOW( 0x1b, struct drm_map)
|
||||
|
||||
#define DRM_IOCTL_SET_SAREA_CTX DRM_IOW( 0x1c, struct drm_ctx_priv_map)
|
||||
#define DRM_IOCTL_GET_SAREA_CTX DRM_IOWR(0x1d, struct drm_ctx_priv_map)
|
||||
|
||||
#define DRM_IOCTL_SET_MASTER DRM_IO(0x1e)
|
||||
#define DRM_IOCTL_DROP_MASTER DRM_IO(0x1f)
|
||||
|
||||
#define DRM_IOCTL_ADD_CTX DRM_IOWR(0x20, struct drm_ctx)
|
||||
#define DRM_IOCTL_RM_CTX DRM_IOWR(0x21, struct drm_ctx)
|
||||
#define DRM_IOCTL_MOD_CTX DRM_IOW( 0x22, struct drm_ctx)
|
||||
#define DRM_IOCTL_GET_CTX DRM_IOWR(0x23, struct drm_ctx)
|
||||
#define DRM_IOCTL_SWITCH_CTX DRM_IOW( 0x24, struct drm_ctx)
|
||||
#define DRM_IOCTL_NEW_CTX DRM_IOW( 0x25, struct drm_ctx)
|
||||
#define DRM_IOCTL_RES_CTX DRM_IOWR(0x26, struct drm_ctx_res)
|
||||
#define DRM_IOCTL_ADD_DRAW DRM_IOWR(0x27, struct drm_draw)
|
||||
#define DRM_IOCTL_RM_DRAW DRM_IOWR(0x28, struct drm_draw)
|
||||
#define DRM_IOCTL_DMA DRM_IOWR(0x29, struct drm_dma)
|
||||
#define DRM_IOCTL_LOCK DRM_IOW( 0x2a, struct drm_lock)
|
||||
#define DRM_IOCTL_UNLOCK DRM_IOW( 0x2b, struct drm_lock)
|
||||
#define DRM_IOCTL_FINISH DRM_IOW( 0x2c, struct drm_lock)
|
||||
|
||||
#define DRM_IOCTL_PRIME_HANDLE_TO_FD DRM_IOWR(0x2d, struct drm_prime_handle)
|
||||
#define DRM_IOCTL_PRIME_FD_TO_HANDLE DRM_IOWR(0x2e, struct drm_prime_handle)
|
||||
|
||||
#define DRM_IOCTL_AGP_ACQUIRE DRM_IO( 0x30)
|
||||
#define DRM_IOCTL_AGP_RELEASE DRM_IO( 0x31)
|
||||
#define DRM_IOCTL_AGP_ENABLE DRM_IOW( 0x32, struct drm_agp_mode)
|
||||
#define DRM_IOCTL_AGP_INFO DRM_IOR( 0x33, struct drm_agp_info)
|
||||
#define DRM_IOCTL_AGP_ALLOC DRM_IOWR(0x34, struct drm_agp_buffer)
|
||||
#define DRM_IOCTL_AGP_FREE DRM_IOW( 0x35, struct drm_agp_buffer)
|
||||
#define DRM_IOCTL_AGP_BIND DRM_IOW( 0x36, struct drm_agp_binding)
|
||||
#define DRM_IOCTL_AGP_UNBIND DRM_IOW( 0x37, struct drm_agp_binding)
|
||||
|
||||
#define DRM_IOCTL_SG_ALLOC DRM_IOWR(0x38, struct drm_scatter_gather)
|
||||
#define DRM_IOCTL_SG_FREE DRM_IOW( 0x39, struct drm_scatter_gather)
|
||||
|
||||
#define DRM_IOCTL_WAIT_VBLANK DRM_IOWR(0x3a, union drm_wait_vblank)
|
||||
|
||||
#define DRM_IOCTL_UPDATE_DRAW DRM_IOW(0x3f, struct drm_update_draw)
|
||||
|
||||
#define DRM_IOCTL_MODE_GETRESOURCES DRM_IOWR(0xA0, struct drm_mode_card_res)
|
||||
#define DRM_IOCTL_MODE_GETCRTC DRM_IOWR(0xA1, struct drm_mode_crtc)
|
||||
#define DRM_IOCTL_MODE_SETCRTC DRM_IOWR(0xA2, struct drm_mode_crtc)
|
||||
#define DRM_IOCTL_MODE_CURSOR DRM_IOWR(0xA3, struct drm_mode_cursor)
|
||||
#define DRM_IOCTL_MODE_GETGAMMA DRM_IOWR(0xA4, struct drm_mode_crtc_lut)
|
||||
#define DRM_IOCTL_MODE_SETGAMMA DRM_IOWR(0xA5, struct drm_mode_crtc_lut)
|
||||
#define DRM_IOCTL_MODE_GETENCODER DRM_IOWR(0xA6, struct drm_mode_get_encoder)
|
||||
#define DRM_IOCTL_MODE_GETCONNECTOR DRM_IOWR(0xA7, struct drm_mode_get_connector)
|
||||
#define DRM_IOCTL_MODE_ATTACHMODE DRM_IOWR(0xA8, struct drm_mode_mode_cmd) /* deprecated (never worked) */
|
||||
#define DRM_IOCTL_MODE_DETACHMODE DRM_IOWR(0xA9, struct drm_mode_mode_cmd) /* deprecated (never worked) */
|
||||
|
||||
#define DRM_IOCTL_MODE_GETPROPERTY DRM_IOWR(0xAA, struct drm_mode_get_property)
|
||||
#define DRM_IOCTL_MODE_SETPROPERTY DRM_IOWR(0xAB, struct drm_mode_connector_set_property)
|
||||
#define DRM_IOCTL_MODE_GETPROPBLOB DRM_IOWR(0xAC, struct drm_mode_get_blob)
|
||||
#define DRM_IOCTL_MODE_GETFB DRM_IOWR(0xAD, struct drm_mode_fb_cmd)
|
||||
#define DRM_IOCTL_MODE_ADDFB DRM_IOWR(0xAE, struct drm_mode_fb_cmd)
|
||||
#define DRM_IOCTL_MODE_RMFB DRM_IOWR(0xAF, unsigned int)
|
||||
#define DRM_IOCTL_MODE_PAGE_FLIP DRM_IOWR(0xB0, struct drm_mode_crtc_page_flip)
|
||||
#define DRM_IOCTL_MODE_DIRTYFB DRM_IOWR(0xB1, struct drm_mode_fb_dirty_cmd)
|
||||
|
||||
#define DRM_IOCTL_MODE_CREATE_DUMB DRM_IOWR(0xB2, struct drm_mode_create_dumb)
|
||||
#define DRM_IOCTL_MODE_MAP_DUMB DRM_IOWR(0xB3, struct drm_mode_map_dumb)
|
||||
#define DRM_IOCTL_MODE_DESTROY_DUMB DRM_IOWR(0xB4, struct drm_mode_destroy_dumb)
|
||||
#define DRM_IOCTL_MODE_GETPLANERESOURCES DRM_IOWR(0xB5, struct drm_mode_get_plane_res)
|
||||
#define DRM_IOCTL_MODE_GETPLANE DRM_IOWR(0xB6, struct drm_mode_get_plane)
|
||||
#define DRM_IOCTL_MODE_SETPLANE DRM_IOWR(0xB7, struct drm_mode_set_plane)
|
||||
#define DRM_IOCTL_MODE_ADDFB2 DRM_IOWR(0xB8, struct drm_mode_fb_cmd2)
|
||||
#define DRM_IOCTL_MODE_OBJ_GETPROPERTIES DRM_IOWR(0xB9, struct drm_mode_obj_get_properties)
|
||||
#define DRM_IOCTL_MODE_OBJ_SETPROPERTY DRM_IOWR(0xBA, struct drm_mode_obj_set_property)
|
||||
#define DRM_IOCTL_MODE_CURSOR2 DRM_IOWR(0xBB, struct drm_mode_cursor2)
|
||||
#define DRM_IOCTL_MODE_ATOMIC DRM_IOWR(0xBC, struct drm_mode_atomic)
|
||||
#define DRM_IOCTL_MODE_CREATEPROPBLOB DRM_IOWR(0xBD, struct drm_mode_create_blob)
|
||||
#define DRM_IOCTL_MODE_DESTROYPROPBLOB DRM_IOWR(0xBE, struct drm_mode_destroy_blob)
|
||||
|
||||
#define DRM_IOCTL_SYNCOBJ_CREATE DRM_IOWR(0xBF, struct drm_syncobj_create)
|
||||
#define DRM_IOCTL_SYNCOBJ_DESTROY DRM_IOWR(0xC0, struct drm_syncobj_destroy)
|
||||
#define DRM_IOCTL_SYNCOBJ_HANDLE_TO_FD DRM_IOWR(0xC1, struct drm_syncobj_handle)
|
||||
#define DRM_IOCTL_SYNCOBJ_FD_TO_HANDLE DRM_IOWR(0xC2, struct drm_syncobj_handle)
|
||||
|
||||
/**
|
||||
* Device specific ioctls should only be in their respective headers
|
||||
* The device specific ioctl range is from 0x40 to 0x9f.
|
||||
* Generic IOCTLS restart at 0xA0.
|
||||
*
|
||||
* \sa drmCommandNone(), drmCommandRead(), drmCommandWrite(), and
|
||||
* drmCommandReadWrite().
|
||||
*/
|
||||
#define DRM_COMMAND_BASE 0x40
|
||||
#define DRM_COMMAND_END 0xA0
|
||||
|
||||
/**
|
||||
* Header for events written back to userspace on the drm fd. The
|
||||
* type defines the type of event, the length specifies the total
|
||||
* length of the event (including the header), and user_data is
|
||||
* typically a 64 bit value passed with the ioctl that triggered the
|
||||
* event. A read on the drm fd will always only return complete
|
||||
* events, that is, if for example the read buffer is 100 bytes, and
|
||||
* there are two 64 byte events pending, only one will be returned.
|
||||
*
|
||||
* Event types 0 - 0x7fffffff are generic drm events, 0x80000000 and
|
||||
* up are chipset specific.
|
||||
*/
|
||||
struct drm_event {
|
||||
__u32 type;
|
||||
__u32 length;
|
||||
};
|
||||
|
||||
#define DRM_EVENT_VBLANK 0x01
|
||||
#define DRM_EVENT_FLIP_COMPLETE 0x02
|
||||
|
||||
struct drm_event_vblank {
|
||||
struct drm_event base;
|
||||
__u64 user_data;
|
||||
__u32 tv_sec;
|
||||
__u32 tv_usec;
|
||||
__u32 sequence;
|
||||
__u32 crtc_id; /* 0 on older kernels that do not support this */
|
||||
};
|
||||
|
||||
/* typedef area */
|
||||
#ifndef __KERNEL__
|
||||
typedef struct drm_clip_rect drm_clip_rect_t;
|
||||
typedef struct drm_drawable_info drm_drawable_info_t;
|
||||
typedef struct drm_tex_region drm_tex_region_t;
|
||||
typedef struct drm_hw_lock drm_hw_lock_t;
|
||||
typedef struct drm_version drm_version_t;
|
||||
typedef struct drm_unique drm_unique_t;
|
||||
typedef struct drm_list drm_list_t;
|
||||
typedef struct drm_block drm_block_t;
|
||||
typedef struct drm_control drm_control_t;
|
||||
typedef enum drm_map_type drm_map_type_t;
|
||||
typedef enum drm_map_flags drm_map_flags_t;
|
||||
typedef struct drm_ctx_priv_map drm_ctx_priv_map_t;
|
||||
typedef struct drm_map drm_map_t;
|
||||
typedef struct drm_client drm_client_t;
|
||||
typedef enum drm_stat_type drm_stat_type_t;
|
||||
typedef struct drm_stats drm_stats_t;
|
||||
typedef enum drm_lock_flags drm_lock_flags_t;
|
||||
typedef struct drm_lock drm_lock_t;
|
||||
typedef enum drm_dma_flags drm_dma_flags_t;
|
||||
typedef struct drm_buf_desc drm_buf_desc_t;
|
||||
typedef struct drm_buf_info drm_buf_info_t;
|
||||
typedef struct drm_buf_free drm_buf_free_t;
|
||||
typedef struct drm_buf_pub drm_buf_pub_t;
|
||||
typedef struct drm_buf_map drm_buf_map_t;
|
||||
typedef struct drm_dma drm_dma_t;
|
||||
typedef union drm_wait_vblank drm_wait_vblank_t;
|
||||
typedef struct drm_agp_mode drm_agp_mode_t;
|
||||
typedef enum drm_ctx_flags drm_ctx_flags_t;
|
||||
typedef struct drm_ctx drm_ctx_t;
|
||||
typedef struct drm_ctx_res drm_ctx_res_t;
|
||||
typedef struct drm_draw drm_draw_t;
|
||||
typedef struct drm_update_draw drm_update_draw_t;
|
||||
typedef struct drm_auth drm_auth_t;
|
||||
typedef struct drm_irq_busid drm_irq_busid_t;
|
||||
typedef enum drm_vblank_seq_type drm_vblank_seq_type_t;
|
||||
|
||||
typedef struct drm_agp_buffer drm_agp_buffer_t;
|
||||
typedef struct drm_agp_binding drm_agp_binding_t;
|
||||
typedef struct drm_agp_info drm_agp_info_t;
|
||||
typedef struct drm_scatter_gather drm_scatter_gather_t;
|
||||
typedef struct drm_set_version drm_set_version_t;
|
||||
#endif
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -643,7 +643,7 @@ enum bpf_func_id {
|
|||
|
||||
/* Mode for BPF_FUNC_skb_adjust_room helper. */
|
||||
enum bpf_adj_room_mode {
|
||||
BPF_ADJ_ROOM_NET_OPTS,
|
||||
BPF_ADJ_ROOM_NET,
|
||||
};
|
||||
|
||||
/* user accessible mirror of in-kernel sk_buff.
|
||||
|
@ -750,6 +750,8 @@ struct bpf_map_info {
|
|||
|
||||
/* User bpf_sock_ops struct to access socket values and specify request ops
|
||||
* and their replies.
|
||||
* Some of this fields are in network (bigendian) byte order and may need
|
||||
* to be converted before use (bpf_ntohl() defined in samples/bpf/bpf_endian.h).
|
||||
* New fields can only be added at the end of this structure
|
||||
*/
|
||||
struct bpf_sock_ops {
|
||||
|
@ -759,12 +761,12 @@ struct bpf_sock_ops {
|
|||
__u32 replylong[4];
|
||||
};
|
||||
__u32 family;
|
||||
__u32 remote_ip4;
|
||||
__u32 local_ip4;
|
||||
__u32 remote_ip6[4];
|
||||
__u32 local_ip6[4];
|
||||
__u32 remote_port;
|
||||
__u32 local_port;
|
||||
__u32 remote_ip4; /* Stored in network byte order */
|
||||
__u32 local_ip4; /* Stored in network byte order */
|
||||
__u32 remote_ip6[4]; /* Stored in network byte order */
|
||||
__u32 local_ip6[4]; /* Stored in network byte order */
|
||||
__u32 remote_port; /* Stored in network byte order */
|
||||
__u32 local_port; /* stored in host byte order */
|
||||
};
|
||||
|
||||
/* List of known BPF sock_ops operators.
|
||||
|
|
|
@ -42,6 +42,27 @@
|
|||
#define F_SEAL_WRITE 0x0008 /* prevent writes */
|
||||
/* (1U << 31) is reserved for signed error codes */
|
||||
|
||||
/*
|
||||
* Set/Get write life time hints. {GET,SET}_RW_HINT operate on the
|
||||
* underlying inode, while {GET,SET}_FILE_RW_HINT operate only on
|
||||
* the specific file.
|
||||
*/
|
||||
#define F_GET_RW_HINT (F_LINUX_SPECIFIC_BASE + 11)
|
||||
#define F_SET_RW_HINT (F_LINUX_SPECIFIC_BASE + 12)
|
||||
#define F_GET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 13)
|
||||
#define F_SET_FILE_RW_HINT (F_LINUX_SPECIFIC_BASE + 14)
|
||||
|
||||
/*
|
||||
* Valid hint values for F_{GET,SET}_RW_HINT. 0 is "not set", or can be
|
||||
* used to clear any hints previously set.
|
||||
*/
|
||||
#define RWF_WRITE_LIFE_NOT_SET 0
|
||||
#define RWH_WRITE_LIFE_NONE 1
|
||||
#define RWH_WRITE_LIFE_SHORT 2
|
||||
#define RWH_WRITE_LIFE_MEDIUM 3
|
||||
#define RWH_WRITE_LIFE_LONG 4
|
||||
#define RWH_WRITE_LIFE_EXTREME 5
|
||||
|
||||
/*
|
||||
* Types of directory notifications that may be requested.
|
||||
*/
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -174,6 +174,8 @@ enum perf_branch_sample_type_shift {
|
|||
PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT = 14, /* no flags */
|
||||
PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT = 15, /* no cycles */
|
||||
|
||||
PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT = 16, /* save branch type */
|
||||
|
||||
PERF_SAMPLE_BRANCH_MAX_SHIFT /* non-ABI */
|
||||
};
|
||||
|
||||
|
@ -198,9 +200,30 @@ enum perf_branch_sample_type {
|
|||
PERF_SAMPLE_BRANCH_NO_FLAGS = 1U << PERF_SAMPLE_BRANCH_NO_FLAGS_SHIFT,
|
||||
PERF_SAMPLE_BRANCH_NO_CYCLES = 1U << PERF_SAMPLE_BRANCH_NO_CYCLES_SHIFT,
|
||||
|
||||
PERF_SAMPLE_BRANCH_TYPE_SAVE =
|
||||
1U << PERF_SAMPLE_BRANCH_TYPE_SAVE_SHIFT,
|
||||
|
||||
PERF_SAMPLE_BRANCH_MAX = 1U << PERF_SAMPLE_BRANCH_MAX_SHIFT,
|
||||
};
|
||||
|
||||
/*
|
||||
* Common flow change classification
|
||||
*/
|
||||
enum {
|
||||
PERF_BR_UNKNOWN = 0, /* unknown */
|
||||
PERF_BR_COND = 1, /* conditional */
|
||||
PERF_BR_UNCOND = 2, /* unconditional */
|
||||
PERF_BR_IND = 3, /* indirect */
|
||||
PERF_BR_CALL = 4, /* function call */
|
||||
PERF_BR_IND_CALL = 5, /* indirect function call */
|
||||
PERF_BR_RET = 6, /* function return */
|
||||
PERF_BR_SYSCALL = 7, /* syscall */
|
||||
PERF_BR_SYSRET = 8, /* syscall return */
|
||||
PERF_BR_COND_CALL = 9, /* conditional function call */
|
||||
PERF_BR_COND_RET = 10, /* conditional function return */
|
||||
PERF_BR_MAX,
|
||||
};
|
||||
|
||||
#define PERF_SAMPLE_BRANCH_PLM_ALL \
|
||||
(PERF_SAMPLE_BRANCH_USER|\
|
||||
PERF_SAMPLE_BRANCH_KERNEL|\
|
||||
|
@ -931,14 +954,20 @@ union perf_mem_data_src {
|
|||
mem_snoop:5, /* snoop mode */
|
||||
mem_lock:2, /* lock instr */
|
||||
mem_dtlb:7, /* tlb access */
|
||||
mem_rsvd:31;
|
||||
mem_lvl_num:4, /* memory hierarchy level number */
|
||||
mem_remote:1, /* remote */
|
||||
mem_snoopx:2, /* snoop mode, ext */
|
||||
mem_rsvd:24;
|
||||
};
|
||||
};
|
||||
#elif defined(__BIG_ENDIAN_BITFIELD)
|
||||
union perf_mem_data_src {
|
||||
__u64 val;
|
||||
struct {
|
||||
__u64 mem_rsvd:31,
|
||||
__u64 mem_rsvd:24,
|
||||
mem_snoopx:2, /* snoop mode, ext */
|
||||
mem_remote:1, /* remote */
|
||||
mem_lvl_num:4, /* memory hierarchy level number */
|
||||
mem_dtlb:7, /* tlb access */
|
||||
mem_lock:2, /* lock instr */
|
||||
mem_snoop:5, /* snoop mode */
|
||||
|
@ -975,6 +1004,22 @@ union perf_mem_data_src {
|
|||
#define PERF_MEM_LVL_UNC 0x2000 /* Uncached memory */
|
||||
#define PERF_MEM_LVL_SHIFT 5
|
||||
|
||||
#define PERF_MEM_REMOTE_REMOTE 0x01 /* Remote */
|
||||
#define PERF_MEM_REMOTE_SHIFT 37
|
||||
|
||||
#define PERF_MEM_LVLNUM_L1 0x01 /* L1 */
|
||||
#define PERF_MEM_LVLNUM_L2 0x02 /* L2 */
|
||||
#define PERF_MEM_LVLNUM_L3 0x03 /* L3 */
|
||||
#define PERF_MEM_LVLNUM_L4 0x04 /* L4 */
|
||||
/* 5-0xa available */
|
||||
#define PERF_MEM_LVLNUM_ANY_CACHE 0x0b /* Any cache */
|
||||
#define PERF_MEM_LVLNUM_LFB 0x0c /* LFB */
|
||||
#define PERF_MEM_LVLNUM_RAM 0x0d /* RAM */
|
||||
#define PERF_MEM_LVLNUM_PMEM 0x0e /* PMEM */
|
||||
#define PERF_MEM_LVLNUM_NA 0x0f /* N/A */
|
||||
|
||||
#define PERF_MEM_LVLNUM_SHIFT 33
|
||||
|
||||
/* snoop mode */
|
||||
#define PERF_MEM_SNOOP_NA 0x01 /* not available */
|
||||
#define PERF_MEM_SNOOP_NONE 0x02 /* no snoop */
|
||||
|
@ -983,6 +1028,10 @@ union perf_mem_data_src {
|
|||
#define PERF_MEM_SNOOP_HITM 0x10 /* snoop hit modified */
|
||||
#define PERF_MEM_SNOOP_SHIFT 19
|
||||
|
||||
#define PERF_MEM_SNOOPX_FWD 0x01 /* forward */
|
||||
/* 1 free */
|
||||
#define PERF_MEM_SNOOPX_SHIFT 37
|
||||
|
||||
/* locked instruction */
|
||||
#define PERF_MEM_LOCK_NA 0x01 /* not available */
|
||||
#define PERF_MEM_LOCK_LOCKED 0x02 /* locked transaction */
|
||||
|
@ -1015,6 +1064,7 @@ union perf_mem_data_src {
|
|||
* in_tx: running in a hardware transaction
|
||||
* abort: aborting a hardware transaction
|
||||
* cycles: cycles from last branch (or 0 if not supported)
|
||||
* type: branch type
|
||||
*/
|
||||
struct perf_branch_entry {
|
||||
__u64 from;
|
||||
|
@ -1024,7 +1074,8 @@ struct perf_branch_entry {
|
|||
in_tx:1, /* in transaction */
|
||||
abort:1, /* transaction abort */
|
||||
cycles:16, /* cycle count to last branch */
|
||||
reserved:44;
|
||||
type:4, /* branch type */
|
||||
reserved:40;
|
||||
};
|
||||
|
||||
#endif /* _UAPI_LINUX_PERF_EVENT_H */
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
#ifndef _UAPI_LINUX_SCHED_H
|
||||
#define _UAPI_LINUX_SCHED_H
|
||||
|
||||
/*
|
||||
* cloning flags:
|
||||
*/
|
||||
#define CSIGNAL 0x000000ff /* signal mask to be sent at exit */
|
||||
#define CLONE_VM 0x00000100 /* set if VM shared between processes */
|
||||
#define CLONE_FS 0x00000200 /* set if fs info shared between processes */
|
||||
#define CLONE_FILES 0x00000400 /* set if open files shared between processes */
|
||||
#define CLONE_SIGHAND 0x00000800 /* set if signal handlers and blocked signals shared */
|
||||
#define CLONE_PTRACE 0x00002000 /* set if we want to let tracing continue on the child too */
|
||||
#define CLONE_VFORK 0x00004000 /* set if the parent wants the child to wake it up on mm_release */
|
||||
#define CLONE_PARENT 0x00008000 /* set if we want to have the same parent as the cloner */
|
||||
#define CLONE_THREAD 0x00010000 /* Same thread group? */
|
||||
#define CLONE_NEWNS 0x00020000 /* New mount namespace group */
|
||||
#define CLONE_SYSVSEM 0x00040000 /* share system V SEM_UNDO semantics */
|
||||
#define CLONE_SETTLS 0x00080000 /* create a new TLS for the child */
|
||||
#define CLONE_PARENT_SETTID 0x00100000 /* set the TID in the parent */
|
||||
#define CLONE_CHILD_CLEARTID 0x00200000 /* clear the TID in the child */
|
||||
#define CLONE_DETACHED 0x00400000 /* Unused, ignored */
|
||||
#define CLONE_UNTRACED 0x00800000 /* set if the tracing process can't force CLONE_PTRACE on this clone */
|
||||
#define CLONE_CHILD_SETTID 0x01000000 /* set the TID in the child */
|
||||
#define CLONE_NEWCGROUP 0x02000000 /* New cgroup namespace */
|
||||
#define CLONE_NEWUTS 0x04000000 /* New utsname namespace */
|
||||
#define CLONE_NEWIPC 0x08000000 /* New ipc namespace */
|
||||
#define CLONE_NEWUSER 0x10000000 /* New user namespace */
|
||||
#define CLONE_NEWPID 0x20000000 /* New pid namespace */
|
||||
#define CLONE_NEWNET 0x40000000 /* New network namespace */
|
||||
#define CLONE_IO 0x80000000 /* Clone io context */
|
||||
|
||||
/*
|
||||
* Scheduling policies
|
||||
*/
|
||||
#define SCHED_NORMAL 0
|
||||
#define SCHED_FIFO 1
|
||||
#define SCHED_RR 2
|
||||
#define SCHED_BATCH 3
|
||||
/* SCHED_ISO: reserved but not implemented yet */
|
||||
#define SCHED_IDLE 5
|
||||
#define SCHED_DEADLINE 6
|
||||
|
||||
/* Can be ORed in to make sure the process is reverted back to SCHED_NORMAL on fork */
|
||||
#define SCHED_RESET_ON_FORK 0x40000000
|
||||
|
||||
/*
|
||||
* For the sched_{set,get}attr() calls
|
||||
*/
|
||||
#define SCHED_FLAG_RESET_ON_FORK 0x01
|
||||
#define SCHED_FLAG_RECLAIM 0x02
|
||||
|
||||
#endif /* _UAPI_LINUX_SCHED_H */
|
|
@ -0,0 +1,209 @@
|
|||
#ifndef _LINUX_VHOST_H
|
||||
#define _LINUX_VHOST_H
|
||||
/* Userspace interface for in-kernel virtio accelerators. */
|
||||
|
||||
/* vhost is used to reduce the number of system calls involved in virtio.
|
||||
*
|
||||
* Existing virtio net code is used in the guest without modification.
|
||||
*
|
||||
* This header includes interface used by userspace hypervisor for
|
||||
* device configuration.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/virtio_config.h>
|
||||
#include <linux/virtio_ring.h>
|
||||
|
||||
struct vhost_vring_state {
|
||||
unsigned int index;
|
||||
unsigned int num;
|
||||
};
|
||||
|
||||
struct vhost_vring_file {
|
||||
unsigned int index;
|
||||
int fd; /* Pass -1 to unbind from file. */
|
||||
|
||||
};
|
||||
|
||||
struct vhost_vring_addr {
|
||||
unsigned int index;
|
||||
/* Option flags. */
|
||||
unsigned int flags;
|
||||
/* Flag values: */
|
||||
/* Whether log address is valid. If set enables logging. */
|
||||
#define VHOST_VRING_F_LOG 0
|
||||
|
||||
/* Start of array of descriptors (virtually contiguous) */
|
||||
__u64 desc_user_addr;
|
||||
/* Used structure address. Must be 32 bit aligned */
|
||||
__u64 used_user_addr;
|
||||
/* Available structure address. Must be 16 bit aligned */
|
||||
__u64 avail_user_addr;
|
||||
/* Logging support. */
|
||||
/* Log writes to used structure, at offset calculated from specified
|
||||
* address. Address must be 32 bit aligned. */
|
||||
__u64 log_guest_addr;
|
||||
};
|
||||
|
||||
/* no alignment requirement */
|
||||
struct vhost_iotlb_msg {
|
||||
__u64 iova;
|
||||
__u64 size;
|
||||
__u64 uaddr;
|
||||
#define VHOST_ACCESS_RO 0x1
|
||||
#define VHOST_ACCESS_WO 0x2
|
||||
#define VHOST_ACCESS_RW 0x3
|
||||
__u8 perm;
|
||||
#define VHOST_IOTLB_MISS 1
|
||||
#define VHOST_IOTLB_UPDATE 2
|
||||
#define VHOST_IOTLB_INVALIDATE 3
|
||||
#define VHOST_IOTLB_ACCESS_FAIL 4
|
||||
__u8 type;
|
||||
};
|
||||
|
||||
#define VHOST_IOTLB_MSG 0x1
|
||||
|
||||
struct vhost_msg {
|
||||
int type;
|
||||
union {
|
||||
struct vhost_iotlb_msg iotlb;
|
||||
__u8 padding[64];
|
||||
};
|
||||
};
|
||||
|
||||
struct vhost_memory_region {
|
||||
__u64 guest_phys_addr;
|
||||
__u64 memory_size; /* bytes */
|
||||
__u64 userspace_addr;
|
||||
__u64 flags_padding; /* No flags are currently specified. */
|
||||
};
|
||||
|
||||
/* All region addresses and sizes must be 4K aligned. */
|
||||
#define VHOST_PAGE_SIZE 0x1000
|
||||
|
||||
struct vhost_memory {
|
||||
__u32 nregions;
|
||||
__u32 padding;
|
||||
struct vhost_memory_region regions[0];
|
||||
};
|
||||
|
||||
/* ioctls */
|
||||
|
||||
#define VHOST_VIRTIO 0xAF
|
||||
|
||||
/* Features bitmask for forward compatibility. Transport bits are used for
|
||||
* vhost specific features. */
|
||||
#define VHOST_GET_FEATURES _IOR(VHOST_VIRTIO, 0x00, __u64)
|
||||
#define VHOST_SET_FEATURES _IOW(VHOST_VIRTIO, 0x00, __u64)
|
||||
|
||||
/* Set current process as the (exclusive) owner of this file descriptor. This
|
||||
* must be called before any other vhost command. Further calls to
|
||||
* VHOST_OWNER_SET fail until VHOST_OWNER_RESET is called. */
|
||||
#define VHOST_SET_OWNER _IO(VHOST_VIRTIO, 0x01)
|
||||
/* Give up ownership, and reset the device to default values.
|
||||
* Allows subsequent call to VHOST_OWNER_SET to succeed. */
|
||||
#define VHOST_RESET_OWNER _IO(VHOST_VIRTIO, 0x02)
|
||||
|
||||
/* Set up/modify memory layout */
|
||||
#define VHOST_SET_MEM_TABLE _IOW(VHOST_VIRTIO, 0x03, struct vhost_memory)
|
||||
|
||||
/* Write logging setup. */
|
||||
/* Memory writes can optionally be logged by setting bit at an offset
|
||||
* (calculated from the physical address) from specified log base.
|
||||
* The bit is set using an atomic 32 bit operation. */
|
||||
/* Set base address for logging. */
|
||||
#define VHOST_SET_LOG_BASE _IOW(VHOST_VIRTIO, 0x04, __u64)
|
||||
/* Specify an eventfd file descriptor to signal on log write. */
|
||||
#define VHOST_SET_LOG_FD _IOW(VHOST_VIRTIO, 0x07, int)
|
||||
|
||||
/* Ring setup. */
|
||||
/* Set number of descriptors in ring. This parameter can not
|
||||
* be modified while ring is running (bound to a device). */
|
||||
#define VHOST_SET_VRING_NUM _IOW(VHOST_VIRTIO, 0x10, struct vhost_vring_state)
|
||||
/* Set addresses for the ring. */
|
||||
#define VHOST_SET_VRING_ADDR _IOW(VHOST_VIRTIO, 0x11, struct vhost_vring_addr)
|
||||
/* Base value where queue looks for available descriptors */
|
||||
#define VHOST_SET_VRING_BASE _IOW(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
|
||||
/* Get accessor: reads index, writes value in num */
|
||||
#define VHOST_GET_VRING_BASE _IOWR(VHOST_VIRTIO, 0x12, struct vhost_vring_state)
|
||||
|
||||
/* Set the vring byte order in num. Valid values are VHOST_VRING_LITTLE_ENDIAN
|
||||
* or VHOST_VRING_BIG_ENDIAN (other values return -EINVAL).
|
||||
* The byte order cannot be changed while the device is active: trying to do so
|
||||
* returns -EBUSY.
|
||||
* This is a legacy only API that is simply ignored when VIRTIO_F_VERSION_1 is
|
||||
* set.
|
||||
* Not all kernel configurations support this ioctl, but all configurations that
|
||||
* support SET also support GET.
|
||||
*/
|
||||
#define VHOST_VRING_LITTLE_ENDIAN 0
|
||||
#define VHOST_VRING_BIG_ENDIAN 1
|
||||
#define VHOST_SET_VRING_ENDIAN _IOW(VHOST_VIRTIO, 0x13, struct vhost_vring_state)
|
||||
#define VHOST_GET_VRING_ENDIAN _IOW(VHOST_VIRTIO, 0x14, struct vhost_vring_state)
|
||||
|
||||
/* The following ioctls use eventfd file descriptors to signal and poll
|
||||
* for events. */
|
||||
|
||||
/* Set eventfd to poll for added buffers */
|
||||
#define VHOST_SET_VRING_KICK _IOW(VHOST_VIRTIO, 0x20, struct vhost_vring_file)
|
||||
/* Set eventfd to signal when buffers have beed used */
|
||||
#define VHOST_SET_VRING_CALL _IOW(VHOST_VIRTIO, 0x21, struct vhost_vring_file)
|
||||
/* Set eventfd to signal an error */
|
||||
#define VHOST_SET_VRING_ERR _IOW(VHOST_VIRTIO, 0x22, struct vhost_vring_file)
|
||||
/* Set busy loop timeout (in us) */
|
||||
#define VHOST_SET_VRING_BUSYLOOP_TIMEOUT _IOW(VHOST_VIRTIO, 0x23, \
|
||||
struct vhost_vring_state)
|
||||
/* Get busy loop timeout (in us) */
|
||||
#define VHOST_GET_VRING_BUSYLOOP_TIMEOUT _IOW(VHOST_VIRTIO, 0x24, \
|
||||
struct vhost_vring_state)
|
||||
|
||||
/* VHOST_NET specific defines */
|
||||
|
||||
/* Attach virtio net ring to a raw socket, or tap device.
|
||||
* The socket must be already bound to an ethernet device, this device will be
|
||||
* used for transmit. Pass fd -1 to unbind from the socket and the transmit
|
||||
* device. This can be used to stop the ring (e.g. for migration). */
|
||||
#define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
|
||||
|
||||
/* Feature bits */
|
||||
/* Log all write descriptors. Can be changed while device is active. */
|
||||
#define VHOST_F_LOG_ALL 26
|
||||
/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
|
||||
#define VHOST_NET_F_VIRTIO_NET_HDR 27
|
||||
|
||||
/* VHOST_SCSI specific definitions */
|
||||
|
||||
/*
|
||||
* Used by QEMU userspace to ensure a consistent vhost-scsi ABI.
|
||||
*
|
||||
* ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate +
|
||||
* RFC-v2 vhost-scsi userspace. Add GET_ABI_VERSION ioctl usage
|
||||
* ABI Rev 1: January 2013. Ignore vhost_tpgt filed in struct vhost_scsi_target.
|
||||
* All the targets under vhost_wwpn can be seen and used by guset.
|
||||
*/
|
||||
|
||||
#define VHOST_SCSI_ABI_VERSION 1
|
||||
|
||||
struct vhost_scsi_target {
|
||||
int abi_version;
|
||||
char vhost_wwpn[224]; /* TRANSPORT_IQN_LEN */
|
||||
unsigned short vhost_tpgt;
|
||||
unsigned short reserved;
|
||||
};
|
||||
|
||||
#define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target)
|
||||
#define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
|
||||
/* Changing this breaks userspace. */
|
||||
#define VHOST_SCSI_GET_ABI_VERSION _IOW(VHOST_VIRTIO, 0x42, int)
|
||||
/* Set and get the events missed flag */
|
||||
#define VHOST_SCSI_SET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x43, __u32)
|
||||
#define VHOST_SCSI_GET_EVENTS_MISSED _IOW(VHOST_VIRTIO, 0x44, __u32)
|
||||
|
||||
/* VHOST_VSOCK specific defines */
|
||||
|
||||
#define VHOST_VSOCK_SET_GUEST_CID _IOW(VHOST_VIRTIO, 0x60, __u64)
|
||||
#define VHOST_VSOCK_SET_RUNNING _IOW(VHOST_VIRTIO, 0x61, int)
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -8,9 +8,9 @@ srctree := $(patsubst %/,%,$(dir $(srctree)))
|
|||
#$(info Determined 'srctree' to be $(srctree))
|
||||
endif
|
||||
|
||||
CC = $(CROSS_COMPILE)gcc
|
||||
AR = $(CROSS_COMPILE)ar
|
||||
LD = $(CROSS_COMPILE)ld
|
||||
CC ?= $(CROSS_COMPILE)gcc
|
||||
AR ?= $(CROSS_COMPILE)ar
|
||||
LD ?= $(CROSS_COMPILE)ld
|
||||
|
||||
MAKEFLAGS += --no-print-directory
|
||||
|
||||
|
@ -19,7 +19,7 @@ LIBFILE = $(OUTPUT)libapi.a
|
|||
CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
|
||||
CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
|
||||
|
||||
ifeq ($(CC), clang)
|
||||
ifeq ($(CC_NO_CLANG), 0)
|
||||
CFLAGS += -O3
|
||||
else
|
||||
CFLAGS += -O6
|
||||
|
|
|
@ -154,12 +154,12 @@ all: fixdep $(VERSION_FILES) all_cmd
|
|||
all_cmd: $(CMD_TARGETS)
|
||||
|
||||
$(BPF_IN): force elfdep bpfdep
|
||||
@(test -f ../../../include/uapi/linux/bpf.h -a -f ../../../include/uapi/linux/bpf.h && ( \
|
||||
@(test -f ../../include/uapi/linux/bpf.h -a -f ../../../include/uapi/linux/bpf.h && ( \
|
||||
(diff -B ../../include/uapi/linux/bpf.h ../../../include/uapi/linux/bpf.h >/dev/null) || \
|
||||
echo "Warning: tools/include/uapi/linux/bpf.h differs from kernel" >&2 )) || true
|
||||
@(test -f ../../../include/uapi/linux/bpf_common.h -a -f ../../../include/uapi/linux/bpf_common.h && ( \
|
||||
echo "Warning: Kernel ABI header at 'tools/include/uapi/linux/bpf.h' differs from latest version at 'include/uapi/linux/bpf.h'" >&2 )) || true
|
||||
@(test -f ../../include/uapi/linux/bpf_common.h -a -f ../../../include/uapi/linux/bpf_common.h && ( \
|
||||
(diff -B ../../include/uapi/linux/bpf_common.h ../../../include/uapi/linux/bpf_common.h >/dev/null) || \
|
||||
echo "Warning: tools/include/uapi/linux/bpf_common.h differs from kernel" >&2 )) || true
|
||||
echo "Warning: Kernel ABI header at 'tools/include/uapi/linux/bpf_common.h' differs from latest version at 'include/uapi/linux/bpf_common.h'" >&2 )) || true
|
||||
$(Q)$(MAKE) $(build)=libbpf
|
||||
|
||||
$(OUTPUT)libbpf.so: $(BPF_IN)
|
||||
|
|
|
@ -39,27 +39,45 @@ void *memdup(const void *src, size_t len)
|
|||
* @s: input string
|
||||
* @res: result
|
||||
*
|
||||
* This routine returns 0 iff the first character is one of 'Yy1Nn0'.
|
||||
* Otherwise it will return -EINVAL. Value pointed to by res is
|
||||
* updated upon finding a match.
|
||||
* This routine returns 0 iff the first character is one of 'Yy1Nn0', or
|
||||
* [oO][NnFf] for "on" and "off". Otherwise it will return -EINVAL. Value
|
||||
* pointed to by res is updated upon finding a match.
|
||||
*/
|
||||
int strtobool(const char *s, bool *res)
|
||||
{
|
||||
if (!s)
|
||||
return -EINVAL;
|
||||
|
||||
switch (s[0]) {
|
||||
case 'y':
|
||||
case 'Y':
|
||||
case '1':
|
||||
*res = true;
|
||||
break;
|
||||
return 0;
|
||||
case 'n':
|
||||
case 'N':
|
||||
case '0':
|
||||
*res = false;
|
||||
break;
|
||||
return 0;
|
||||
case 'o':
|
||||
case 'O':
|
||||
switch (s[1]) {
|
||||
case 'n':
|
||||
case 'N':
|
||||
*res = true;
|
||||
return 0;
|
||||
case 'f':
|
||||
case 'F':
|
||||
*res = false;
|
||||
return 0;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return -EINVAL;
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -87,12 +105,3 @@ size_t __weak strlcpy(char *dest, const char *src, size_t size)
|
|||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int prefixcmp(const char *str, const char *prefix)
|
||||
{
|
||||
for (; ; str++, prefix++)
|
||||
if (!*prefix)
|
||||
return 0;
|
||||
else if (*str != *prefix)
|
||||
return (unsigned char)*prefix - (unsigned char)*str;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ LIBFILE = $(OUTPUT)libsubcmd.a
|
|||
CFLAGS := $(EXTRA_WARNINGS) $(EXTRA_CFLAGS)
|
||||
CFLAGS += -ggdb3 -Wall -Wextra -std=gnu99 -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fPIC
|
||||
|
||||
ifeq ($(CC), clang)
|
||||
ifeq ($(CC_NO_CLANG), 0)
|
||||
CFLAGS += -O3
|
||||
else
|
||||
CFLAGS += -O6
|
||||
|
|
|
@ -171,7 +171,7 @@ static void list_commands_in_dir(struct cmdnames *cmds,
|
|||
while ((de = readdir(dir)) != NULL) {
|
||||
int entlen;
|
||||
|
||||
if (prefixcmp(de->d_name, prefix))
|
||||
if (!strstarts(de->d_name, prefix))
|
||||
continue;
|
||||
|
||||
astrcat(&buf, de->d_name);
|
||||
|
|
|
@ -368,7 +368,7 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
|
|||
return 0;
|
||||
}
|
||||
if (!rest) {
|
||||
if (!prefixcmp(options->long_name, "no-")) {
|
||||
if (strstarts(options->long_name, "no-")) {
|
||||
/*
|
||||
* The long name itself starts with "no-", so
|
||||
* accept the option without "no-" so that users
|
||||
|
@ -381,7 +381,7 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
|
|||
goto match;
|
||||
}
|
||||
/* Abbreviated case */
|
||||
if (!prefixcmp(options->long_name + 3, arg)) {
|
||||
if (strstarts(options->long_name + 3, arg)) {
|
||||
flags |= OPT_UNSET;
|
||||
goto is_abbreviated;
|
||||
}
|
||||
|
@ -406,7 +406,7 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
|
|||
continue;
|
||||
}
|
||||
/* negated and abbreviated very much? */
|
||||
if (!prefixcmp("no-", arg)) {
|
||||
if (strstarts("no-", arg)) {
|
||||
flags |= OPT_UNSET;
|
||||
goto is_abbreviated;
|
||||
}
|
||||
|
@ -416,7 +416,7 @@ static int parse_long_opt(struct parse_opt_ctx_t *p, const char *arg,
|
|||
flags |= OPT_UNSET;
|
||||
rest = skip_prefix(arg + 3, options->long_name);
|
||||
/* abbreviated and negated? */
|
||||
if (!rest && !prefixcmp(options->long_name, arg + 3))
|
||||
if (!rest && strstarts(options->long_name, arg + 3))
|
||||
goto is_abbreviated;
|
||||
if (!rest)
|
||||
continue;
|
||||
|
@ -456,7 +456,7 @@ static void check_typos(const char *arg, const struct option *options)
|
|||
if (strlen(arg) < 3)
|
||||
return;
|
||||
|
||||
if (!prefixcmp(arg, "no-")) {
|
||||
if (strstarts(arg, "no-")) {
|
||||
fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
|
||||
exit(129);
|
||||
}
|
||||
|
@ -464,7 +464,7 @@ static void check_typos(const char *arg, const struct option *options)
|
|||
for (; options->type != OPTION_END; options++) {
|
||||
if (!options->long_name)
|
||||
continue;
|
||||
if (!prefixcmp(options->long_name, arg)) {
|
||||
if (strstarts(options->long_name, arg)) {
|
||||
fprintf(stderr, " Error: did you mean `--%s` (with two dashes ?)", arg);
|
||||
exit(129);
|
||||
}
|
||||
|
@ -933,10 +933,10 @@ int parse_options_usage(const char * const *usagestr,
|
|||
if (opts->long_name == NULL)
|
||||
continue;
|
||||
|
||||
if (!prefixcmp(opts->long_name, optstr))
|
||||
if (strstarts(opts->long_name, optstr))
|
||||
print_option_help(opts, 0);
|
||||
if (!prefixcmp("no-", optstr) &&
|
||||
!prefixcmp(opts->long_name, optstr + 3))
|
||||
if (strstarts("no-", optstr) &&
|
||||
strstarts(opts->long_name, optstr + 3))
|
||||
print_option_help(opts, 0);
|
||||
}
|
||||
|
||||
|
|
|
@ -50,6 +50,6 @@ libperf-y += util/
|
|||
libperf-y += arch/
|
||||
libperf-y += ui/
|
||||
libperf-y += scripts/
|
||||
libperf-y += trace/beauty/
|
||||
libperf-$(CONFIG_AUDIT) += trace/beauty/
|
||||
|
||||
gtk-y += ui/gtk/
|
||||
|
|
|
@ -192,7 +192,7 @@ do-install-man: man
|
|||
# $(INSTALL) -m 644 $(DOC_MAN5) $(DESTDIR)$(man5dir); \
|
||||
# $(INSTALL) -m 644 $(DOC_MAN7) $(DESTDIR)$(man7dir)
|
||||
|
||||
install-man: check-man-tools man
|
||||
install-man: check-man-tools man do-install-man
|
||||
|
||||
ifdef missing_tools
|
||||
DO_INSTALL_MAN = $(warning Please install $(missing_tools) to have the man pages installed)
|
||||
|
|
|
@ -104,9 +104,9 @@ system, asynchronous, interrupt, transaction abort, trace begin, trace end, and
|
|||
in transaction, respectively.
|
||||
|
||||
While it is possible to create scripts to analyze the data, an alternative
|
||||
approach is available to export the data to a postgresql database. Refer to
|
||||
script export-to-postgresql.py for more details, and to script
|
||||
call-graph-from-postgresql.py for an example of using the database.
|
||||
approach is available to export the data to a sqlite or postgresql database.
|
||||
Refer to script export-to-sqlite.py or export-to-postgresql.py for more details,
|
||||
and to script call-graph-from-sql.py for an example of using the database.
|
||||
|
||||
There is also script intel-pt-events.py which provides an example of how to
|
||||
unpack the raw data for power events and PTWRITE.
|
||||
|
|
|
@ -43,6 +43,10 @@ OPTIONS
|
|||
--quiet::
|
||||
Do not show any message. (Suppress -v)
|
||||
|
||||
-n::
|
||||
--show-nr-samples::
|
||||
Show the number of samples for each symbol
|
||||
|
||||
-D::
|
||||
--dump-raw-trace::
|
||||
Dump raw trace in ASCII.
|
||||
|
@ -88,6 +92,8 @@ OPTIONS
|
|||
--asm-raw::
|
||||
Show raw instruction encoding of assembly instructions.
|
||||
|
||||
--show-total-period:: Show a column with the sum of periods.
|
||||
|
||||
--source::
|
||||
Interleave source code with assembly code. Enabled by default,
|
||||
disable with --no-source.
|
||||
|
|
|
@ -61,6 +61,11 @@ OPTIONS
|
|||
--verbose::
|
||||
Be more verbose.
|
||||
|
||||
--target-ns=PID:
|
||||
Obtain mount namespace information from the target pid. This is
|
||||
used when creating a uprobe for a process that resides in a
|
||||
different mount namespace from the perf(1) utility.
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-buildid-list[1]
|
||||
|
|
|
@ -130,6 +130,11 @@ OPTIONS
|
|||
--max-probes=NUM::
|
||||
Set the maximum number of probe points for an event. Default is 128.
|
||||
|
||||
--target-ns=PID:
|
||||
Obtain mount namespace information from the target pid. This is
|
||||
used when creating a uprobe for a process that resides in a
|
||||
different mount namespace from the perf(1) utility.
|
||||
|
||||
-x::
|
||||
--exec=PATH::
|
||||
Specify path to the executable or shared library file for user
|
||||
|
@ -264,6 +269,15 @@ Add probes at malloc() function on libc
|
|||
|
||||
./perf probe -x /lib/libc.so.6 malloc or ./perf probe /lib/libc.so.6 malloc
|
||||
|
||||
Add a uprobe to a target process running in a different mount namespace
|
||||
|
||||
./perf probe --target-ns <target pid> -x /lib64/libc.so.6 malloc
|
||||
|
||||
Add a USDT probe to a target process running in a different mount namespace
|
||||
|
||||
./perf probe --target-ns <target pid> -x /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.121-0.b13.el7_3.x86_64/jre/lib/amd64/server/libjvm.so %sdt_hotspot:thread__sleep__end
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkperf:perf-trace[1], linkperf:perf-record[1], linkperf:perf-buildid-cache[1]
|
||||
|
|
|
@ -332,6 +332,7 @@ following filters are defined:
|
|||
- no_tx: only when the target is not in a hardware transaction
|
||||
- abort_tx: only when the target is a hardware transaction abort
|
||||
- cond: conditional branches
|
||||
- save_type: save branch type during sampling in case binary is not available later
|
||||
|
||||
+
|
||||
The option requires at least one branch type among any, any_call, any_ret, ind_call, cond.
|
||||
|
|
|
@ -41,13 +41,13 @@ report::
|
|||
|
||||
- a symbolically formed event like 'pmu/param1=0x3,param2/' where
|
||||
param1 and param2 are defined as formats for the PMU in
|
||||
/sys/bus/event_sources/devices/<pmu>/format/*
|
||||
/sys/bus/event_source/devices/<pmu>/format/*
|
||||
|
||||
- a symbolically formed event like 'pmu/config=M,config1=N,config2=K/'
|
||||
where M, N, K are numbers (in decimal, hex, octal format).
|
||||
Acceptable values for each of 'config', 'config1' and 'config2'
|
||||
parameters are defined by corresponding entries in
|
||||
/sys/bus/event_sources/devices/<pmu>/format/*
|
||||
/sys/bus/event_source/devices/<pmu>/format/*
|
||||
|
||||
-i::
|
||||
--no-inherit::
|
||||
|
|
|
@ -237,6 +237,10 @@ Default is to monitor all CPUS.
|
|||
--hierarchy::
|
||||
Enable hierarchy output.
|
||||
|
||||
--force::
|
||||
Don't do ownership validation.
|
||||
|
||||
|
||||
INTERACTIVE PROMPTING KEYS
|
||||
--------------------------
|
||||
|
||||
|
|
|
@ -398,6 +398,11 @@ struct auxtrace_error_event {
|
|||
char msg[MAX_AUXTRACE_ERROR_MSG];
|
||||
};
|
||||
|
||||
PERF_RECORD_HEADER_FEATURE = 80,
|
||||
|
||||
Describes a header feature. These are records used in pipe-mode that
|
||||
contain information that otherwise would be in perf.data file's header.
|
||||
|
||||
Event types
|
||||
|
||||
Define the event attributes with their IDs.
|
||||
|
@ -422,8 +427,9 @@ struct perf_pipe_file_header {
|
|||
};
|
||||
|
||||
The information about attrs, data, and event_types is instead in the
|
||||
synthesized events PERF_RECORD_ATTR, PERF_RECORD_HEADER_TRACING_DATA and
|
||||
PERF_RECORD_HEADER_EVENT_TYPE that are generated by perf record in pipe-mode.
|
||||
synthesized events PERF_RECORD_ATTR, PERF_RECORD_HEADER_TRACING_DATA,
|
||||
PERF_RECORD_HEADER_EVENT_TYPE, and PERF_RECORD_HEADER_FEATURE
|
||||
that are generated by perf record in pipe-mode.
|
||||
|
||||
|
||||
References:
|
||||
|
|
|
@ -70,15 +70,23 @@ tools/include/linux/hash.h
|
|||
tools/include/linux/kernel.h
|
||||
tools/include/linux/list.h
|
||||
tools/include/linux/log2.h
|
||||
tools/include/uapi/asm-generic/fcntl.h
|
||||
tools/include/uapi/asm-generic/ioctls.h
|
||||
tools/include/uapi/asm-generic/mman-common.h
|
||||
tools/include/uapi/asm-generic/mman.h
|
||||
tools/include/uapi/drm/drm.h
|
||||
tools/include/uapi/drm/i915_drm.h
|
||||
tools/include/uapi/linux/bpf.h
|
||||
tools/include/uapi/linux/bpf_common.h
|
||||
tools/include/uapi/linux/fcntl.h
|
||||
tools/include/uapi/linux/hw_breakpoint.h
|
||||
tools/include/uapi/linux/kvm.h
|
||||
tools/include/uapi/linux/mman.h
|
||||
tools/include/uapi/linux/perf_event.h
|
||||
tools/include/uapi/linux/sched.h
|
||||
tools/include/uapi/linux/stat.h
|
||||
tools/include/uapi/linux/vhost.h
|
||||
tools/include/uapi/sound/asound.h
|
||||
tools/include/linux/poison.h
|
||||
tools/include/linux/rbtree.h
|
||||
tools/include/linux/rbtree_augmented.h
|
||||
|
|
|
@ -35,7 +35,7 @@ ifeq ($(SRCARCH),x86)
|
|||
ifeq (${IS_64_BIT}, 1)
|
||||
CFLAGS += -DHAVE_ARCH_X86_64_SUPPORT -DHAVE_SYSCALL_TABLE -I$(OUTPUT)arch/x86/include/generated
|
||||
ARCH_INCLUDE = ../../arch/x86/lib/memcpy_64.S ../../arch/x86/lib/memset_64.S
|
||||
LIBUNWIND_LIBS = -lunwind -lunwind-x86_64
|
||||
LIBUNWIND_LIBS = -lunwind-x86_64 -lunwind -llzma
|
||||
$(call detected,CONFIG_X86_64)
|
||||
else
|
||||
LIBUNWIND_LIBS = -lunwind-x86 -llzma -lunwind
|
||||
|
@ -103,8 +103,12 @@ ifdef LIBDW_DIR
|
|||
LIBDW_CFLAGS := -I$(LIBDW_DIR)/include
|
||||
LIBDW_LDFLAGS := -L$(LIBDW_DIR)/lib
|
||||
endif
|
||||
DWARFLIBS := -ldw
|
||||
ifeq ($(findstring -static,${LDFLAGS}),-static)
|
||||
DWARFLIBS += -lelf -lebl -ldl -lz -llzma -lbz2
|
||||
endif
|
||||
FEATURE_CHECK_CFLAGS-libdw-dwarf-unwind := $(LIBDW_CFLAGS)
|
||||
FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) -ldw
|
||||
FEATURE_CHECK_LDFLAGS-libdw-dwarf-unwind := $(LIBDW_LDFLAGS) $(DWARFLIBS)
|
||||
|
||||
# for linking with debug library, run like:
|
||||
# make DEBUG=1 LIBBABELTRACE_DIR=/opt/libbabeltrace/
|
||||
|
@ -144,7 +148,7 @@ ifndef DEBUG
|
|||
endif
|
||||
|
||||
ifeq ($(DEBUG),0)
|
||||
ifeq ($(CC), clang)
|
||||
ifeq ($(CC_NO_CLANG), 0)
|
||||
CFLAGS += -O3
|
||||
else
|
||||
CFLAGS += -O6
|
||||
|
@ -180,7 +184,7 @@ ifdef PYTHON_CONFIG
|
|||
PYTHON_EMBED_LDFLAGS := $(call strip-libs,$(PYTHON_EMBED_LDOPTS))
|
||||
PYTHON_EMBED_LIBADD := $(call grep-libs,$(PYTHON_EMBED_LDOPTS)) -lutil
|
||||
PYTHON_EMBED_CCOPTS := $(shell $(PYTHON_CONFIG_SQ) --cflags 2>/dev/null)
|
||||
ifeq ($(CC), clang)
|
||||
ifeq ($(CC_NO_CLANG), 1)
|
||||
PYTHON_EMBED_CCOPTS := $(filter-out -specs=%,$(PYTHON_EMBED_CCOPTS))
|
||||
endif
|
||||
FLAGS_PYTHON_EMBED := $(PYTHON_EMBED_CCOPTS) $(PYTHON_EMBED_LDOPTS)
|
||||
|
@ -330,6 +334,11 @@ ifeq ($(feature-sched_getcpu), 1)
|
|||
CFLAGS += -DHAVE_SCHED_GETCPU_SUPPORT
|
||||
endif
|
||||
|
||||
ifeq ($(feature-setns), 1)
|
||||
CFLAGS += -DHAVE_SETNS_SUPPORT
|
||||
$(call detected,CONFIG_SETNS)
|
||||
endif
|
||||
|
||||
ifndef NO_LIBELF
|
||||
CFLAGS += -DHAVE_LIBELF_SUPPORT
|
||||
EXTLIBS += -lelf
|
||||
|
@ -360,10 +369,6 @@ ifndef NO_LIBELF
|
|||
else
|
||||
CFLAGS += -DHAVE_DWARF_SUPPORT $(LIBDW_CFLAGS)
|
||||
LDFLAGS += $(LIBDW_LDFLAGS)
|
||||
DWARFLIBS := -ldw
|
||||
ifeq ($(findstring -static,${LDFLAGS}),-static)
|
||||
DWARFLIBS += -lelf -lebl -lz -llzma -lbz2
|
||||
endif
|
||||
EXTLIBS += ${DWARFLIBS}
|
||||
$(call detected,CONFIG_DWARF)
|
||||
endif # PERF_HAVE_DWARF_REGS
|
||||
|
@ -500,6 +505,10 @@ ifndef NO_LOCAL_LIBUNWIND
|
|||
EXTLIBS += $(LIBUNWIND_LIBS)
|
||||
LDFLAGS += $(LIBUNWIND_LIBS)
|
||||
endif
|
||||
ifeq ($(findstring -static,${LDFLAGS}),-static)
|
||||
# gcc -static links libgcc_eh which contans piece of libunwind
|
||||
LIBUNWIND_LDFLAGS += -Wl,--allow-multiple-definition
|
||||
endif
|
||||
|
||||
ifndef NO_LIBUNWIND
|
||||
CFLAGS += -DHAVE_LIBUNWIND_SUPPORT
|
||||
|
|
|
@ -33,6 +33,11 @@ include ../scripts/utilities.mak
|
|||
#
|
||||
# Define EXTRA_CFLAGS=-m64 or EXTRA_CFLAGS=-m32 as appropriate for cross-builds.
|
||||
#
|
||||
# Define EXCLUDE_EXTLIBS=-lmylib to exclude libmylib from the auto-generated
|
||||
# EXTLIBS.
|
||||
#
|
||||
# Define EXTRA_PERFLIBS to pass extra libraries to PERFLIBS.
|
||||
#
|
||||
# Define NO_DWARF if you do not want debug-info analysis feature at all.
|
||||
#
|
||||
# Define WERROR=0 to disable treating any warnings as errors.
|
||||
|
@ -159,8 +164,8 @@ LN = ln -f
|
|||
MKDIR = mkdir
|
||||
FIND = find
|
||||
INSTALL = install
|
||||
FLEX = flex
|
||||
BISON = bison
|
||||
FLEX ?= flex
|
||||
BISON ?= bison
|
||||
STRIP = strip
|
||||
AWK = awk
|
||||
|
||||
|
@ -235,7 +240,7 @@ endif
|
|||
ifeq ($(FEATURES_DUMP),)
|
||||
FEATURE_DUMP_EXPORT := $(realpath $(OUTPUT)FEATURE-DUMP)
|
||||
else
|
||||
FEATURE_DUMP_EXPORT := $(FEATURES_DUMP)
|
||||
FEATURE_DUMP_EXPORT := $(realpath $(FEATURES_DUMP))
|
||||
endif
|
||||
|
||||
export prefix bindir sharedir sysconfdir DESTDIR
|
||||
|
@ -274,7 +279,13 @@ LIBTRACEEVENT = $(TE_PATH)libtraceevent.a
|
|||
export LIBTRACEEVENT
|
||||
|
||||
LIBTRACEEVENT_DYNAMIC_LIST = $(TE_PATH)libtraceevent-dynamic-list
|
||||
LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS = -Xlinker --dynamic-list=$(LIBTRACEEVENT_DYNAMIC_LIST)
|
||||
|
||||
#
|
||||
# The static build has no dynsym table, so this does not work for
|
||||
# static build. Looks like linker starts to scream about that now
|
||||
# (in Fedora 26) so we need to switch it off for static build.
|
||||
DYNAMIC_LIST_LDFLAGS = -Xlinker --dynamic-list=$(LIBTRACEEVENT_DYNAMIC_LIST)
|
||||
LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS = $(if $(findstring -static,$(LDFLAGS)),,$(DYNAMIC_LIST_LDFLAGS))
|
||||
|
||||
LIBAPI = $(API_PATH)libapi.a
|
||||
export LIBAPI
|
||||
|
@ -352,7 +363,8 @@ ifdef ASCIIDOC8
|
|||
export ASCIIDOC8
|
||||
endif
|
||||
|
||||
LIBS = -Wl,--whole-archive $(PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
|
||||
EXTLIBS := $(call filter-out,$(EXCLUDE_EXTLIBS),$(EXTLIBS))
|
||||
LIBS = -Wl,--whole-archive $(PERFLIBS) $(EXTRA_PERFLIBS) -Wl,--no-whole-archive -Wl,--start-group $(EXTLIBS) -Wl,--end-group
|
||||
|
||||
ifeq ($(USE_CLANG), 1)
|
||||
CLANGLIBS_LIST = AST Basic CodeGen Driver Frontend Lex Tooling Edit Sema Analysis Parse Serialization
|
||||
|
@ -375,6 +387,60 @@ export INSTALL SHELL_PATH
|
|||
|
||||
SHELL = $(SHELL_PATH)
|
||||
|
||||
beauty_outdir := $(OUTPUT)trace/beauty/generated
|
||||
beauty_ioctl_outdir := $(beauty_outdir)/ioctl
|
||||
drm_ioctl_array := $(beauty_ioctl_outdir)/drm_ioctl_array.c
|
||||
drm_hdr_dir := $(srctree)/tools/include/uapi/drm
|
||||
drm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/drm_ioctl.sh
|
||||
|
||||
# Create output directory if not already present
|
||||
_dummy := $(shell [ -d '$(beauty_ioctl_outdir)' ] || mkdir -p '$(beauty_ioctl_outdir)')
|
||||
|
||||
$(drm_ioctl_array): $(drm_hdr_dir)/drm.h $(drm_hdr_dir)/i915_drm.h $(drm_ioctl_tbl)
|
||||
$(Q)$(SHELL) '$(drm_ioctl_tbl)' $(drm_hdr_dir) > $@
|
||||
|
||||
pkey_alloc_access_rights_array := $(beauty_outdir)/pkey_alloc_access_rights_array.c
|
||||
asm_generic_hdr_dir := $(srctree)/tools/include/uapi/asm-generic/
|
||||
pkey_alloc_access_rights_tbl := $(srctree)/tools/perf/trace/beauty/pkey_alloc_access_rights.sh
|
||||
|
||||
$(pkey_alloc_access_rights_array): $(asm_generic_hdr_dir)/mman-common.h $(pkey_alloc_access_rights_tbl)
|
||||
$(Q)$(SHELL) '$(pkey_alloc_access_rights_tbl)' $(asm_generic_hdr_dir) > $@
|
||||
|
||||
sndrv_ctl_ioctl_array := $(beauty_ioctl_outdir)/sndrv_ctl_ioctl_array.c
|
||||
sndrv_ctl_hdr_dir := $(srctree)/tools/include/uapi/sound
|
||||
sndrv_ctl_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/sndrv_ctl_ioctl.sh
|
||||
|
||||
$(sndrv_ctl_ioctl_array): $(sndrv_ctl_hdr_dir)/asound.h $(sndrv_ctl_ioctl_tbl)
|
||||
$(Q)$(SHELL) '$(sndrv_ctl_ioctl_tbl)' $(sndrv_ctl_hdr_dir) > $@
|
||||
|
||||
sndrv_pcm_ioctl_array := $(beauty_ioctl_outdir)/sndrv_pcm_ioctl_array.c
|
||||
sndrv_pcm_hdr_dir := $(srctree)/tools/include/uapi/sound
|
||||
sndrv_pcm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/sndrv_pcm_ioctl.sh
|
||||
|
||||
$(sndrv_pcm_ioctl_array): $(sndrv_pcm_hdr_dir)/asound.h $(sndrv_pcm_ioctl_tbl)
|
||||
$(Q)$(SHELL) '$(sndrv_pcm_ioctl_tbl)' $(sndrv_pcm_hdr_dir) > $@
|
||||
|
||||
kvm_ioctl_array := $(beauty_ioctl_outdir)/kvm_ioctl_array.c
|
||||
kvm_hdr_dir := $(srctree)/tools/include/uapi/linux
|
||||
kvm_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/kvm_ioctl.sh
|
||||
|
||||
$(kvm_ioctl_array): $(kvm_hdr_dir)/kvm.h $(kvm_ioctl_tbl)
|
||||
$(Q)$(SHELL) '$(kvm_ioctl_tbl)' $(kvm_hdr_dir) > $@
|
||||
|
||||
vhost_virtio_ioctl_array := $(beauty_ioctl_outdir)/vhost_virtio_ioctl_array.c
|
||||
vhost_virtio_hdr_dir := $(srctree)/tools/include/uapi/linux
|
||||
vhost_virtio_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/vhost_virtio_ioctl.sh
|
||||
|
||||
$(vhost_virtio_ioctl_array): $(vhost_virtio_hdr_dir)/vhost.h $(vhost_virtio_ioctl_tbl)
|
||||
$(Q)$(SHELL) '$(vhost_virtio_ioctl_tbl)' $(vhost_virtio_hdr_dir) > $@
|
||||
|
||||
perf_ioctl_array := $(beauty_ioctl_outdir)/perf_ioctl_array.c
|
||||
perf_hdr_dir := $(srctree)/tools/include/uapi/linux
|
||||
perf_ioctl_tbl := $(srctree)/tools/perf/trace/beauty/perf_ioctl.sh
|
||||
|
||||
$(perf_ioctl_array): $(perf_hdr_dir)/perf_event.h $(perf_ioctl_tbl)
|
||||
$(Q)$(SHELL) '$(perf_ioctl_tbl)' $(perf_hdr_dir) > $@
|
||||
|
||||
all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
|
||||
|
||||
$(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
|
||||
|
@ -469,7 +535,13 @@ endif
|
|||
__build-dir = $(subst $(OUTPUT),,$(dir $@))
|
||||
build-dir = $(if $(__build-dir),$(__build-dir),.)
|
||||
|
||||
prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders
|
||||
prepare: $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)common-cmds.h archheaders $(drm_ioctl_array) \
|
||||
$(pkey_alloc_access_rights_array) \
|
||||
$(sndrv_pcm_ioctl_array) \
|
||||
$(sndrv_ctl_ioctl_array) \
|
||||
$(kvm_ioctl_array) \
|
||||
$(vhost_virtio_ioctl_array) \
|
||||
$(perf_ioctl_array)
|
||||
|
||||
$(OUTPUT)%.o: %.c prepare FORCE
|
||||
$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=$(build-dir) $@
|
||||
|
@ -512,7 +584,7 @@ $(LIBJVMTI_IN): FORCE
|
|||
$(Q)$(MAKE) -f $(srctree)/tools/build/Makefile.build dir=jvmti obj=jvmti
|
||||
|
||||
$(OUTPUT)$(LIBJVMTI): $(LIBJVMTI_IN)
|
||||
$(QUIET_LINK)$(CC) -shared -Wl,-soname -Wl,$(LIBJVMTI) -o $@ $< -lelf -lrt
|
||||
$(QUIET_LINK)$(CC) -shared -Wl,-soname -Wl,$(LIBJVMTI) -o $@ $<
|
||||
endif
|
||||
|
||||
$(patsubst perf-%,%.o,$(PROGRAMS)): $(wildcard */*.h)
|
||||
|
@ -703,7 +775,11 @@ install-tests: all install-gtk
|
|||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
|
||||
$(INSTALL) tests/attr.py '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests'; \
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
|
||||
$(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'
|
||||
$(INSTALL) tests/attr/* '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/attr'; \
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell'; \
|
||||
$(INSTALL) tests/shell/*.sh '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell'; \
|
||||
$(INSTALL) -d -m 755 '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/lib'; \
|
||||
$(INSTALL) tests/shell/lib/*.sh '$(DESTDIR_SQ)$(perfexec_instdir_SQ)/tests/shell/lib'
|
||||
|
||||
install-bin: install-tools install-tests install-traceevent-plugins
|
||||
|
||||
|
@ -734,7 +810,14 @@ clean:: $(LIBTRACEEVENT)-clean $(LIBAPI)-clean $(LIBBPF)-clean $(LIBSUBCMD)-clea
|
|||
$(call QUIET_CLEAN, core-gen) $(RM) *.spec *.pyc *.pyo */*.pyc */*.pyo $(OUTPUT)common-cmds.h TAGS tags cscope* $(OUTPUT)PERF-VERSION-FILE $(OUTPUT)FEATURE-DUMP $(OUTPUT)util/*-bison* $(OUTPUT)util/*-flex* \
|
||||
$(OUTPUT)util/intel-pt-decoder/inat-tables.c \
|
||||
$(OUTPUT)tests/llvm-src-{base,kbuild,prologue,relocation}.c \
|
||||
$(OUTPUT)pmu-events/pmu-events.c
|
||||
$(OUTPUT)pmu-events/pmu-events.c \
|
||||
$(OUTPUT)$(drm_ioctl_array) \
|
||||
$(OUTPUT)$(pkey_alloc_access_rights_array) \
|
||||
$(OUTPUT)$(sndrv_ctl_ioctl_array) \
|
||||
$(OUTPUT)$(sndrv_pcm_ioctl_array) \
|
||||
$(OUTPUT)$(kvm_ioctl_array) \
|
||||
$(OUTPUT)$(vhost_virtio_ioctl_array) \
|
||||
$(OUTPUT)$(perf_ioctl_array)
|
||||
$(QUIET_SUBDIR0)Documentation $(QUIET_SUBDIR1) clean
|
||||
$(python-clean)
|
||||
|
||||
|
|
|
@ -126,7 +126,7 @@ void arch__post_process_probe_trace_events(struct perf_probe_event *pev,
|
|||
struct rb_node *tmp;
|
||||
int i = 0;
|
||||
|
||||
map = get_target_map(pev->target, pev->uprobes);
|
||||
map = get_target_map(pev->target, pev->nsi, pev->uprobes);
|
||||
if (!map || map__load(map) < 0)
|
||||
return;
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
libperf-y += header.o
|
||||
libperf-y += sym-handling.o
|
||||
libperf-y += kvm-stat.o
|
||||
|
||||
libperf-$(CONFIG_DWARF) += dwarf-regs.o
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* Architecture specific ELF symbol handling and relocation mapping.
|
||||
*
|
||||
* Copyright 2017 IBM Corp.
|
||||
* Author(s): Thomas Richter <tmricht@linux.vnet.ibm.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License (version 2 only)
|
||||
* as published by the Free Software Foundation.
|
||||
*/
|
||||
|
||||
#include "symbol.h"
|
||||
|
||||
#ifdef HAVE_LIBELF_SUPPORT
|
||||
bool elf__needs_adjust_symbols(GElf_Ehdr ehdr)
|
||||
{
|
||||
if (ehdr.e_type == ET_EXEC)
|
||||
return false;
|
||||
return ehdr.e_type == ET_REL || ehdr.e_type == ET_DYN;
|
||||
}
|
||||
|
||||
void arch__adjust_sym_map_offset(GElf_Sym *sym,
|
||||
GElf_Shdr *shdr __maybe_unused,
|
||||
struct map *map)
|
||||
{
|
||||
if (map->type == MAP__FUNCTION)
|
||||
sym->st_value += map->start;
|
||||
}
|
||||
#endif
|
|
@ -20,7 +20,7 @@ _dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
|
|||
$(header): $(sys)/syscall_64.tbl $(systbl)
|
||||
@(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
|
||||
(diff -B arch/x86/entry/syscalls/syscall_64.tbl ../../arch/x86/entry/syscalls/syscall_64.tbl >/dev/null) \
|
||||
|| echo "Warning: x86_64's syscall_64.tbl differs from kernel" >&2 )) || true
|
||||
|| echo "Warning: Kernel ABI header at 'tools/arch/x86/entry/syscalls/syscall_64.tbl' differs from latest version at 'arch/x86/entry/syscalls/syscall_64.tbl'" >&2 )) || true
|
||||
$(Q)$(SHELL) '$(systbl)' $(sys)/syscall_64.tbl 'x86_64' > $@
|
||||
|
||||
clean::
|
||||
|
|
|
@ -76,3 +76,49 @@ static struct ins x86__instructions[] = {
|
|||
{ .name = "xbeginq", .ops = &jump_ops, },
|
||||
{ .name = "retq", .ops = &ret_ops, },
|
||||
};
|
||||
|
||||
static bool x86__ins_is_fused(struct arch *arch, const char *ins1,
|
||||
const char *ins2)
|
||||
{
|
||||
if (arch->family != 6 || arch->model < 0x1e || strstr(ins2, "jmp"))
|
||||
return false;
|
||||
|
||||
if (arch->model == 0x1e) {
|
||||
/* Nehalem */
|
||||
if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
|
||||
strstr(ins1, "test")) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
/* Newer platform */
|
||||
if ((strstr(ins1, "cmp") && !strstr(ins1, "xchg")) ||
|
||||
strstr(ins1, "test") ||
|
||||
strstr(ins1, "add") ||
|
||||
strstr(ins1, "sub") ||
|
||||
strstr(ins1, "and") ||
|
||||
strstr(ins1, "inc") ||
|
||||
strstr(ins1, "dec")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int x86__cpuid_parse(struct arch *arch, char *cpuid)
|
||||
{
|
||||
unsigned int family, model, stepping;
|
||||
int ret;
|
||||
|
||||
/*
|
||||
* cpuid = "GenuineIntel,family,model,stepping"
|
||||
*/
|
||||
ret = sscanf(cpuid, "%*[^,],%u,%u,%u", &family, &model, &stepping);
|
||||
if (ret == 3) {
|
||||
arch->family = family;
|
||||
arch->model = model;
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
#ifndef ARCH_TESTS_H
|
||||
#define ARCH_TESTS_H
|
||||
|
||||
#include <linux/compiler.h>
|
||||
struct test;
|
||||
|
||||
/* Tests */
|
||||
int test__rdpmc(int subtest);
|
||||
int test__perf_time_to_tsc(int subtest);
|
||||
int test__insn_x86(int subtest);
|
||||
int test__intel_cqm_count_nmi_context(int subtest);
|
||||
int test__rdpmc(struct test *test __maybe_unused, int subtest);
|
||||
int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest);
|
||||
int test__insn_x86(struct test *test __maybe_unused, int subtest);
|
||||
int test__intel_cqm_count_nmi_context(struct test *test __maybe_unused, int subtest);
|
||||
|
||||
#ifdef HAVE_DWARF_UNWIND_SUPPORT
|
||||
struct thread;
|
||||
|
|
|
@ -171,7 +171,7 @@ static int test_data_set(struct test_data *dat_set, int x86_64)
|
|||
* verbose (-v) option to see all the instructions and whether or not they
|
||||
* decoded successfuly.
|
||||
*/
|
||||
int test__insn_x86(int subtest __maybe_unused)
|
||||
int test__insn_x86(struct test *test __maybe_unused, int subtest __maybe_unused)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
|
|
|
@ -36,7 +36,7 @@ static pid_t spawn(void)
|
|||
* the last read counter value to avoid triggering a WARN_ON_ONCE() in
|
||||
* smp_call_function_many() caused by sending IPIs from NMI context.
|
||||
*/
|
||||
int test__intel_cqm_count_nmi_context(int subtest __maybe_unused)
|
||||
int test__intel_cqm_count_nmi_context(struct test *test __maybe_unused, int subtest __maybe_unused)
|
||||
{
|
||||
struct perf_evlist *evlist = NULL;
|
||||
struct perf_evsel *evsel = NULL;
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
* %0 is returned, otherwise %-1 is returned. If TSC conversion is not
|
||||
* supported then then the test passes but " (not supported)" is printed.
|
||||
*/
|
||||
int test__perf_time_to_tsc(int subtest __maybe_unused)
|
||||
int test__perf_time_to_tsc(struct test *test __maybe_unused, int subtest __maybe_unused)
|
||||
{
|
||||
struct record_opts opts = {
|
||||
.mmap_pages = UINT_MAX,
|
||||
|
|
|
@ -154,7 +154,7 @@ static int __test__rdpmc(void)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int test__rdpmc(int subtest __maybe_unused)
|
||||
int test__rdpmc(struct test *test __maybe_unused, int subtest __maybe_unused)
|
||||
{
|
||||
int status = 0;
|
||||
int wret = 0;
|
||||
|
|
|
@ -701,6 +701,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
|
|||
perf_evsel__set_sample_bit(switch_evsel, TID);
|
||||
perf_evsel__set_sample_bit(switch_evsel, TIME);
|
||||
perf_evsel__set_sample_bit(switch_evsel, CPU);
|
||||
perf_evsel__reset_sample_bit(switch_evsel, BRANCH_STACK);
|
||||
|
||||
opts->record_switch_events = false;
|
||||
ptr->have_sched_switch = 3;
|
||||
|
@ -752,6 +753,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
|
|||
tracking_evsel->attr.freq = 0;
|
||||
tracking_evsel->attr.sample_period = 1;
|
||||
|
||||
tracking_evsel->no_aux_samples = true;
|
||||
if (need_immediate)
|
||||
tracking_evsel->immediate = true;
|
||||
|
||||
|
@ -761,6 +763,7 @@ static int intel_pt_recording_options(struct auxtrace_record *itr,
|
|||
/* And the CPU for switch events */
|
||||
perf_evsel__set_sample_bit(tracking_evsel, CPU);
|
||||
}
|
||||
perf_evsel__reset_sample_bit(tracking_evsel, BRANCH_STACK);
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -177,14 +177,11 @@ static int perf_evsel__add_sample(struct perf_evsel *evsel,
|
|||
*/
|
||||
process_branch_stack(sample->branch_stack, al, sample);
|
||||
|
||||
sample->period = 1;
|
||||
sample->weight = 1;
|
||||
|
||||
he = hists__add_entry(hists, al, NULL, NULL, NULL, sample, true);
|
||||
if (he == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
ret = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
|
||||
ret = hist_entry__inc_addr_samples(he, sample, evsel->idx, al->addr);
|
||||
hists__inc_nr_samples(hists, true);
|
||||
return ret;
|
||||
}
|
||||
|
@ -397,6 +394,8 @@ int cmd_annotate(int argc, const char **argv)
|
|||
.namespaces = perf_event__process_namespaces,
|
||||
.attr = perf_event__process_attr,
|
||||
.build_id = perf_event__process_build_id,
|
||||
.tracing_data = perf_event__process_tracing_data,
|
||||
.feature = perf_event__process_feature,
|
||||
.ordered_events = true,
|
||||
.ordering_requires_timestamps = true,
|
||||
},
|
||||
|
@ -404,7 +403,7 @@ int cmd_annotate(int argc, const char **argv)
|
|||
struct perf_data_file file = {
|
||||
.mode = PERF_DATA_MODE_READ,
|
||||
};
|
||||
const struct option options[] = {
|
||||
struct option options[] = {
|
||||
OPT_STRING('i', "input", &input_name, "file",
|
||||
"input file name"),
|
||||
OPT_STRING('d', "dsos", &symbol_conf.dso_list_str, "dso[,dso...]",
|
||||
|
@ -446,13 +445,20 @@ int cmd_annotate(int argc, const char **argv)
|
|||
"Show event group information together"),
|
||||
OPT_BOOLEAN(0, "show-total-period", &symbol_conf.show_total_period,
|
||||
"Show a column with the sum of periods"),
|
||||
OPT_BOOLEAN('n', "show-nr-samples", &symbol_conf.show_nr_samples,
|
||||
"Show a column with the number of samples"),
|
||||
OPT_CALLBACK_DEFAULT(0, "stdio-color", NULL, "mode",
|
||||
"'always' (default), 'never' or 'auto' only applicable to --stdio mode",
|
||||
stdio__config_color, "always"),
|
||||
OPT_END()
|
||||
};
|
||||
int ret = hists__init();
|
||||
int ret;
|
||||
|
||||
set_option_flag(options, 0, "show-total-period", PARSE_OPT_EXCLUSIVE);
|
||||
set_option_flag(options, 0, "show-nr-samples", PARSE_OPT_EXCLUSIVE);
|
||||
|
||||
|
||||
ret = hists__init();
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -468,6 +474,11 @@ int cmd_annotate(int argc, const char **argv)
|
|||
annotate.sym_hist_filter = argv[0];
|
||||
}
|
||||
|
||||
if (symbol_conf.show_nr_samples && annotate.use_gtk) {
|
||||
pr_err("--show-nr-samples is not available in --gtk mode at this time\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (quiet)
|
||||
perf_quiet_option();
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include <unistd.h>
|
||||
#include "builtin.h"
|
||||
#include "perf.h"
|
||||
#include "namespaces.h"
|
||||
#include "util/cache.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/header.h"
|
||||
|
@ -165,33 +166,41 @@ static int build_id_cache__add_kcore(const char *filename, bool force)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int build_id_cache__add_file(const char *filename)
|
||||
static int build_id_cache__add_file(const char *filename, struct nsinfo *nsi)
|
||||
{
|
||||
char sbuild_id[SBUILD_ID_SIZE];
|
||||
u8 build_id[BUILD_ID_SIZE];
|
||||
int err;
|
||||
struct nscookie nsc;
|
||||
|
||||
if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
|
||||
nsinfo__mountns_enter(nsi, &nsc);
|
||||
err = filename__read_build_id(filename, &build_id, sizeof(build_id));
|
||||
nsinfo__mountns_exit(&nsc);
|
||||
if (err < 0) {
|
||||
pr_debug("Couldn't read a build-id in %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
||||
build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
|
||||
err = build_id_cache__add_s(sbuild_id, filename,
|
||||
err = build_id_cache__add_s(sbuild_id, filename, nsi,
|
||||
false, false);
|
||||
pr_debug("Adding %s %s: %s\n", sbuild_id, filename,
|
||||
err ? "FAIL" : "Ok");
|
||||
return err;
|
||||
}
|
||||
|
||||
static int build_id_cache__remove_file(const char *filename)
|
||||
static int build_id_cache__remove_file(const char *filename, struct nsinfo *nsi)
|
||||
{
|
||||
u8 build_id[BUILD_ID_SIZE];
|
||||
char sbuild_id[SBUILD_ID_SIZE];
|
||||
struct nscookie nsc;
|
||||
|
||||
int err;
|
||||
|
||||
if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
|
||||
nsinfo__mountns_enter(nsi, &nsc);
|
||||
err = filename__read_build_id(filename, &build_id, sizeof(build_id));
|
||||
nsinfo__mountns_exit(&nsc);
|
||||
if (err < 0) {
|
||||
pr_debug("Couldn't read a build-id in %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
|
@ -204,13 +213,13 @@ static int build_id_cache__remove_file(const char *filename)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int build_id_cache__purge_path(const char *pathname)
|
||||
static int build_id_cache__purge_path(const char *pathname, struct nsinfo *nsi)
|
||||
{
|
||||
struct strlist *list;
|
||||
struct str_node *pos;
|
||||
int err;
|
||||
|
||||
err = build_id_cache__list_build_ids(pathname, &list);
|
||||
err = build_id_cache__list_build_ids(pathname, nsi, &list);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
|
@ -234,7 +243,7 @@ static bool dso__missing_buildid_cache(struct dso *dso, int parm __maybe_unused)
|
|||
char filename[PATH_MAX];
|
||||
u8 build_id[BUILD_ID_SIZE];
|
||||
|
||||
if (dso__build_id_filename(dso, filename, sizeof(filename)) &&
|
||||
if (dso__build_id_filename(dso, filename, sizeof(filename), false) &&
|
||||
filename__read_build_id(filename, build_id,
|
||||
sizeof(build_id)) != sizeof(build_id)) {
|
||||
if (errno == ENOENT)
|
||||
|
@ -256,24 +265,30 @@ static int build_id_cache__fprintf_missing(struct perf_session *session, FILE *f
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int build_id_cache__update_file(const char *filename)
|
||||
static int build_id_cache__update_file(const char *filename, struct nsinfo *nsi)
|
||||
{
|
||||
u8 build_id[BUILD_ID_SIZE];
|
||||
char sbuild_id[SBUILD_ID_SIZE];
|
||||
struct nscookie nsc;
|
||||
|
||||
int err = 0;
|
||||
int err;
|
||||
|
||||
if (filename__read_build_id(filename, &build_id, sizeof(build_id)) < 0) {
|
||||
nsinfo__mountns_enter(nsi, &nsc);
|
||||
err = filename__read_build_id(filename, &build_id, sizeof(build_id));
|
||||
nsinfo__mountns_exit(&nsc);
|
||||
if (err < 0) {
|
||||
pr_debug("Couldn't read a build-id in %s\n", filename);
|
||||
return -1;
|
||||
}
|
||||
err = 0;
|
||||
|
||||
build_id__sprintf(build_id, sizeof(build_id), sbuild_id);
|
||||
if (build_id_cache__cached(sbuild_id))
|
||||
err = build_id_cache__remove_s(sbuild_id);
|
||||
|
||||
if (!err)
|
||||
err = build_id_cache__add_s(sbuild_id, filename, false, false);
|
||||
err = build_id_cache__add_s(sbuild_id, filename, nsi, false,
|
||||
false);
|
||||
|
||||
pr_debug("Updating %s %s: %s\n", sbuild_id, filename,
|
||||
err ? "FAIL" : "Ok");
|
||||
|
@ -286,6 +301,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
struct strlist *list;
|
||||
struct str_node *pos;
|
||||
int ret = 0;
|
||||
int ns_id = -1;
|
||||
bool force = false;
|
||||
char const *add_name_list_str = NULL,
|
||||
*remove_name_list_str = NULL,
|
||||
|
@ -299,6 +315,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
.mode = PERF_DATA_MODE_READ,
|
||||
};
|
||||
struct perf_session *session = NULL;
|
||||
struct nsinfo *nsi = NULL;
|
||||
|
||||
const struct option buildid_cache_options[] = {
|
||||
OPT_STRING('a', "add", &add_name_list_str,
|
||||
|
@ -315,6 +332,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
OPT_STRING('u', "update", &update_name_list_str, "file list",
|
||||
"file(s) to update"),
|
||||
OPT_INCR('v', "verbose", &verbose, "be more verbose"),
|
||||
OPT_INTEGER(0, "target-ns", &ns_id, "target pid for namespace context"),
|
||||
OPT_END()
|
||||
};
|
||||
const char * const buildid_cache_usage[] = {
|
||||
|
@ -330,6 +348,9 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
!missing_filename && !update_name_list_str))
|
||||
usage_with_options(buildid_cache_usage, buildid_cache_options);
|
||||
|
||||
if (ns_id > 0)
|
||||
nsi = nsinfo__new(ns_id);
|
||||
|
||||
if (missing_filename) {
|
||||
file.path = missing_filename;
|
||||
file.force = force;
|
||||
|
@ -348,7 +369,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
list = strlist__new(add_name_list_str, NULL);
|
||||
if (list) {
|
||||
strlist__for_each_entry(pos, list)
|
||||
if (build_id_cache__add_file(pos->s)) {
|
||||
if (build_id_cache__add_file(pos->s, nsi)) {
|
||||
if (errno == EEXIST) {
|
||||
pr_debug("%s already in the cache\n",
|
||||
pos->s);
|
||||
|
@ -366,7 +387,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
list = strlist__new(remove_name_list_str, NULL);
|
||||
if (list) {
|
||||
strlist__for_each_entry(pos, list)
|
||||
if (build_id_cache__remove_file(pos->s)) {
|
||||
if (build_id_cache__remove_file(pos->s, nsi)) {
|
||||
if (errno == ENOENT) {
|
||||
pr_debug("%s wasn't in the cache\n",
|
||||
pos->s);
|
||||
|
@ -384,7 +405,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
list = strlist__new(purge_name_list_str, NULL);
|
||||
if (list) {
|
||||
strlist__for_each_entry(pos, list)
|
||||
if (build_id_cache__purge_path(pos->s)) {
|
||||
if (build_id_cache__purge_path(pos->s, nsi)) {
|
||||
if (errno == ENOENT) {
|
||||
pr_debug("%s wasn't in the cache\n",
|
||||
pos->s);
|
||||
|
@ -405,7 +426,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
list = strlist__new(update_name_list_str, NULL);
|
||||
if (list) {
|
||||
strlist__for_each_entry(pos, list)
|
||||
if (build_id_cache__update_file(pos->s)) {
|
||||
if (build_id_cache__update_file(pos->s, nsi)) {
|
||||
if (errno == ENOENT) {
|
||||
pr_debug("%s wasn't in the cache\n",
|
||||
pos->s);
|
||||
|
@ -424,6 +445,7 @@ int cmd_buildid_cache(int argc, const char **argv)
|
|||
|
||||
out:
|
||||
perf_session__delete(session);
|
||||
nsinfo__zput(nsi);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#include "util/util.h"
|
||||
#include "util/debug.h"
|
||||
#include "util/config.h"
|
||||
#include <linux/string.h>
|
||||
|
||||
static bool use_system_config, use_user_config;
|
||||
|
||||
|
@ -79,7 +80,7 @@ static int show_spec_config(struct perf_config_set *set, const char *var)
|
|||
return -1;
|
||||
|
||||
perf_config_items__for_each_entry(&set->sections, section) {
|
||||
if (prefixcmp(var, section->name) != 0)
|
||||
if (!strstarts(var, section->name))
|
||||
continue;
|
||||
|
||||
perf_config_items__for_each_entry(§ion->items, item) {
|
||||
|
|
|
@ -69,7 +69,7 @@ static int cmd_data_convert(int argc, const char **argv)
|
|||
};
|
||||
|
||||
#ifndef HAVE_LIBBABELTRACE_SUPPORT
|
||||
pr_err("No conversion support compiled in.\n");
|
||||
pr_err("No conversion support compiled in. perf should be compiled with environment variables LIBBABELTRACE=1 and LIBBABELTRACE_DIR=/path/to/libbabeltrace/\n");
|
||||
return -1;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -381,7 +381,7 @@ static int perf_ftrace_config(const char *var, const char *value, void *cb)
|
|||
{
|
||||
struct perf_ftrace *ftrace = cb;
|
||||
|
||||
if (prefixcmp(var, "ftrace."))
|
||||
if (!strstarts(var, "ftrace."))
|
||||
return 0;
|
||||
|
||||
if (strcmp(var, "ftrace.tracer"))
|
||||
|
|
|
@ -90,7 +90,7 @@ static int check_emacsclient_version(void)
|
|||
*/
|
||||
finish_command(&ec_process);
|
||||
|
||||
if (prefixcmp(buffer.buf, "emacsclient")) {
|
||||
if (!strstarts(buffer.buf, "emacsclient")) {
|
||||
fprintf(stderr, "Failed to parse emacsclient version.\n");
|
||||
goto out;
|
||||
}
|
||||
|
@ -283,7 +283,7 @@ static int perf_help_config(const char *var, const char *value, void *cb)
|
|||
add_man_viewer(value);
|
||||
return 0;
|
||||
}
|
||||
if (!prefixcmp(var, "man."))
|
||||
if (!strstarts(var, "man."))
|
||||
return add_man_viewer_info(var, value);
|
||||
|
||||
return 0;
|
||||
|
@ -313,7 +313,7 @@ static const char *cmd_to_page(const char *perf_cmd)
|
|||
|
||||
if (!perf_cmd)
|
||||
return "perf";
|
||||
else if (!prefixcmp(perf_cmd, "perf"))
|
||||
else if (!strstarts(perf_cmd, "perf"))
|
||||
return perf_cmd;
|
||||
|
||||
return asprintf(&s, "perf-%s", perf_cmd) < 0 ? NULL : s;
|
||||
|
|
|
@ -770,6 +770,7 @@ int cmd_inject(int argc, const char **argv)
|
|||
.finished_round = perf_event__repipe_oe_synth,
|
||||
.build_id = perf_event__repipe_op2_synth,
|
||||
.id_index = perf_event__repipe_op2_synth,
|
||||
.feature = perf_event__repipe_op2_synth,
|
||||
},
|
||||
.input_name = "-",
|
||||
.samples = LIST_HEAD_INIT(inject.samples),
|
||||
|
|
|
@ -58,6 +58,7 @@ static struct {
|
|||
struct line_range line_range;
|
||||
char *target;
|
||||
struct strfilter *filter;
|
||||
struct nsinfo *nsi;
|
||||
} params;
|
||||
|
||||
/* Parse an event definition. Note that any error must die. */
|
||||
|
@ -80,6 +81,9 @@ static int parse_probe_event(const char *str)
|
|||
params.target_used = true;
|
||||
}
|
||||
|
||||
if (params.nsi)
|
||||
pev->nsi = nsinfo__get(params.nsi);
|
||||
|
||||
/* Parse a perf-probe command into event */
|
||||
ret = parse_perf_probe_command(str, pev);
|
||||
pr_debug("%d arguments\n", pev->nargs);
|
||||
|
@ -189,7 +193,7 @@ static int opt_set_target(const struct option *opt, const char *str,
|
|||
|
||||
/* Expand given path to absolute path, except for modulename */
|
||||
if (params.uprobes || strchr(str, '/')) {
|
||||
tmp = realpath(str, NULL);
|
||||
tmp = nsinfo__realpath(str, params.nsi);
|
||||
if (!tmp) {
|
||||
pr_warning("Failed to get the absolute path of %s: %m\n", str);
|
||||
return ret;
|
||||
|
@ -208,6 +212,34 @@ static int opt_set_target(const struct option *opt, const char *str,
|
|||
return ret;
|
||||
}
|
||||
|
||||
static int opt_set_target_ns(const struct option *opt __maybe_unused,
|
||||
const char *str, int unset __maybe_unused)
|
||||
{
|
||||
int ret = -ENOENT;
|
||||
pid_t ns_pid;
|
||||
struct nsinfo *nsip;
|
||||
|
||||
if (str) {
|
||||
errno = 0;
|
||||
ns_pid = (pid_t)strtol(str, NULL, 10);
|
||||
if (errno != 0) {
|
||||
ret = -errno;
|
||||
pr_warning("Failed to parse %s as a pid: %s\n", str,
|
||||
strerror(errno));
|
||||
return ret;
|
||||
}
|
||||
nsip = nsinfo__new(ns_pid);
|
||||
if (nsip && nsip->need_setns)
|
||||
params.nsi = nsinfo__get(nsip);
|
||||
nsinfo__put(nsip);
|
||||
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* Command option callbacks */
|
||||
|
||||
#ifdef HAVE_DWARF_SUPPORT
|
||||
|
@ -299,6 +331,7 @@ static void cleanup_params(void)
|
|||
line_range__clear(¶ms.line_range);
|
||||
free(params.target);
|
||||
strfilter__delete(params.filter);
|
||||
nsinfo__put(params.nsi);
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
}
|
||||
|
||||
|
@ -383,7 +416,7 @@ static int del_perf_probe_caches(struct strfilter *filter)
|
|||
}
|
||||
|
||||
strlist__for_each_entry(nd, bidlist) {
|
||||
cache = probe_cache__new(nd->s);
|
||||
cache = probe_cache__new(nd->s, NULL);
|
||||
if (!cache)
|
||||
continue;
|
||||
if (probe_cache__filter_purge(cache, filter) < 0 ||
|
||||
|
@ -554,6 +587,8 @@ __cmd_probe(int argc, const char **argv)
|
|||
OPT_BOOLEAN(0, "cache", &probe_conf.cache, "Manipulate probe cache"),
|
||||
OPT_STRING(0, "symfs", &symbol_conf.symfs, "directory",
|
||||
"Look for files with symbols relative to this directory"),
|
||||
OPT_CALLBACK(0, "target-ns", NULL, "pid",
|
||||
"target pid for namespace contexts", opt_set_target_ns),
|
||||
OPT_END()
|
||||
};
|
||||
int ret;
|
||||
|
@ -634,15 +669,15 @@ __cmd_probe(int argc, const char **argv)
|
|||
pr_err_with_code(" Error: Failed to show event list.", ret);
|
||||
return ret;
|
||||
case 'F':
|
||||
ret = show_available_funcs(params.target, params.filter,
|
||||
params.uprobes);
|
||||
ret = show_available_funcs(params.target, params.nsi,
|
||||
params.filter, params.uprobes);
|
||||
if (ret < 0)
|
||||
pr_err_with_code(" Error: Failed to show functions.", ret);
|
||||
return ret;
|
||||
#ifdef HAVE_DWARF_SUPPORT
|
||||
case 'L':
|
||||
ret = show_line_range(¶ms.line_range, params.target,
|
||||
params.uprobes);
|
||||
params.nsi, params.uprobes);
|
||||
if (ret < 0)
|
||||
pr_err_with_code(" Error: Failed to show lines.", ret);
|
||||
return ret;
|
||||
|
|
|
@ -799,6 +799,13 @@ static int record__synthesize(struct record *rec, bool tail)
|
|||
return 0;
|
||||
|
||||
if (file->is_pipe) {
|
||||
err = perf_event__synthesize_features(
|
||||
tool, session, rec->evlist, process_synthesized_event);
|
||||
if (err < 0) {
|
||||
pr_err("Couldn't synthesize features.\n");
|
||||
return err;
|
||||
}
|
||||
|
||||
err = perf_event__synthesize_attrs(tool, session,
|
||||
process_synthesized_event);
|
||||
if (err < 0) {
|
||||
|
@ -1821,7 +1828,7 @@ int cmd_record(int argc, const char **argv)
|
|||
record.opts.tail_synthesize = true;
|
||||
|
||||
if (rec->evlist->nr_entries == 0 &&
|
||||
perf_evlist__add_default(rec->evlist) < 0) {
|
||||
__perf_evlist__add_default(rec->evlist, !record.opts.no_samples) < 0) {
|
||||
pr_err("Not enough memory for event selector list\n");
|
||||
goto out;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "util/time-utils.h"
|
||||
#include "util/auxtrace.h"
|
||||
#include "util/units.h"
|
||||
#include "util/branch.h"
|
||||
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
|
@ -73,6 +74,7 @@ struct report {
|
|||
u64 queue_size;
|
||||
int socket_filter;
|
||||
DECLARE_BITMAP(cpu_bitmap, MAX_NR_CPUS);
|
||||
struct branch_type_stat brtype_stat;
|
||||
};
|
||||
|
||||
static int report__config(const char *var, const char *value, void *cb)
|
||||
|
@ -113,43 +115,60 @@ static int hist_iter__report_callback(struct hist_entry_iter *iter,
|
|||
struct report *rep = arg;
|
||||
struct hist_entry *he = iter->he;
|
||||
struct perf_evsel *evsel = iter->evsel;
|
||||
struct perf_sample *sample = iter->sample;
|
||||
struct mem_info *mi;
|
||||
struct branch_info *bi;
|
||||
|
||||
if (!ui__has_annotation())
|
||||
return 0;
|
||||
|
||||
hist__account_cycles(iter->sample->branch_stack, al, iter->sample,
|
||||
hist__account_cycles(sample->branch_stack, al, sample,
|
||||
rep->nonany_branch_mode);
|
||||
|
||||
if (sort__mode == SORT_MODE__BRANCH) {
|
||||
bi = he->branch_info;
|
||||
err = addr_map_symbol__inc_samples(&bi->from, evsel->idx);
|
||||
err = addr_map_symbol__inc_samples(&bi->from, sample, evsel->idx);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = addr_map_symbol__inc_samples(&bi->to, evsel->idx);
|
||||
err = addr_map_symbol__inc_samples(&bi->to, sample, evsel->idx);
|
||||
|
||||
} else if (rep->mem_mode) {
|
||||
mi = he->mem_info;
|
||||
err = addr_map_symbol__inc_samples(&mi->daddr, evsel->idx);
|
||||
err = addr_map_symbol__inc_samples(&mi->daddr, sample, evsel->idx);
|
||||
if (err)
|
||||
goto out;
|
||||
|
||||
err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
|
||||
err = hist_entry__inc_addr_samples(he, sample, evsel->idx, al->addr);
|
||||
|
||||
} else if (symbol_conf.cumulate_callchain) {
|
||||
if (single)
|
||||
err = hist_entry__inc_addr_samples(he, evsel->idx,
|
||||
err = hist_entry__inc_addr_samples(he, sample, evsel->idx,
|
||||
al->addr);
|
||||
} else {
|
||||
err = hist_entry__inc_addr_samples(he, evsel->idx, al->addr);
|
||||
err = hist_entry__inc_addr_samples(he, sample, evsel->idx, al->addr);
|
||||
}
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
static int hist_iter__branch_callback(struct hist_entry_iter *iter,
|
||||
struct addr_location *al __maybe_unused,
|
||||
bool single __maybe_unused,
|
||||
void *arg)
|
||||
{
|
||||
struct hist_entry *he = iter->he;
|
||||
struct report *rep = arg;
|
||||
struct branch_info *bi;
|
||||
|
||||
bi = he->branch_info;
|
||||
branch_type_count(&rep->brtype_stat, &bi->flags,
|
||||
bi->from.addr, bi->to.addr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int process_sample_event(struct perf_tool *tool,
|
||||
union perf_event *event,
|
||||
struct perf_sample *sample,
|
||||
|
@ -188,6 +207,8 @@ static int process_sample_event(struct perf_tool *tool,
|
|||
*/
|
||||
if (!sample->branch_stack)
|
||||
goto out_put;
|
||||
|
||||
iter.add_entry_cb = hist_iter__branch_callback;
|
||||
iter.ops = &hist_iter_branch;
|
||||
} else if (rep->mem_mode) {
|
||||
iter.ops = &hist_iter_mem;
|
||||
|
@ -220,7 +241,7 @@ static int process_read_event(struct perf_tool *tool,
|
|||
const char *name = evsel ? perf_evsel__name(evsel) : "unknown";
|
||||
int err = perf_read_values_add_value(&rep->show_threads_values,
|
||||
event->read.pid, event->read.tid,
|
||||
event->read.id,
|
||||
evsel->idx,
|
||||
name,
|
||||
event->read.value);
|
||||
|
||||
|
@ -228,10 +249,6 @@ static int process_read_event(struct perf_tool *tool,
|
|||
return err;
|
||||
}
|
||||
|
||||
dump_printf(": %d %d %s %" PRIu64 "\n", event->read.pid, event->read.tid,
|
||||
evsel ? perf_evsel__name(evsel) : "FAIL",
|
||||
event->read.value);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -258,10 +275,11 @@ static int report__setup_sample_type(struct report *rep)
|
|||
"'perf record' without -g?\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
if (symbol_conf.use_callchain) {
|
||||
ui__error("Selected -g or --branch-history but no "
|
||||
"callchain data. Did\n"
|
||||
"you call 'perf record' without -g?\n");
|
||||
if (symbol_conf.use_callchain &&
|
||||
!symbol_conf.show_branchflag_count) {
|
||||
ui__error("Selected -g or --branch-history.\n"
|
||||
"But no callchain or branch data.\n"
|
||||
"Did you call 'perf record' without -g or -b?\n");
|
||||
return -1;
|
||||
}
|
||||
} else if (!callchain_param.enabled &&
|
||||
|
@ -396,7 +414,8 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
|
|||
|
||||
hists__fprintf_nr_sample_events(hists, rep, evname, stdout);
|
||||
hists__fprintf(hists, !quiet, 0, 0, rep->min_percent, stdout,
|
||||
symbol_conf.use_callchain);
|
||||
symbol_conf.use_callchain ||
|
||||
symbol_conf.show_branchflag_count);
|
||||
fprintf(stdout, "\n\n");
|
||||
}
|
||||
|
||||
|
@ -410,6 +429,9 @@ static int perf_evlist__tty_browse_hists(struct perf_evlist *evlist,
|
|||
perf_read_values_destroy(&rep->show_threads_values);
|
||||
}
|
||||
|
||||
if (sort__mode == SORT_MODE__BRANCH)
|
||||
branch_type_stat_display(stdout, &rep->brtype_stat);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -718,6 +740,7 @@ int cmd_report(int argc, const char **argv)
|
|||
.id_index = perf_event__process_id_index,
|
||||
.auxtrace_info = perf_event__process_auxtrace_info,
|
||||
.auxtrace = perf_event__process_auxtrace,
|
||||
.feature = perf_event__process_feature,
|
||||
.ordered_events = true,
|
||||
.ordering_requires_timestamps = true,
|
||||
},
|
||||
|
@ -943,6 +966,8 @@ int cmd_report(int argc, const char **argv)
|
|||
if (has_br_stack && branch_call_mode)
|
||||
symbol_conf.show_branchflag_count = true;
|
||||
|
||||
memset(&report.brtype_stat, 0, sizeof(struct branch_type_stat));
|
||||
|
||||
/*
|
||||
* Branch mode is a tristate:
|
||||
* -1 means default, so decide based on the file having branch data.
|
||||
|
@ -988,6 +1013,10 @@ int cmd_report(int argc, const char **argv)
|
|||
/* Force tty output for header output and per-thread stat. */
|
||||
if (report.header || report.header_only || report.show_threads)
|
||||
use_browser = 0;
|
||||
if (report.header || report.header_only)
|
||||
report.tool.show_feat_hdr = SHOW_FEAT_HEADER;
|
||||
if (report.show_full_info)
|
||||
report.tool.show_feat_hdr = SHOW_FEAT_HEADER_FULL_INFO;
|
||||
|
||||
if (strcmp(input_name, "-") != 0)
|
||||
setup_browser(true);
|
||||
|
|
|
@ -2199,16 +2199,11 @@ static struct script_desc *script_desc__findnew(const char *name)
|
|||
|
||||
s = script_desc__new(name);
|
||||
if (!s)
|
||||
goto out_delete_desc;
|
||||
return NULL;
|
||||
|
||||
script_desc__add(s);
|
||||
|
||||
return s;
|
||||
|
||||
out_delete_desc:
|
||||
script_desc__delete(s);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *ends_with(const char *str, const char *suffix)
|
||||
|
@ -2682,6 +2677,7 @@ int cmd_script(int argc, const char **argv)
|
|||
.attr = process_attr,
|
||||
.event_update = perf_event__process_event_update,
|
||||
.tracing_data = perf_event__process_tracing_data,
|
||||
.feature = perf_event__process_feature,
|
||||
.build_id = perf_event__process_build_id,
|
||||
.id_index = perf_event__process_id_index,
|
||||
.auxtrace_info = perf_event__process_auxtrace_info,
|
||||
|
@ -2972,10 +2968,13 @@ int cmd_script(int argc, const char **argv)
|
|||
return -1;
|
||||
|
||||
if (header || header_only) {
|
||||
script.tool.show_feat_hdr = SHOW_FEAT_HEADER;
|
||||
perf_session__fprintf_info(session, stdout, show_full_info);
|
||||
if (header_only)
|
||||
goto out_delete;
|
||||
}
|
||||
if (show_full_info)
|
||||
script.tool.show_feat_hdr = SHOW_FEAT_HEADER_FULL_INFO;
|
||||
|
||||
if (symbol__init(&session->header.env) < 0)
|
||||
goto out_delete;
|
||||
|
|
|
@ -213,10 +213,20 @@ static void perf_stat__reset_stats(void)
|
|||
static int create_perf_stat_counter(struct perf_evsel *evsel)
|
||||
{
|
||||
struct perf_event_attr *attr = &evsel->attr;
|
||||
struct perf_evsel *leader = evsel->leader;
|
||||
|
||||
if (stat_config.scale)
|
||||
if (stat_config.scale) {
|
||||
attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
|
||||
PERF_FORMAT_TOTAL_TIME_RUNNING;
|
||||
}
|
||||
|
||||
/*
|
||||
* The event is part of non trivial group, let's enable
|
||||
* the group read (for leader) and ID retrieval for all
|
||||
* members.
|
||||
*/
|
||||
if (leader->nr_members > 1)
|
||||
attr->read_format |= PERF_FORMAT_ID|PERF_FORMAT_GROUP;
|
||||
|
||||
attr->inherit = !no_inherit;
|
||||
|
||||
|
@ -333,13 +343,21 @@ static int read_counter(struct perf_evsel *counter)
|
|||
struct perf_counts_values *count;
|
||||
|
||||
count = perf_counts(counter->counts, cpu, thread);
|
||||
if (perf_evsel__read(counter, cpu, thread, count)) {
|
||||
|
||||
/*
|
||||
* The leader's group read loads data into its group members
|
||||
* (via perf_evsel__read_counter) and sets threir count->loaded.
|
||||
*/
|
||||
if (!count->loaded &&
|
||||
perf_evsel__read_counter(counter, cpu, thread)) {
|
||||
counter->counts->scaled = -1;
|
||||
perf_counts(counter->counts, cpu, thread)->ena = 0;
|
||||
perf_counts(counter->counts, cpu, thread)->run = 0;
|
||||
return -1;
|
||||
}
|
||||
|
||||
count->loaded = false;
|
||||
|
||||
if (STAT_RECORD) {
|
||||
if (perf_evsel__write_stat_event(counter, cpu, thread, count)) {
|
||||
pr_err("failed to write stat event\n");
|
||||
|
@ -559,6 +577,11 @@ static int store_counter_ids(struct perf_evsel *counter)
|
|||
return __store_counter_ids(counter, cpus, threads);
|
||||
}
|
||||
|
||||
static bool perf_evsel__should_store_id(struct perf_evsel *counter)
|
||||
{
|
||||
return STAT_RECORD || counter->attr.read_format & PERF_FORMAT_ID;
|
||||
}
|
||||
|
||||
static int __run_perf_stat(int argc, const char **argv)
|
||||
{
|
||||
int interval = stat_config.interval;
|
||||
|
@ -631,7 +654,8 @@ static int __run_perf_stat(int argc, const char **argv)
|
|||
if (l > unit_width)
|
||||
unit_width = l;
|
||||
|
||||
if (STAT_RECORD && store_counter_ids(counter))
|
||||
if (perf_evsel__should_store_id(counter) &&
|
||||
store_counter_ids(counter))
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
|
@ -134,7 +134,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
|
|||
return err;
|
||||
}
|
||||
|
||||
err = symbol__disassemble(sym, map, NULL, 0, NULL);
|
||||
err = symbol__disassemble(sym, map, NULL, 0, NULL, NULL);
|
||||
if (err == 0) {
|
||||
out_assign:
|
||||
top->sym_filter_entry = he;
|
||||
|
@ -183,6 +183,7 @@ static void ui__warn_map_erange(struct map *map, struct symbol *sym, u64 ip)
|
|||
|
||||
static void perf_top__record_precise_ip(struct perf_top *top,
|
||||
struct hist_entry *he,
|
||||
struct perf_sample *sample,
|
||||
int counter, u64 ip)
|
||||
{
|
||||
struct annotation *notes;
|
||||
|
@ -199,7 +200,7 @@ static void perf_top__record_precise_ip(struct perf_top *top,
|
|||
if (pthread_mutex_trylock(¬es->lock))
|
||||
return;
|
||||
|
||||
err = hist_entry__inc_addr_samples(he, counter, ip);
|
||||
err = hist_entry__inc_addr_samples(he, sample, counter, ip);
|
||||
|
||||
pthread_mutex_unlock(¬es->lock);
|
||||
|
||||
|
@ -586,6 +587,13 @@ static void *display_thread_tui(void *arg)
|
|||
.refresh = top->delay_secs,
|
||||
};
|
||||
|
||||
/* In order to read symbols from other namespaces perf to needs to call
|
||||
* setns(2). This isn't permitted if the struct_fs has multiple users.
|
||||
* unshare(2) the fs so that we may continue to setns into namespaces
|
||||
* that we're observing.
|
||||
*/
|
||||
unshare(CLONE_FS);
|
||||
|
||||
perf_top__sort_new_samples(top);
|
||||
|
||||
/*
|
||||
|
@ -627,6 +635,13 @@ static void *display_thread(void *arg)
|
|||
struct perf_top *top = arg;
|
||||
int delay_msecs, c;
|
||||
|
||||
/* In order to read symbols from other namespaces perf to needs to call
|
||||
* setns(2). This isn't permitted if the struct_fs has multiple users.
|
||||
* unshare(2) the fs so that we may continue to setns into namespaces
|
||||
* that we're observing.
|
||||
*/
|
||||
unshare(CLONE_FS);
|
||||
|
||||
display_setup_sig();
|
||||
pthread__unblock_sigwinch();
|
||||
repeat:
|
||||
|
@ -671,7 +686,7 @@ static int hist_iter__top_callback(struct hist_entry_iter *iter,
|
|||
struct perf_evsel *evsel = iter->evsel;
|
||||
|
||||
if (perf_hpp_list.sym && single)
|
||||
perf_top__record_precise_ip(top, he, evsel->idx, al->addr);
|
||||
perf_top__record_precise_ip(top, he, iter->sample, evsel->idx, al->addr);
|
||||
|
||||
hist__account_cycles(iter->sample->branch_stack, al, iter->sample,
|
||||
!(top->record_opts.branch_stack & PERF_SAMPLE_BRANCH_ANY));
|
||||
|
@ -1205,6 +1220,7 @@ int cmd_top(int argc, const char **argv)
|
|||
"Show raw trace event output (do not use print fmt or plugins)"),
|
||||
OPT_BOOLEAN(0, "hierarchy", &symbol_conf.report_hierarchy,
|
||||
"Show entries in a hierarchy"),
|
||||
OPT_BOOLEAN(0, "force", &symbol_conf.force, "don't complain, do it"),
|
||||
OPT_END()
|
||||
};
|
||||
const char * const top_usage[] = {
|
||||
|
|
|
@ -64,6 +64,10 @@
|
|||
# define O_CLOEXEC 02000000
|
||||
#endif
|
||||
|
||||
#ifndef F_LINUX_SPECIFIC_BASE
|
||||
# define F_LINUX_SPECIFIC_BASE 1024
|
||||
#endif
|
||||
|
||||
struct trace {
|
||||
struct perf_tool tool;
|
||||
struct syscalltbl *sctbl;
|
||||
|
@ -279,34 +283,21 @@ static struct perf_evsel *perf_evsel__syscall_newtp(const char *direction, void
|
|||
({ struct syscall_tp *fields = evsel->priv; \
|
||||
fields->name.pointer(&fields->name, sample); })
|
||||
|
||||
struct strarray {
|
||||
int offset;
|
||||
int nr_entries;
|
||||
const char **entries;
|
||||
};
|
||||
size_t strarray__scnprintf(struct strarray *sa, char *bf, size_t size, const char *intfmt, int val)
|
||||
{
|
||||
int idx = val - sa->offset;
|
||||
|
||||
#define DEFINE_STRARRAY(array) struct strarray strarray__##array = { \
|
||||
.nr_entries = ARRAY_SIZE(array), \
|
||||
.entries = array, \
|
||||
}
|
||||
if (idx < 0 || idx >= sa->nr_entries)
|
||||
return scnprintf(bf, size, intfmt, val);
|
||||
|
||||
#define DEFINE_STRARRAY_OFFSET(array, off) struct strarray strarray__##array = { \
|
||||
.offset = off, \
|
||||
.nr_entries = ARRAY_SIZE(array), \
|
||||
.entries = array, \
|
||||
return scnprintf(bf, size, "%s", sa->entries[idx]);
|
||||
}
|
||||
|
||||
static size_t __syscall_arg__scnprintf_strarray(char *bf, size_t size,
|
||||
const char *intfmt,
|
||||
struct syscall_arg *arg)
|
||||
{
|
||||
struct strarray *sa = arg->parm;
|
||||
int idx = arg->val - sa->offset;
|
||||
|
||||
if (idx < 0 || idx >= sa->nr_entries)
|
||||
return scnprintf(bf, size, intfmt, arg->val);
|
||||
|
||||
return scnprintf(bf, size, "%s", sa->entries[idx]);
|
||||
return strarray__scnprintf(arg->parm, bf, size, intfmt, arg->val);
|
||||
}
|
||||
|
||||
static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
|
||||
|
@ -317,24 +308,35 @@ static size_t syscall_arg__scnprintf_strarray(char *bf, size_t size,
|
|||
|
||||
#define SCA_STRARRAY syscall_arg__scnprintf_strarray
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/*
|
||||
* FIXME: Make this available to all arches as soon as the ioctl beautifier
|
||||
* gets rewritten to support all arches.
|
||||
*/
|
||||
static size_t syscall_arg__scnprintf_strhexarray(char *bf, size_t size,
|
||||
struct syscall_arg *arg)
|
||||
{
|
||||
return __syscall_arg__scnprintf_strarray(bf, size, "%#x", arg);
|
||||
struct strarrays {
|
||||
int nr_entries;
|
||||
struct strarray **entries;
|
||||
};
|
||||
|
||||
#define DEFINE_STRARRAYS(array) struct strarrays strarrays__##array = { \
|
||||
.nr_entries = ARRAY_SIZE(array), \
|
||||
.entries = array, \
|
||||
}
|
||||
|
||||
#define SCA_STRHEXARRAY syscall_arg__scnprintf_strhexarray
|
||||
#endif /* defined(__i386__) || defined(__x86_64__) */
|
||||
size_t syscall_arg__scnprintf_strarrays(char *bf, size_t size,
|
||||
struct syscall_arg *arg)
|
||||
{
|
||||
struct strarrays *sas = arg->parm;
|
||||
int i;
|
||||
|
||||
static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
|
||||
struct syscall_arg *arg);
|
||||
for (i = 0; i < sas->nr_entries; ++i) {
|
||||
struct strarray *sa = sas->entries[i];
|
||||
int idx = arg->val - sa->offset;
|
||||
|
||||
#define SCA_FD syscall_arg__scnprintf_fd
|
||||
if (idx >= 0 && idx < sa->nr_entries) {
|
||||
if (sa->entries[idx] == NULL)
|
||||
break;
|
||||
return scnprintf(bf, size, "%s", sa->entries[idx]);
|
||||
}
|
||||
}
|
||||
|
||||
return scnprintf(bf, size, "%d", arg->val);
|
||||
}
|
||||
|
||||
#ifndef AT_FDCWD
|
||||
#define AT_FDCWD -100
|
||||
|
@ -358,21 +360,20 @@ static size_t syscall_arg__scnprintf_close_fd(char *bf, size_t size,
|
|||
|
||||
#define SCA_CLOSE_FD syscall_arg__scnprintf_close_fd
|
||||
|
||||
static size_t syscall_arg__scnprintf_hex(char *bf, size_t size,
|
||||
struct syscall_arg *arg)
|
||||
size_t syscall_arg__scnprintf_hex(char *bf, size_t size, struct syscall_arg *arg)
|
||||
{
|
||||
return scnprintf(bf, size, "%#lx", arg->val);
|
||||
}
|
||||
|
||||
#define SCA_HEX syscall_arg__scnprintf_hex
|
||||
|
||||
static size_t syscall_arg__scnprintf_int(char *bf, size_t size,
|
||||
struct syscall_arg *arg)
|
||||
size_t syscall_arg__scnprintf_int(char *bf, size_t size, struct syscall_arg *arg)
|
||||
{
|
||||
return scnprintf(bf, size, "%d", arg->val);
|
||||
}
|
||||
|
||||
#define SCA_INT syscall_arg__scnprintf_int
|
||||
size_t syscall_arg__scnprintf_long(char *bf, size_t size, struct syscall_arg *arg)
|
||||
{
|
||||
return scnprintf(bf, size, "%ld", arg->val);
|
||||
}
|
||||
|
||||
static const char *bpf_cmd[] = {
|
||||
"MAP_CREATE", "MAP_LOOKUP_ELEM", "MAP_UPDATE_ELEM", "MAP_DELETE_ELEM",
|
||||
|
@ -407,12 +408,27 @@ static DEFINE_STRARRAY(whences);
|
|||
|
||||
static const char *fcntl_cmds[] = {
|
||||
"DUPFD", "GETFD", "SETFD", "GETFL", "SETFL", "GETLK", "SETLK",
|
||||
"SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "F_GETLK64",
|
||||
"F_SETLK64", "F_SETLKW64", "F_SETOWN_EX", "F_GETOWN_EX",
|
||||
"F_GETOWNER_UIDS",
|
||||
"SETLKW", "SETOWN", "GETOWN", "SETSIG", "GETSIG", "GETLK64",
|
||||
"SETLK64", "SETLKW64", "SETOWN_EX", "GETOWN_EX",
|
||||
"GETOWNER_UIDS",
|
||||
};
|
||||
static DEFINE_STRARRAY(fcntl_cmds);
|
||||
|
||||
static const char *fcntl_linux_specific_cmds[] = {
|
||||
"SETLEASE", "GETLEASE", "NOTIFY", [5] = "CANCELLK", "DUPFD_CLOEXEC",
|
||||
"SETPIPE_SZ", "GETPIPE_SZ", "ADD_SEALS", "GET_SEALS",
|
||||
"GET_RW_HINT", "SET_RW_HINT", "GET_FILE_RW_HINT", "SET_FILE_RW_HINT",
|
||||
};
|
||||
|
||||
static DEFINE_STRARRAY_OFFSET(fcntl_linux_specific_cmds, F_LINUX_SPECIFIC_BASE);
|
||||
|
||||
static struct strarray *fcntl_cmds_arrays[] = {
|
||||
&strarray__fcntl_cmds,
|
||||
&strarray__fcntl_linux_specific_cmds,
|
||||
};
|
||||
|
||||
static DEFINE_STRARRAYS(fcntl_cmds_arrays);
|
||||
|
||||
static const char *rlimit_resources[] = {
|
||||
"CPU", "FSIZE", "DATA", "STACK", "CORE", "RSS", "NPROC", "NOFILE",
|
||||
"MEMLOCK", "AS", "LOCKS", "SIGPENDING", "MSGQUEUE", "NICE", "RTPRIO",
|
||||
|
@ -495,33 +511,6 @@ static size_t syscall_arg__scnprintf_pipe_flags(char *bf, size_t size,
|
|||
|
||||
#define SCA_PIPE_FLAGS syscall_arg__scnprintf_pipe_flags
|
||||
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/*
|
||||
* FIXME: Make this available to all arches.
|
||||
*/
|
||||
#define TCGETS 0x5401
|
||||
|
||||
static const char *tioctls[] = {
|
||||
"TCGETS", "TCSETS", "TCSETSW", "TCSETSF", "TCGETA", "TCSETA", "TCSETAW",
|
||||
"TCSETAF", "TCSBRK", "TCXONC", "TCFLSH", "TIOCEXCL", "TIOCNXCL",
|
||||
"TIOCSCTTY", "TIOCGPGRP", "TIOCSPGRP", "TIOCOUTQ", "TIOCSTI",
|
||||
"TIOCGWINSZ", "TIOCSWINSZ", "TIOCMGET", "TIOCMBIS", "TIOCMBIC",
|
||||
"TIOCMSET", "TIOCGSOFTCAR", "TIOCSSOFTCAR", "FIONREAD", "TIOCLINUX",
|
||||
"TIOCCONS", "TIOCGSERIAL", "TIOCSSERIAL", "TIOCPKT", "FIONBIO",
|
||||
"TIOCNOTTY", "TIOCSETD", "TIOCGETD", "TCSBRKP", [0x27] = "TIOCSBRK",
|
||||
"TIOCCBRK", "TIOCGSID", "TCGETS2", "TCSETS2", "TCSETSW2", "TCSETSF2",
|
||||
"TIOCGRS485", "TIOCSRS485", "TIOCGPTN", "TIOCSPTLCK",
|
||||
"TIOCGDEV||TCGETX", "TCSETX", "TCSETXF", "TCSETXW", "TIOCSIG",
|
||||
"TIOCVHANGUP", "TIOCGPKT", "TIOCGPTLCK", "TIOCGEXCL",
|
||||
[0x50] = "FIONCLEX", "FIOCLEX", "FIOASYNC", "TIOCSERCONFIG",
|
||||
"TIOCSERGWILD", "TIOCSERSWILD", "TIOCGLCKTRMIOS", "TIOCSLCKTRMIOS",
|
||||
"TIOCSERGSTRUCT", "TIOCSERGETLSR", "TIOCSERGETMULTI", "TIOCSERSETMULTI",
|
||||
"TIOCMIWAIT", "TIOCGICOUNT", [0x60] = "FIOQSIZE",
|
||||
};
|
||||
|
||||
static DEFINE_STRARRAY_OFFSET(tioctls, 0x5401);
|
||||
#endif /* defined(__i386__) || defined(__x86_64__) */
|
||||
|
||||
#ifndef GRND_NONBLOCK
|
||||
#define GRND_NONBLOCK 0x0001
|
||||
#endif
|
||||
|
@ -552,9 +541,9 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
|
|||
|
||||
#define SCA_GETRANDOM_FLAGS syscall_arg__scnprintf_getrandom_flags
|
||||
|
||||
#define STRARRAY(arg, name, array) \
|
||||
.arg_scnprintf = { [arg] = SCA_STRARRAY, }, \
|
||||
.arg_parm = { [arg] = &strarray__##array, }
|
||||
#define STRARRAY(name, array) \
|
||||
{ .scnprintf = SCA_STRARRAY, \
|
||||
.parm = &strarray__##array, }
|
||||
|
||||
#include "trace/beauty/eventfd.c"
|
||||
#include "trace/beauty/flock.c"
|
||||
|
@ -571,242 +560,219 @@ static size_t syscall_arg__scnprintf_getrandom_flags(char *bf, size_t size,
|
|||
#include "trace/beauty/socket_type.c"
|
||||
#include "trace/beauty/waitid_options.c"
|
||||
|
||||
struct syscall_arg_fmt {
|
||||
size_t (*scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
|
||||
void *parm;
|
||||
const char *name;
|
||||
bool show_zero;
|
||||
};
|
||||
|
||||
static struct syscall_fmt {
|
||||
const char *name;
|
||||
const char *alias;
|
||||
size_t (*arg_scnprintf[6])(char *bf, size_t size, struct syscall_arg *arg);
|
||||
void *arg_parm[6];
|
||||
bool errmsg;
|
||||
struct syscall_arg_fmt arg[6];
|
||||
u8 nr_args;
|
||||
bool errpid;
|
||||
bool timeout;
|
||||
bool hexret;
|
||||
} syscall_fmts[] = {
|
||||
{ .name = "access", .errmsg = true,
|
||||
.arg_scnprintf = { [1] = SCA_ACCMODE, /* mode */ }, },
|
||||
{ .name = "arch_prctl", .errmsg = true, .alias = "prctl", },
|
||||
{ .name = "bpf", .errmsg = true, STRARRAY(0, cmd, bpf_cmd), },
|
||||
{ .name = "access",
|
||||
.arg = { [1] = { .scnprintf = SCA_ACCMODE, /* mode */ }, }, },
|
||||
{ .name = "arch_prctl", .alias = "prctl", },
|
||||
{ .name = "bpf",
|
||||
.arg = { [0] = STRARRAY(cmd, bpf_cmd), }, },
|
||||
{ .name = "brk", .hexret = true,
|
||||
.arg_scnprintf = { [0] = SCA_HEX, /* brk */ }, },
|
||||
{ .name = "chdir", .errmsg = true, },
|
||||
{ .name = "chmod", .errmsg = true, },
|
||||
{ .name = "chroot", .errmsg = true, },
|
||||
{ .name = "clock_gettime", .errmsg = true, STRARRAY(0, clk_id, clockid), },
|
||||
{ .name = "clone", .errpid = true, },
|
||||
{ .name = "close", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_CLOSE_FD, /* fd */ }, },
|
||||
{ .name = "connect", .errmsg = true, },
|
||||
{ .name = "creat", .errmsg = true, },
|
||||
{ .name = "dup", .errmsg = true, },
|
||||
{ .name = "dup2", .errmsg = true, },
|
||||
{ .name = "dup3", .errmsg = true, },
|
||||
{ .name = "epoll_ctl", .errmsg = true, STRARRAY(1, op, epoll_ctl_ops), },
|
||||
{ .name = "eventfd2", .errmsg = true,
|
||||
.arg_scnprintf = { [1] = SCA_EFD_FLAGS, /* flags */ }, },
|
||||
{ .name = "faccessat", .errmsg = true, },
|
||||
{ .name = "fadvise64", .errmsg = true, },
|
||||
{ .name = "fallocate", .errmsg = true, },
|
||||
{ .name = "fchdir", .errmsg = true, },
|
||||
{ .name = "fchmod", .errmsg = true, },
|
||||
{ .name = "fchmodat", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
|
||||
{ .name = "fchown", .errmsg = true, },
|
||||
{ .name = "fchownat", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
|
||||
{ .name = "fcntl", .errmsg = true,
|
||||
.arg_scnprintf = { [1] = SCA_STRARRAY, /* cmd */ },
|
||||
.arg_parm = { [1] = &strarray__fcntl_cmds, /* cmd */ }, },
|
||||
{ .name = "fdatasync", .errmsg = true, },
|
||||
{ .name = "flock", .errmsg = true,
|
||||
.arg_scnprintf = { [1] = SCA_FLOCK, /* cmd */ }, },
|
||||
{ .name = "fsetxattr", .errmsg = true, },
|
||||
{ .name = "fstat", .errmsg = true, .alias = "newfstat", },
|
||||
{ .name = "fstatat", .errmsg = true, .alias = "newfstatat", },
|
||||
{ .name = "fstatfs", .errmsg = true, },
|
||||
{ .name = "fsync", .errmsg = true, },
|
||||
{ .name = "ftruncate", .errmsg = true, },
|
||||
{ .name = "futex", .errmsg = true,
|
||||
.arg_scnprintf = { [1] = SCA_FUTEX_OP, /* op */ }, },
|
||||
{ .name = "futimesat", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
|
||||
{ .name = "getdents", .errmsg = true, },
|
||||
{ .name = "getdents64", .errmsg = true, },
|
||||
{ .name = "getitimer", .errmsg = true, STRARRAY(0, which, itimers), },
|
||||
.arg = { [0] = { .scnprintf = SCA_HEX, /* brk */ }, }, },
|
||||
{ .name = "clock_gettime",
|
||||
.arg = { [0] = STRARRAY(clk_id, clockid), }, },
|
||||
{ .name = "clone", .errpid = true, .nr_args = 5,
|
||||
.arg = { [0] = { .name = "flags", .scnprintf = SCA_CLONE_FLAGS, },
|
||||
[1] = { .name = "child_stack", .scnprintf = SCA_HEX, },
|
||||
[2] = { .name = "parent_tidptr", .scnprintf = SCA_HEX, },
|
||||
[3] = { .name = "child_tidptr", .scnprintf = SCA_HEX, },
|
||||
[4] = { .name = "tls", .scnprintf = SCA_HEX, }, }, },
|
||||
{ .name = "close",
|
||||
.arg = { [0] = { .scnprintf = SCA_CLOSE_FD, /* fd */ }, }, },
|
||||
{ .name = "epoll_ctl",
|
||||
.arg = { [1] = STRARRAY(op, epoll_ctl_ops), }, },
|
||||
{ .name = "eventfd2",
|
||||
.arg = { [1] = { .scnprintf = SCA_EFD_FLAGS, /* flags */ }, }, },
|
||||
{ .name = "fchmodat",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
|
||||
{ .name = "fchownat",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
|
||||
{ .name = "fcntl",
|
||||
.arg = { [1] = { .scnprintf = SCA_FCNTL_CMD, /* cmd */
|
||||
.parm = &strarrays__fcntl_cmds_arrays,
|
||||
.show_zero = true, },
|
||||
[2] = { .scnprintf = SCA_FCNTL_ARG, /* arg */ }, }, },
|
||||
{ .name = "flock",
|
||||
.arg = { [1] = { .scnprintf = SCA_FLOCK, /* cmd */ }, }, },
|
||||
{ .name = "fstat", .alias = "newfstat", },
|
||||
{ .name = "fstatat", .alias = "newfstatat", },
|
||||
{ .name = "futex",
|
||||
.arg = { [1] = { .scnprintf = SCA_FUTEX_OP, /* op */ }, }, },
|
||||
{ .name = "futimesat",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
|
||||
{ .name = "getitimer",
|
||||
.arg = { [0] = STRARRAY(which, itimers), }, },
|
||||
{ .name = "getpid", .errpid = true, },
|
||||
{ .name = "getpgid", .errpid = true, },
|
||||
{ .name = "getppid", .errpid = true, },
|
||||
{ .name = "getrandom", .errmsg = true,
|
||||
.arg_scnprintf = { [2] = SCA_GETRANDOM_FLAGS, /* flags */ }, },
|
||||
{ .name = "getrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
|
||||
{ .name = "getxattr", .errmsg = true, },
|
||||
{ .name = "inotify_add_watch", .errmsg = true, },
|
||||
{ .name = "ioctl", .errmsg = true,
|
||||
.arg_scnprintf = {
|
||||
{ .name = "getrandom",
|
||||
.arg = { [2] = { .scnprintf = SCA_GETRANDOM_FLAGS, /* flags */ }, }, },
|
||||
{ .name = "getrlimit",
|
||||
.arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
|
||||
{ .name = "ioctl",
|
||||
.arg = {
|
||||
#if defined(__i386__) || defined(__x86_64__)
|
||||
/*
|
||||
* FIXME: Make this available to all arches.
|
||||
*/
|
||||
[1] = SCA_STRHEXARRAY, /* cmd */
|
||||
[2] = SCA_HEX, /* arg */ },
|
||||
.arg_parm = { [1] = &strarray__tioctls, /* cmd */ }, },
|
||||
[1] = { .scnprintf = SCA_IOCTL_CMD, /* cmd */ },
|
||||
[2] = { .scnprintf = SCA_HEX, /* arg */ }, }, },
|
||||
#else
|
||||
[2] = SCA_HEX, /* arg */ }, },
|
||||
[2] = { .scnprintf = SCA_HEX, /* arg */ }, }, },
|
||||
#endif
|
||||
{ .name = "keyctl", .errmsg = true, STRARRAY(0, option, keyctl_options), },
|
||||
{ .name = "kill", .errmsg = true,
|
||||
.arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
|
||||
{ .name = "lchown", .errmsg = true, },
|
||||
{ .name = "lgetxattr", .errmsg = true, },
|
||||
{ .name = "linkat", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
|
||||
{ .name = "listxattr", .errmsg = true, },
|
||||
{ .name = "llistxattr", .errmsg = true, },
|
||||
{ .name = "lremovexattr", .errmsg = true, },
|
||||
{ .name = "lseek", .errmsg = true,
|
||||
.arg_scnprintf = { [2] = SCA_STRARRAY, /* whence */ },
|
||||
.arg_parm = { [2] = &strarray__whences, /* whence */ }, },
|
||||
{ .name = "lsetxattr", .errmsg = true, },
|
||||
{ .name = "lstat", .errmsg = true, .alias = "newlstat", },
|
||||
{ .name = "lsxattr", .errmsg = true, },
|
||||
{ .name = "madvise", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_HEX, /* start */
|
||||
[2] = SCA_MADV_BHV, /* behavior */ }, },
|
||||
{ .name = "mkdir", .errmsg = true, },
|
||||
{ .name = "mkdirat", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
|
||||
{ .name = "mknod", .errmsg = true, },
|
||||
{ .name = "mknodat", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* fd */ }, },
|
||||
{ .name = "mlock", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
|
||||
{ .name = "mlockall", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
|
||||
{ .name = "keyctl",
|
||||
.arg = { [0] = STRARRAY(option, keyctl_options), }, },
|
||||
{ .name = "kill",
|
||||
.arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
|
||||
{ .name = "linkat",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
|
||||
{ .name = "lseek",
|
||||
.arg = { [2] = STRARRAY(whence, whences), }, },
|
||||
{ .name = "lstat", .alias = "newlstat", },
|
||||
{ .name = "madvise",
|
||||
.arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
|
||||
[2] = { .scnprintf = SCA_MADV_BHV, /* behavior */ }, }, },
|
||||
{ .name = "mkdirat",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
|
||||
{ .name = "mknodat",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fd */ }, }, },
|
||||
{ .name = "mlock",
|
||||
.arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
|
||||
{ .name = "mlockall",
|
||||
.arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
|
||||
{ .name = "mmap", .hexret = true,
|
||||
/* The standard mmap maps to old_mmap on s390x */
|
||||
#if defined(__s390x__)
|
||||
.alias = "old_mmap",
|
||||
#endif
|
||||
.arg_scnprintf = { [0] = SCA_HEX, /* addr */
|
||||
[2] = SCA_MMAP_PROT, /* prot */
|
||||
[3] = SCA_MMAP_FLAGS, /* flags */ }, },
|
||||
{ .name = "mprotect", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_HEX, /* start */
|
||||
[2] = SCA_MMAP_PROT, /* prot */ }, },
|
||||
{ .name = "mq_unlink", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* u_name */ }, },
|
||||
.arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
|
||||
[2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ },
|
||||
[3] = { .scnprintf = SCA_MMAP_FLAGS, /* flags */ }, }, },
|
||||
{ .name = "mprotect",
|
||||
.arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
|
||||
[2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ }, }, },
|
||||
{ .name = "mq_unlink",
|
||||
.arg = { [0] = { .scnprintf = SCA_FILENAME, /* u_name */ }, }, },
|
||||
{ .name = "mremap", .hexret = true,
|
||||
.arg_scnprintf = { [0] = SCA_HEX, /* addr */
|
||||
[3] = SCA_MREMAP_FLAGS, /* flags */
|
||||
[4] = SCA_HEX, /* new_addr */ }, },
|
||||
{ .name = "munlock", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
|
||||
{ .name = "munmap", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_HEX, /* addr */ }, },
|
||||
{ .name = "name_to_handle_at", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
|
||||
{ .name = "newfstatat", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
|
||||
{ .name = "open", .errmsg = true,
|
||||
.arg_scnprintf = { [1] = SCA_OPEN_FLAGS, /* flags */ }, },
|
||||
{ .name = "open_by_handle_at", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
|
||||
[2] = SCA_OPEN_FLAGS, /* flags */ }, },
|
||||
{ .name = "openat", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */
|
||||
[2] = SCA_OPEN_FLAGS, /* flags */ }, },
|
||||
{ .name = "perf_event_open", .errmsg = true,
|
||||
.arg_scnprintf = { [2] = SCA_INT, /* cpu */
|
||||
[3] = SCA_FD, /* group_fd */
|
||||
[4] = SCA_PERF_FLAGS, /* flags */ }, },
|
||||
{ .name = "pipe2", .errmsg = true,
|
||||
.arg_scnprintf = { [1] = SCA_PIPE_FLAGS, /* flags */ }, },
|
||||
{ .name = "poll", .errmsg = true, .timeout = true, },
|
||||
{ .name = "ppoll", .errmsg = true, .timeout = true, },
|
||||
{ .name = "pread", .errmsg = true, .alias = "pread64", },
|
||||
{ .name = "preadv", .errmsg = true, .alias = "pread", },
|
||||
{ .name = "prlimit64", .errmsg = true, STRARRAY(1, resource, rlimit_resources), },
|
||||
{ .name = "pwrite", .errmsg = true, .alias = "pwrite64", },
|
||||
{ .name = "pwritev", .errmsg = true, },
|
||||
{ .name = "read", .errmsg = true, },
|
||||
{ .name = "readlink", .errmsg = true, },
|
||||
{ .name = "readlinkat", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
|
||||
{ .name = "readv", .errmsg = true, },
|
||||
{ .name = "recvfrom", .errmsg = true,
|
||||
.arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
|
||||
{ .name = "recvmmsg", .errmsg = true,
|
||||
.arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
|
||||
{ .name = "recvmsg", .errmsg = true,
|
||||
.arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
|
||||
{ .name = "removexattr", .errmsg = true, },
|
||||
{ .name = "renameat", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
|
||||
{ .name = "rmdir", .errmsg = true, },
|
||||
{ .name = "rt_sigaction", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_SIGNUM, /* sig */ }, },
|
||||
{ .name = "rt_sigprocmask", .errmsg = true, STRARRAY(0, how, sighow), },
|
||||
{ .name = "rt_sigqueueinfo", .errmsg = true,
|
||||
.arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
|
||||
{ .name = "rt_tgsigqueueinfo", .errmsg = true,
|
||||
.arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
|
||||
{ .name = "sched_getattr", .errmsg = true, },
|
||||
{ .name = "sched_setattr", .errmsg = true, },
|
||||
{ .name = "sched_setscheduler", .errmsg = true,
|
||||
.arg_scnprintf = { [1] = SCA_SCHED_POLICY, /* policy */ }, },
|
||||
{ .name = "seccomp", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_SECCOMP_OP, /* op */
|
||||
[1] = SCA_SECCOMP_FLAGS, /* flags */ }, },
|
||||
{ .name = "select", .errmsg = true, .timeout = true, },
|
||||
{ .name = "sendmmsg", .errmsg = true,
|
||||
.arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
|
||||
{ .name = "sendmsg", .errmsg = true,
|
||||
.arg_scnprintf = { [2] = SCA_MSG_FLAGS, /* flags */ }, },
|
||||
{ .name = "sendto", .errmsg = true,
|
||||
.arg_scnprintf = { [3] = SCA_MSG_FLAGS, /* flags */ }, },
|
||||
.arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ },
|
||||
[3] = { .scnprintf = SCA_MREMAP_FLAGS, /* flags */ },
|
||||
[4] = { .scnprintf = SCA_HEX, /* new_addr */ }, }, },
|
||||
{ .name = "munlock",
|
||||
.arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
|
||||
{ .name = "munmap",
|
||||
.arg = { [0] = { .scnprintf = SCA_HEX, /* addr */ }, }, },
|
||||
{ .name = "name_to_handle_at",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
|
||||
{ .name = "newfstatat",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
|
||||
{ .name = "open",
|
||||
.arg = { [1] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
|
||||
{ .name = "open_by_handle_at",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ },
|
||||
[2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
|
||||
{ .name = "openat",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ },
|
||||
[2] = { .scnprintf = SCA_OPEN_FLAGS, /* flags */ }, }, },
|
||||
{ .name = "perf_event_open",
|
||||
.arg = { [2] = { .scnprintf = SCA_INT, /* cpu */ },
|
||||
[3] = { .scnprintf = SCA_FD, /* group_fd */ },
|
||||
[4] = { .scnprintf = SCA_PERF_FLAGS, /* flags */ }, }, },
|
||||
{ .name = "pipe2",
|
||||
.arg = { [1] = { .scnprintf = SCA_PIPE_FLAGS, /* flags */ }, }, },
|
||||
{ .name = "pkey_alloc",
|
||||
.arg = { [1] = { .scnprintf = SCA_PKEY_ALLOC_ACCESS_RIGHTS, /* access_rights */ }, }, },
|
||||
{ .name = "pkey_free",
|
||||
.arg = { [0] = { .scnprintf = SCA_INT, /* key */ }, }, },
|
||||
{ .name = "pkey_mprotect",
|
||||
.arg = { [0] = { .scnprintf = SCA_HEX, /* start */ },
|
||||
[2] = { .scnprintf = SCA_MMAP_PROT, /* prot */ },
|
||||
[3] = { .scnprintf = SCA_INT, /* pkey */ }, }, },
|
||||
{ .name = "poll", .timeout = true, },
|
||||
{ .name = "ppoll", .timeout = true, },
|
||||
{ .name = "pread", .alias = "pread64", },
|
||||
{ .name = "preadv", .alias = "pread", },
|
||||
{ .name = "prlimit64",
|
||||
.arg = { [1] = STRARRAY(resource, rlimit_resources), }, },
|
||||
{ .name = "pwrite", .alias = "pwrite64", },
|
||||
{ .name = "readlinkat",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
|
||||
{ .name = "recvfrom",
|
||||
.arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
|
||||
{ .name = "recvmmsg",
|
||||
.arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
|
||||
{ .name = "recvmsg",
|
||||
.arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
|
||||
{ .name = "renameat",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
|
||||
{ .name = "rt_sigaction",
|
||||
.arg = { [0] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
|
||||
{ .name = "rt_sigprocmask",
|
||||
.arg = { [0] = STRARRAY(how, sighow), }, },
|
||||
{ .name = "rt_sigqueueinfo",
|
||||
.arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
|
||||
{ .name = "rt_tgsigqueueinfo",
|
||||
.arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
|
||||
{ .name = "sched_setscheduler",
|
||||
.arg = { [1] = { .scnprintf = SCA_SCHED_POLICY, /* policy */ }, }, },
|
||||
{ .name = "seccomp",
|
||||
.arg = { [0] = { .scnprintf = SCA_SECCOMP_OP, /* op */ },
|
||||
[1] = { .scnprintf = SCA_SECCOMP_FLAGS, /* flags */ }, }, },
|
||||
{ .name = "select", .timeout = true, },
|
||||
{ .name = "sendmmsg",
|
||||
.arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
|
||||
{ .name = "sendmsg",
|
||||
.arg = { [2] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
|
||||
{ .name = "sendto",
|
||||
.arg = { [3] = { .scnprintf = SCA_MSG_FLAGS, /* flags */ }, }, },
|
||||
{ .name = "set_tid_address", .errpid = true, },
|
||||
{ .name = "setitimer", .errmsg = true, STRARRAY(0, which, itimers), },
|
||||
{ .name = "setpgid", .errmsg = true, },
|
||||
{ .name = "setrlimit", .errmsg = true, STRARRAY(0, resource, rlimit_resources), },
|
||||
{ .name = "setxattr", .errmsg = true, },
|
||||
{ .name = "shutdown", .errmsg = true, },
|
||||
{ .name = "socket", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
|
||||
[1] = SCA_SK_TYPE, /* type */ },
|
||||
.arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
|
||||
{ .name = "socketpair", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_STRARRAY, /* family */
|
||||
[1] = SCA_SK_TYPE, /* type */ },
|
||||
.arg_parm = { [0] = &strarray__socket_families, /* family */ }, },
|
||||
{ .name = "stat", .errmsg = true, .alias = "newstat", },
|
||||
{ .name = "statfs", .errmsg = true, },
|
||||
{ .name = "statx", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* flags */
|
||||
[2] = SCA_STATX_FLAGS, /* flags */
|
||||
[3] = SCA_STATX_MASK, /* mask */ }, },
|
||||
{ .name = "swapoff", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
|
||||
{ .name = "swapon", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FILENAME, /* specialfile */ }, },
|
||||
{ .name = "symlinkat", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
|
||||
{ .name = "tgkill", .errmsg = true,
|
||||
.arg_scnprintf = { [2] = SCA_SIGNUM, /* sig */ }, },
|
||||
{ .name = "tkill", .errmsg = true,
|
||||
.arg_scnprintf = { [1] = SCA_SIGNUM, /* sig */ }, },
|
||||
{ .name = "truncate", .errmsg = true, },
|
||||
{ .name = "uname", .errmsg = true, .alias = "newuname", },
|
||||
{ .name = "unlinkat", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dfd */ }, },
|
||||
{ .name = "utime", .errmsg = true, },
|
||||
{ .name = "utimensat", .errmsg = true,
|
||||
.arg_scnprintf = { [0] = SCA_FDAT, /* dirfd */ }, },
|
||||
{ .name = "utimes", .errmsg = true, },
|
||||
{ .name = "vmsplice", .errmsg = true, },
|
||||
{ .name = "setitimer",
|
||||
.arg = { [0] = STRARRAY(which, itimers), }, },
|
||||
{ .name = "setrlimit",
|
||||
.arg = { [0] = STRARRAY(resource, rlimit_resources), }, },
|
||||
{ .name = "socket",
|
||||
.arg = { [0] = STRARRAY(family, socket_families),
|
||||
[1] = { .scnprintf = SCA_SK_TYPE, /* type */ }, }, },
|
||||
{ .name = "socketpair",
|
||||
.arg = { [0] = STRARRAY(family, socket_families),
|
||||
[1] = { .scnprintf = SCA_SK_TYPE, /* type */ }, }, },
|
||||
{ .name = "stat", .alias = "newstat", },
|
||||
{ .name = "statx",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* fdat */ },
|
||||
[2] = { .scnprintf = SCA_STATX_FLAGS, /* flags */ } ,
|
||||
[3] = { .scnprintf = SCA_STATX_MASK, /* mask */ }, }, },
|
||||
{ .name = "swapoff",
|
||||
.arg = { [0] = { .scnprintf = SCA_FILENAME, /* specialfile */ }, }, },
|
||||
{ .name = "swapon",
|
||||
.arg = { [0] = { .scnprintf = SCA_FILENAME, /* specialfile */ }, }, },
|
||||
{ .name = "symlinkat",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
|
||||
{ .name = "tgkill",
|
||||
.arg = { [2] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
|
||||
{ .name = "tkill",
|
||||
.arg = { [1] = { .scnprintf = SCA_SIGNUM, /* sig */ }, }, },
|
||||
{ .name = "uname", .alias = "newuname", },
|
||||
{ .name = "unlinkat",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dfd */ }, }, },
|
||||
{ .name = "utimensat",
|
||||
.arg = { [0] = { .scnprintf = SCA_FDAT, /* dirfd */ }, }, },
|
||||
{ .name = "wait4", .errpid = true,
|
||||
.arg_scnprintf = { [2] = SCA_WAITID_OPTIONS, /* options */ }, },
|
||||
.arg = { [2] = { .scnprintf = SCA_WAITID_OPTIONS, /* options */ }, }, },
|
||||
{ .name = "waitid", .errpid = true,
|
||||
.arg_scnprintf = { [3] = SCA_WAITID_OPTIONS, /* options */ }, },
|
||||
{ .name = "write", .errmsg = true, },
|
||||
{ .name = "writev", .errmsg = true, },
|
||||
.arg = { [3] = { .scnprintf = SCA_WAITID_OPTIONS, /* options */ }, }, },
|
||||
};
|
||||
|
||||
static int syscall_fmt__cmp(const void *name, const void *fmtp)
|
||||
|
@ -828,8 +794,7 @@ struct syscall {
|
|||
const char *name;
|
||||
bool is_exit;
|
||||
struct syscall_fmt *fmt;
|
||||
size_t (**arg_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
|
||||
void **arg_parm;
|
||||
struct syscall_arg_fmt *arg_fmt;
|
||||
};
|
||||
|
||||
/*
|
||||
|
@ -859,6 +824,8 @@ static size_t fprintf_duration(unsigned long t, bool calculated, FILE *fp)
|
|||
* filename.ptr: The filename char pointer that will be vfs_getname'd
|
||||
* filename.entry_str_pos: Where to insert the string translated from
|
||||
* filename.ptr by the vfs_getname tracepoint/kprobe.
|
||||
* ret_scnprintf: syscall args may set this to a different syscall return
|
||||
* formatter, for instance, fcntl may return fds, file flags, etc.
|
||||
*/
|
||||
struct thread_trace {
|
||||
u64 entry_time;
|
||||
|
@ -867,6 +834,7 @@ struct thread_trace {
|
|||
unsigned long pfmaj, pfmin;
|
||||
char *entry_str;
|
||||
double runtime_ms;
|
||||
size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg);
|
||||
struct {
|
||||
unsigned long ptr;
|
||||
short int entry_str_pos;
|
||||
|
@ -917,6 +885,15 @@ static struct thread_trace *thread__trace(struct thread *thread, FILE *fp)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void syscall_arg__set_ret_scnprintf(struct syscall_arg *arg,
|
||||
size_t (*ret_scnprintf)(char *bf, size_t size, struct syscall_arg *arg))
|
||||
{
|
||||
struct thread_trace *ttrace = thread__priv(arg->thread);
|
||||
|
||||
ttrace->ret_scnprintf = ret_scnprintf;
|
||||
}
|
||||
|
||||
#define TRACE_PFMAJ (1 << 0)
|
||||
#define TRACE_PFMIN (1 << 1)
|
||||
|
||||
|
@ -996,8 +973,7 @@ static const char *thread__fd_path(struct thread *thread, int fd,
|
|||
return ttrace->paths.table[fd];
|
||||
}
|
||||
|
||||
static size_t syscall_arg__scnprintf_fd(char *bf, size_t size,
|
||||
struct syscall_arg *arg)
|
||||
size_t syscall_arg__scnprintf_fd(char *bf, size_t size, struct syscall_arg *arg)
|
||||
{
|
||||
int fd = arg->val;
|
||||
size_t printed = scnprintf(bf, size, "%d", fd);
|
||||
|
@ -1162,32 +1138,46 @@ static int trace__symbols_init(struct trace *trace, struct perf_evlist *evlist)
|
|||
return err;
|
||||
}
|
||||
|
||||
static int syscall__alloc_arg_fmts(struct syscall *sc, int nr_args)
|
||||
{
|
||||
int idx;
|
||||
|
||||
if (nr_args == 6 && sc->fmt && sc->fmt->nr_args != 0)
|
||||
nr_args = sc->fmt->nr_args;
|
||||
|
||||
sc->arg_fmt = calloc(nr_args, sizeof(*sc->arg_fmt));
|
||||
if (sc->arg_fmt == NULL)
|
||||
return -1;
|
||||
|
||||
for (idx = 0; idx < nr_args; ++idx) {
|
||||
if (sc->fmt)
|
||||
sc->arg_fmt[idx] = sc->fmt->arg[idx];
|
||||
}
|
||||
|
||||
sc->nr_args = nr_args;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int syscall__set_arg_fmts(struct syscall *sc)
|
||||
{
|
||||
struct format_field *field;
|
||||
int idx = 0, len;
|
||||
|
||||
sc->arg_scnprintf = calloc(sc->nr_args, sizeof(void *));
|
||||
if (sc->arg_scnprintf == NULL)
|
||||
return -1;
|
||||
for (field = sc->args; field; field = field->next, ++idx) {
|
||||
if (sc->fmt && sc->fmt->arg[idx].scnprintf)
|
||||
continue;
|
||||
|
||||
if (sc->fmt)
|
||||
sc->arg_parm = sc->fmt->arg_parm;
|
||||
|
||||
for (field = sc->args; field; field = field->next) {
|
||||
if (sc->fmt && sc->fmt->arg_scnprintf[idx])
|
||||
sc->arg_scnprintf[idx] = sc->fmt->arg_scnprintf[idx];
|
||||
else if (strcmp(field->type, "const char *") == 0 &&
|
||||
if (strcmp(field->type, "const char *") == 0 &&
|
||||
(strcmp(field->name, "filename") == 0 ||
|
||||
strcmp(field->name, "path") == 0 ||
|
||||
strcmp(field->name, "pathname") == 0))
|
||||
sc->arg_scnprintf[idx] = SCA_FILENAME;
|
||||
sc->arg_fmt[idx].scnprintf = SCA_FILENAME;
|
||||
else if (field->flags & FIELD_IS_POINTER)
|
||||
sc->arg_scnprintf[idx] = syscall_arg__scnprintf_hex;
|
||||
sc->arg_fmt[idx].scnprintf = syscall_arg__scnprintf_hex;
|
||||
else if (strcmp(field->type, "pid_t") == 0)
|
||||
sc->arg_scnprintf[idx] = SCA_PID;
|
||||
sc->arg_fmt[idx].scnprintf = SCA_PID;
|
||||
else if (strcmp(field->type, "umode_t") == 0)
|
||||
sc->arg_scnprintf[idx] = SCA_MODE_T;
|
||||
sc->arg_fmt[idx].scnprintf = SCA_MODE_T;
|
||||
else if ((strcmp(field->type, "int") == 0 ||
|
||||
strcmp(field->type, "unsigned int") == 0 ||
|
||||
strcmp(field->type, "long") == 0) &&
|
||||
|
@ -1200,9 +1190,8 @@ static int syscall__set_arg_fmts(struct syscall *sc)
|
|||
* 23 unsigned int
|
||||
* 7 unsigned long
|
||||
*/
|
||||
sc->arg_scnprintf[idx] = SCA_FD;
|
||||
sc->arg_fmt[idx].scnprintf = SCA_FD;
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
@ -1247,11 +1236,13 @@ static int trace__read_syscall_info(struct trace *trace, int id)
|
|||
sc->tp_format = trace_event__tp_format("syscalls", tp_name);
|
||||
}
|
||||
|
||||
if (syscall__alloc_arg_fmts(sc, IS_ERR(sc->tp_format) ? 6 : sc->tp_format->format.nr_fields))
|
||||
return -1;
|
||||
|
||||
if (IS_ERR(sc->tp_format))
|
||||
return -1;
|
||||
|
||||
sc->args = sc->tp_format->format.fields;
|
||||
sc->nr_args = sc->tp_format->format.nr_fields;
|
||||
/*
|
||||
* We need to check and discard the first variable '__syscall_nr'
|
||||
* or 'nr' that mean the syscall number. It is needless here.
|
||||
|
@ -1321,33 +1312,68 @@ static int trace__validate_ev_qualifier(struct trace *trace)
|
|||
* variable to read it. Most notably this avoids extended load instructions
|
||||
* on unaligned addresses
|
||||
*/
|
||||
unsigned long syscall_arg__val(struct syscall_arg *arg, u8 idx)
|
||||
{
|
||||
unsigned long val;
|
||||
unsigned char *p = arg->args + sizeof(unsigned long) * idx;
|
||||
|
||||
memcpy(&val, p, sizeof(val));
|
||||
return val;
|
||||
}
|
||||
|
||||
static size_t syscall__scnprintf_name(struct syscall *sc, char *bf, size_t size,
|
||||
struct syscall_arg *arg)
|
||||
{
|
||||
if (sc->arg_fmt && sc->arg_fmt[arg->idx].name)
|
||||
return scnprintf(bf, size, "%s: ", sc->arg_fmt[arg->idx].name);
|
||||
|
||||
return scnprintf(bf, size, "arg%d: ", arg->idx);
|
||||
}
|
||||
|
||||
static size_t syscall__scnprintf_val(struct syscall *sc, char *bf, size_t size,
|
||||
struct syscall_arg *arg, unsigned long val)
|
||||
{
|
||||
if (sc->arg_fmt && sc->arg_fmt[arg->idx].scnprintf) {
|
||||
arg->val = val;
|
||||
if (sc->arg_fmt[arg->idx].parm)
|
||||
arg->parm = sc->arg_fmt[arg->idx].parm;
|
||||
return sc->arg_fmt[arg->idx].scnprintf(bf, size, arg);
|
||||
}
|
||||
return scnprintf(bf, size, "%ld", val);
|
||||
}
|
||||
|
||||
static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
|
||||
unsigned char *args, struct trace *trace,
|
||||
struct thread *thread)
|
||||
{
|
||||
size_t printed = 0;
|
||||
unsigned char *p;
|
||||
unsigned long val;
|
||||
u8 bit = 1;
|
||||
struct syscall_arg arg = {
|
||||
.args = args,
|
||||
.idx = 0,
|
||||
.mask = 0,
|
||||
.trace = trace,
|
||||
.thread = thread,
|
||||
};
|
||||
struct thread_trace *ttrace = thread__priv(thread);
|
||||
|
||||
/*
|
||||
* Things like fcntl will set this in its 'cmd' formatter to pick the
|
||||
* right formatter for the return value (an fd? file flags?), which is
|
||||
* not needed for syscalls that always return a given type, say an fd.
|
||||
*/
|
||||
ttrace->ret_scnprintf = NULL;
|
||||
|
||||
if (sc->args != NULL) {
|
||||
struct format_field *field;
|
||||
u8 bit = 1;
|
||||
struct syscall_arg arg = {
|
||||
.idx = 0,
|
||||
.mask = 0,
|
||||
.trace = trace,
|
||||
.thread = thread,
|
||||
};
|
||||
|
||||
for (field = sc->args; field;
|
||||
field = field->next, ++arg.idx, bit <<= 1) {
|
||||
if (arg.mask & bit)
|
||||
continue;
|
||||
|
||||
/* special care for unaligned accesses */
|
||||
p = args + sizeof(unsigned long) * arg.idx;
|
||||
memcpy(&val, p, sizeof(val));
|
||||
val = syscall_arg__val(&arg, arg.idx);
|
||||
|
||||
/*
|
||||
* Suppress this argument if its value is zero and
|
||||
|
@ -1355,23 +1381,16 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
|
|||
* strarray for it.
|
||||
*/
|
||||
if (val == 0 &&
|
||||
!(sc->arg_scnprintf &&
|
||||
sc->arg_scnprintf[arg.idx] == SCA_STRARRAY &&
|
||||
sc->arg_parm[arg.idx]))
|
||||
!(sc->arg_fmt &&
|
||||
(sc->arg_fmt[arg.idx].show_zero ||
|
||||
sc->arg_fmt[arg.idx].scnprintf == SCA_STRARRAY ||
|
||||
sc->arg_fmt[arg.idx].scnprintf == SCA_STRARRAYS) &&
|
||||
sc->arg_fmt[arg.idx].parm))
|
||||
continue;
|
||||
|
||||
printed += scnprintf(bf + printed, size - printed,
|
||||
"%s%s: ", printed ? ", " : "", field->name);
|
||||
if (sc->arg_scnprintf && sc->arg_scnprintf[arg.idx]) {
|
||||
arg.val = val;
|
||||
if (sc->arg_parm)
|
||||
arg.parm = sc->arg_parm[arg.idx];
|
||||
printed += sc->arg_scnprintf[arg.idx](bf + printed,
|
||||
size - printed, &arg);
|
||||
} else {
|
||||
printed += scnprintf(bf + printed, size - printed,
|
||||
"%ld", val);
|
||||
}
|
||||
printed += syscall__scnprintf_val(sc, bf + printed, size - printed, &arg, val);
|
||||
}
|
||||
} else if (IS_ERR(sc->tp_format)) {
|
||||
/*
|
||||
|
@ -1379,16 +1398,17 @@ static size_t syscall__scnprintf_args(struct syscall *sc, char *bf, size_t size,
|
|||
* may end up not having any args, like with gettid(), so only
|
||||
* print the raw args when we didn't manage to read it.
|
||||
*/
|
||||
int i = 0;
|
||||
|
||||
while (i < 6) {
|
||||
/* special care for unaligned accesses */
|
||||
p = args + sizeof(unsigned long) * i;
|
||||
memcpy(&val, p, sizeof(val));
|
||||
printed += scnprintf(bf + printed, size - printed,
|
||||
"%sarg%d: %ld",
|
||||
printed ? ", " : "", i, val);
|
||||
++i;
|
||||
while (arg.idx < sc->nr_args) {
|
||||
if (arg.mask & bit)
|
||||
goto next_arg;
|
||||
val = syscall_arg__val(&arg, arg.idx);
|
||||
if (printed)
|
||||
printed += scnprintf(bf + printed, size - printed, ", ");
|
||||
printed += syscall__scnprintf_name(sc, bf + printed, size - printed, &arg);
|
||||
printed += syscall__scnprintf_val(sc, bf + printed, size - printed, &arg, val);
|
||||
next_arg:
|
||||
++arg.idx;
|
||||
bit <<= 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1635,17 +1655,31 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
|
|||
}
|
||||
|
||||
if (sc->fmt == NULL) {
|
||||
if (ret < 0)
|
||||
goto errno_print;
|
||||
signed_print:
|
||||
fprintf(trace->output, ") = %ld", ret);
|
||||
} else if (ret < 0 && (sc->fmt->errmsg || sc->fmt->errpid)) {
|
||||
} else if (ret < 0) {
|
||||
errno_print: {
|
||||
char bf[STRERR_BUFSIZE];
|
||||
const char *emsg = str_error_r(-ret, bf, sizeof(bf)),
|
||||
*e = audit_errno_to_name(-ret);
|
||||
|
||||
fprintf(trace->output, ") = -1 %s %s", e, emsg);
|
||||
}
|
||||
} else if (ret == 0 && sc->fmt->timeout)
|
||||
fprintf(trace->output, ") = 0 Timeout");
|
||||
else if (sc->fmt->hexret)
|
||||
else if (ttrace->ret_scnprintf) {
|
||||
char bf[1024];
|
||||
struct syscall_arg arg = {
|
||||
.val = ret,
|
||||
.thread = thread,
|
||||
.trace = trace,
|
||||
};
|
||||
ttrace->ret_scnprintf(bf, sizeof(bf), &arg);
|
||||
ttrace->ret_scnprintf = NULL;
|
||||
fprintf(trace->output, ") = %s", bf);
|
||||
} else if (sc->fmt->hexret)
|
||||
fprintf(trace->output, ") = %#lx", ret);
|
||||
else if (sc->fmt->errpid) {
|
||||
struct thread *child = machine__find_thread(trace->host, ret, ret);
|
||||
|
@ -2171,6 +2205,30 @@ static int trace__set_ev_qualifier_filter(struct trace *trace)
|
|||
goto out;
|
||||
}
|
||||
|
||||
static int trace__set_filter_loop_pids(struct trace *trace)
|
||||
{
|
||||
unsigned int nr = 1;
|
||||
pid_t pids[32] = {
|
||||
getpid(),
|
||||
};
|
||||
struct thread *thread = machine__find_thread(trace->host, pids[0], pids[0]);
|
||||
|
||||
while (thread && nr < ARRAY_SIZE(pids)) {
|
||||
struct thread *parent = machine__find_thread(trace->host, thread->ppid, thread->ppid);
|
||||
|
||||
if (parent == NULL)
|
||||
break;
|
||||
|
||||
if (!strcmp(thread__comm_str(parent), "sshd")) {
|
||||
pids[nr++] = parent->tid;
|
||||
break;
|
||||
}
|
||||
thread = parent;
|
||||
}
|
||||
|
||||
return perf_evlist__set_filter_pids(trace->evlist, nr, pids);
|
||||
}
|
||||
|
||||
static int trace__run(struct trace *trace, int argc, const char **argv)
|
||||
{
|
||||
struct perf_evlist *evlist = trace->evlist;
|
||||
|
@ -2294,7 +2352,7 @@ static int trace__run(struct trace *trace, int argc, const char **argv)
|
|||
if (trace->filter_pids.nr > 0)
|
||||
err = perf_evlist__set_filter_pids(evlist, trace->filter_pids.nr, trace->filter_pids.entries);
|
||||
else if (thread_map__pid(evlist->threads, 0) == -1)
|
||||
err = perf_evlist__set_filter_pid(evlist, getpid());
|
||||
err = trace__set_filter_loop_pids(trace);
|
||||
|
||||
if (err < 0)
|
||||
goto out_error_mem;
|
||||
|
@ -2756,7 +2814,7 @@ static int trace__parse_events_option(const struct option *opt, const char *str,
|
|||
struct trace *trace = (struct trace *)opt->value;
|
||||
const char *s = str;
|
||||
char *sep = NULL, *lists[2] = { NULL, NULL, };
|
||||
int len = strlen(str), err = -1, list;
|
||||
int len = strlen(str) + 1, err = -1, list;
|
||||
char *strace_groups_dir = system_path(STRACE_GROUPS_DIR);
|
||||
char group_name[PATH_MAX];
|
||||
|
||||
|
|
|
@ -1,9 +1,15 @@
|
|||
#!/bin/sh
|
||||
|
||||
HEADERS='
|
||||
include/uapi/drm/drm.h
|
||||
include/uapi/drm/i915_drm.h
|
||||
include/uapi/linux/fcntl.h
|
||||
include/uapi/linux/kvm.h
|
||||
include/uapi/linux/perf_event.h
|
||||
include/uapi/linux/sched.h
|
||||
include/uapi/linux/stat.h
|
||||
include/uapi/linux/vhost.h
|
||||
include/uapi/sound/asound.h
|
||||
include/linux/hash.h
|
||||
include/uapi/linux/hw_breakpoint.h
|
||||
arch/x86/include/asm/disabled-features.h
|
||||
|
@ -16,6 +22,7 @@ arch/x86/include/uapi/asm/perf_regs.h
|
|||
arch/x86/include/uapi/asm/kvm.h
|
||||
arch/x86/include/uapi/asm/kvm_perf.h
|
||||
arch/x86/include/uapi/asm/svm.h
|
||||
arch/x86/include/uapi/asm/unistd.h
|
||||
arch/x86/include/uapi/asm/vmx.h
|
||||
arch/powerpc/include/uapi/asm/kvm.h
|
||||
arch/s390/include/uapi/asm/kvm.h
|
||||
|
@ -29,12 +36,13 @@ include/asm-generic/bitops/__fls.h
|
|||
include/asm-generic/bitops/fls.h
|
||||
include/asm-generic/bitops/fls64.h
|
||||
include/linux/coresight-pmu.h
|
||||
include/uapi/asm-generic/ioctls.h
|
||||
include/uapi/asm-generic/mman-common.h
|
||||
'
|
||||
|
||||
check () {
|
||||
file=$1
|
||||
opts=
|
||||
opts="--ignore-blank-lines --ignore-space-change"
|
||||
|
||||
shift
|
||||
while [ -n "$*" ]; do
|
||||
|
@ -45,7 +53,7 @@ check () {
|
|||
cmd="diff $opts ../$file ../../$file > /dev/null"
|
||||
|
||||
test -f ../../$file &&
|
||||
eval $cmd || echo "Warning: $file differs from kernel" >&2
|
||||
eval $cmd || echo "Warning: Kernel ABI header at 'tools/$file' differs from latest version at '$file'" >&2
|
||||
}
|
||||
|
||||
|
||||
|
@ -55,7 +63,7 @@ for i in $HEADERS; do
|
|||
done
|
||||
|
||||
# diff with extra ignore lines
|
||||
check arch/x86/lib/memcpy_64.S -B -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"
|
||||
check arch/x86/lib/memset_64.S -B -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"
|
||||
check include/uapi/asm-generic/mman.h -B -I "^#include <\(uapi/\)*asm-generic/mman-common.h>"
|
||||
check include/uapi/linux/mman.h -B -I "^#include <\(uapi/\)*asm/mman.h>"
|
||||
check arch/x86/lib/memcpy_64.S -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"
|
||||
check arch/x86/lib/memset_64.S -I "^EXPORT_SYMBOL" -I "^#include <asm/export.h>"
|
||||
check include/uapi/asm-generic/mman.h -I "^#include <\(uapi/\)*asm-generic/mman-common.h>"
|
||||
check include/uapi/linux/mman.h -I "^#include <\(uapi/\)*asm/mman.h>"
|
||||
|
|
|
@ -9,16 +9,6 @@
|
|||
#include <linux/perf_event.h>
|
||||
#include <asm/barrier.h>
|
||||
|
||||
#if defined(__i386__)
|
||||
#define cpu_relax() asm volatile("rep; nop" ::: "memory");
|
||||
#define CPUINFO_PROC {"model name"}
|
||||
#endif
|
||||
|
||||
#if defined(__x86_64__)
|
||||
#define cpu_relax() asm volatile("rep; nop" ::: "memory");
|
||||
#define CPUINFO_PROC {"model name"}
|
||||
#endif
|
||||
|
||||
#ifdef __powerpc__
|
||||
#define CPUINFO_PROC {"cpu"}
|
||||
#endif
|
||||
|
@ -43,19 +33,10 @@
|
|||
#define CPUINFO_PROC {"cpu model"}
|
||||
#endif
|
||||
|
||||
#ifdef __ia64__
|
||||
#define cpu_relax() asm volatile ("hint @pause" ::: "memory")
|
||||
#define CPUINFO_PROC {"model name"}
|
||||
#endif
|
||||
|
||||
#ifdef __arm__
|
||||
#define CPUINFO_PROC {"model name", "Processor"}
|
||||
#endif
|
||||
|
||||
#ifdef __aarch64__
|
||||
#define cpu_relax() asm volatile("yield" ::: "memory")
|
||||
#endif
|
||||
|
||||
#ifdef __mips__
|
||||
#define CPUINFO_PROC {"cpu model"}
|
||||
#endif
|
||||
|
@ -72,13 +53,8 @@
|
|||
#define CPUINFO_PROC {"core ID"}
|
||||
#endif
|
||||
|
||||
#ifdef __tile__
|
||||
#define cpu_relax() asm volatile ("mfspr zero, PASS" ::: "memory")
|
||||
#define CPUINFO_PROC {"model name"}
|
||||
#endif
|
||||
|
||||
#ifndef cpu_relax
|
||||
#define cpu_relax() barrier()
|
||||
#ifndef CPUINFO_PROC
|
||||
#define CPUINFO_PROC { "model name", }
|
||||
#endif
|
||||
|
||||
static inline int
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue