Merge branch 'perf/urgent' into perf/core, to pick up fixes and to refresh to v4.15
Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
@@ -1,9 +1,72 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
#ifndef S390_DWARF_REGS_TABLE_H
|
||||
#define S390_DWARF_REGS_TABLE_H
|
||||
|
||||
#define REG_DWARFNUM_NAME(reg, idx) [idx] = "%" #reg
|
||||
|
||||
/*
|
||||
* For reference, see DWARF register mapping:
|
||||
* http://refspecs.linuxfoundation.org/ELF/zSeries/lzsabi0_s390/x1542.html
|
||||
*/
|
||||
static const char * const s390_dwarf_regs[] = {
|
||||
"%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
|
||||
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
|
||||
REG_DWARFNUM_NAME(f0, 16),
|
||||
REG_DWARFNUM_NAME(f1, 20),
|
||||
REG_DWARFNUM_NAME(f2, 17),
|
||||
REG_DWARFNUM_NAME(f3, 21),
|
||||
REG_DWARFNUM_NAME(f4, 18),
|
||||
REG_DWARFNUM_NAME(f5, 22),
|
||||
REG_DWARFNUM_NAME(f6, 19),
|
||||
REG_DWARFNUM_NAME(f7, 23),
|
||||
REG_DWARFNUM_NAME(f8, 24),
|
||||
REG_DWARFNUM_NAME(f9, 28),
|
||||
REG_DWARFNUM_NAME(f10, 25),
|
||||
REG_DWARFNUM_NAME(f11, 29),
|
||||
REG_DWARFNUM_NAME(f12, 26),
|
||||
REG_DWARFNUM_NAME(f13, 30),
|
||||
REG_DWARFNUM_NAME(f14, 27),
|
||||
REG_DWARFNUM_NAME(f15, 31),
|
||||
REG_DWARFNUM_NAME(c0, 32),
|
||||
REG_DWARFNUM_NAME(c1, 33),
|
||||
REG_DWARFNUM_NAME(c2, 34),
|
||||
REG_DWARFNUM_NAME(c3, 35),
|
||||
REG_DWARFNUM_NAME(c4, 36),
|
||||
REG_DWARFNUM_NAME(c5, 37),
|
||||
REG_DWARFNUM_NAME(c6, 38),
|
||||
REG_DWARFNUM_NAME(c7, 39),
|
||||
REG_DWARFNUM_NAME(c8, 40),
|
||||
REG_DWARFNUM_NAME(c9, 41),
|
||||
REG_DWARFNUM_NAME(c10, 42),
|
||||
REG_DWARFNUM_NAME(c11, 43),
|
||||
REG_DWARFNUM_NAME(c12, 44),
|
||||
REG_DWARFNUM_NAME(c13, 45),
|
||||
REG_DWARFNUM_NAME(c14, 46),
|
||||
REG_DWARFNUM_NAME(c15, 47),
|
||||
REG_DWARFNUM_NAME(a0, 48),
|
||||
REG_DWARFNUM_NAME(a1, 49),
|
||||
REG_DWARFNUM_NAME(a2, 50),
|
||||
REG_DWARFNUM_NAME(a3, 51),
|
||||
REG_DWARFNUM_NAME(a4, 52),
|
||||
REG_DWARFNUM_NAME(a5, 53),
|
||||
REG_DWARFNUM_NAME(a6, 54),
|
||||
REG_DWARFNUM_NAME(a7, 55),
|
||||
REG_DWARFNUM_NAME(a8, 56),
|
||||
REG_DWARFNUM_NAME(a9, 57),
|
||||
REG_DWARFNUM_NAME(a10, 58),
|
||||
REG_DWARFNUM_NAME(a11, 59),
|
||||
REG_DWARFNUM_NAME(a12, 60),
|
||||
REG_DWARFNUM_NAME(a13, 61),
|
||||
REG_DWARFNUM_NAME(a14, 62),
|
||||
REG_DWARFNUM_NAME(a15, 63),
|
||||
REG_DWARFNUM_NAME(pswm, 64),
|
||||
REG_DWARFNUM_NAME(pswa, 65),
|
||||
};
|
||||
|
||||
#ifdef DEFINE_DWARF_REGSTR_TABLE
|
||||
/* This is included in perf/util/dwarf-regs.c */
|
||||
|
||||
static const char * const s390_regstr_tbl[] = {
|
||||
"%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
|
||||
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
|
||||
};
|
||||
#endif
|
||||
#define s390_regstr_tbl s390_dwarf_regs
|
||||
|
||||
#endif /* DEFINE_DWARF_REGSTR_TABLE */
|
||||
#endif /* S390_DWARF_REGS_TABLE_H */
|
||||
|
95
tools/perf/arch/s390/include/perf_regs.h
Normal file
95
tools/perf/arch/s390/include/perf_regs.h
Normal file
@@ -0,0 +1,95 @@
|
||||
#ifndef ARCH_PERF_REGS_H
|
||||
#define ARCH_PERF_REGS_H
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <linux/types.h>
|
||||
#include <../../../../arch/s390/include/uapi/asm/perf_regs.h>
|
||||
|
||||
void perf_regs_load(u64 *regs);
|
||||
|
||||
#define PERF_REGS_MASK ((1ULL << PERF_REG_S390_MAX) - 1)
|
||||
#define PERF_REGS_MAX PERF_REG_S390_MAX
|
||||
#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64
|
||||
|
||||
#define PERF_REG_IP PERF_REG_S390_PC
|
||||
#define PERF_REG_SP PERF_REG_S390_R15
|
||||
|
||||
static inline const char *perf_reg_name(int id)
|
||||
{
|
||||
switch (id) {
|
||||
case PERF_REG_S390_R0:
|
||||
return "R0";
|
||||
case PERF_REG_S390_R1:
|
||||
return "R1";
|
||||
case PERF_REG_S390_R2:
|
||||
return "R2";
|
||||
case PERF_REG_S390_R3:
|
||||
return "R3";
|
||||
case PERF_REG_S390_R4:
|
||||
return "R4";
|
||||
case PERF_REG_S390_R5:
|
||||
return "R5";
|
||||
case PERF_REG_S390_R6:
|
||||
return "R6";
|
||||
case PERF_REG_S390_R7:
|
||||
return "R7";
|
||||
case PERF_REG_S390_R8:
|
||||
return "R8";
|
||||
case PERF_REG_S390_R9:
|
||||
return "R9";
|
||||
case PERF_REG_S390_R10:
|
||||
return "R10";
|
||||
case PERF_REG_S390_R11:
|
||||
return "R11";
|
||||
case PERF_REG_S390_R12:
|
||||
return "R12";
|
||||
case PERF_REG_S390_R13:
|
||||
return "R13";
|
||||
case PERF_REG_S390_R14:
|
||||
return "R14";
|
||||
case PERF_REG_S390_R15:
|
||||
return "R15";
|
||||
case PERF_REG_S390_FP0:
|
||||
return "FP0";
|
||||
case PERF_REG_S390_FP1:
|
||||
return "FP1";
|
||||
case PERF_REG_S390_FP2:
|
||||
return "FP2";
|
||||
case PERF_REG_S390_FP3:
|
||||
return "FP3";
|
||||
case PERF_REG_S390_FP4:
|
||||
return "FP4";
|
||||
case PERF_REG_S390_FP5:
|
||||
return "FP5";
|
||||
case PERF_REG_S390_FP6:
|
||||
return "FP6";
|
||||
case PERF_REG_S390_FP7:
|
||||
return "FP7";
|
||||
case PERF_REG_S390_FP8:
|
||||
return "FP8";
|
||||
case PERF_REG_S390_FP9:
|
||||
return "FP9";
|
||||
case PERF_REG_S390_FP10:
|
||||
return "FP10";
|
||||
case PERF_REG_S390_FP11:
|
||||
return "FP11";
|
||||
case PERF_REG_S390_FP12:
|
||||
return "FP12";
|
||||
case PERF_REG_S390_FP13:
|
||||
return "FP13";
|
||||
case PERF_REG_S390_FP14:
|
||||
return "FP14";
|
||||
case PERF_REG_S390_FP15:
|
||||
return "FP15";
|
||||
case PERF_REG_S390_MASK:
|
||||
return "MASK";
|
||||
case PERF_REG_S390_PC:
|
||||
return "PC";
|
||||
default:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif /* ARCH_PERF_REGS_H */
|
@@ -2,5 +2,8 @@ libperf-y += header.o
|
||||
libperf-y += kvm-stat.o
|
||||
|
||||
libperf-$(CONFIG_DWARF) += dwarf-regs.o
|
||||
libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o
|
||||
|
||||
libperf-y += machine.o
|
||||
|
||||
libperf-$(CONFIG_AUXTRACE) += auxtrace.o
|
||||
|
118
tools/perf/arch/s390/util/auxtrace.c
Normal file
118
tools/perf/arch/s390/util/auxtrace.c
Normal file
@@ -0,0 +1,118 @@
|
||||
#include <stdbool.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/log2.h>
|
||||
|
||||
#include "../../util/evlist.h"
|
||||
#include "../../util/auxtrace.h"
|
||||
#include "../../util/evsel.h"
|
||||
|
||||
#define PERF_EVENT_CPUM_SF 0xB0000 /* Event: Basic-sampling */
|
||||
#define PERF_EVENT_CPUM_SF_DIAG 0xBD000 /* Event: Combined-sampling */
|
||||
#define DEFAULT_AUX_PAGES 128
|
||||
#define DEFAULT_FREQ 4000
|
||||
|
||||
static void cpumsf_free(struct auxtrace_record *itr)
|
||||
{
|
||||
free(itr);
|
||||
}
|
||||
|
||||
static size_t cpumsf_info_priv_size(struct auxtrace_record *itr __maybe_unused,
|
||||
struct perf_evlist *evlist __maybe_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cpumsf_info_fill(struct auxtrace_record *itr __maybe_unused,
|
||||
struct perf_session *session __maybe_unused,
|
||||
struct auxtrace_info_event *auxtrace_info __maybe_unused,
|
||||
size_t priv_size __maybe_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long
|
||||
cpumsf_reference(struct auxtrace_record *itr __maybe_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cpumsf_recording_options(struct auxtrace_record *ar __maybe_unused,
|
||||
struct perf_evlist *evlist __maybe_unused,
|
||||
struct record_opts *opts)
|
||||
{
|
||||
unsigned int factor = 1;
|
||||
unsigned int pages;
|
||||
|
||||
opts->full_auxtrace = true;
|
||||
|
||||
/*
|
||||
* The AUX buffer size should be set properly to avoid
|
||||
* overflow of samples if it is not set explicitly.
|
||||
* DEFAULT_AUX_PAGES is an proper size when sampling frequency
|
||||
* is DEFAULT_FREQ. It is expected to hold about 1/2 second
|
||||
* of sampling data. The size used for AUX buffer will scale
|
||||
* according to the specified frequency and DEFAULT_FREQ.
|
||||
*/
|
||||
if (!opts->auxtrace_mmap_pages) {
|
||||
if (opts->user_freq != UINT_MAX)
|
||||
factor = (opts->user_freq + DEFAULT_FREQ
|
||||
- 1) / DEFAULT_FREQ;
|
||||
pages = DEFAULT_AUX_PAGES * factor;
|
||||
opts->auxtrace_mmap_pages = roundup_pow_of_two(pages);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
cpumsf_parse_snapshot_options(struct auxtrace_record *itr __maybe_unused,
|
||||
struct record_opts *opts __maybe_unused,
|
||||
const char *str __maybe_unused)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* auxtrace_record__init is called when perf record
|
||||
* check if the event really need auxtrace
|
||||
*/
|
||||
struct auxtrace_record *auxtrace_record__init(struct perf_evlist *evlist,
|
||||
int *err)
|
||||
{
|
||||
struct auxtrace_record *aux;
|
||||
struct perf_evsel *pos;
|
||||
int diagnose = 0;
|
||||
|
||||
if (evlist->nr_entries == 0)
|
||||
return NULL;
|
||||
|
||||
evlist__for_each_entry(evlist, pos) {
|
||||
if (pos->attr.config == PERF_EVENT_CPUM_SF_DIAG) {
|
||||
diagnose = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!diagnose)
|
||||
return NULL;
|
||||
|
||||
/* sampling in diagnose mode. alloc aux buffer */
|
||||
aux = zalloc(sizeof(*aux));
|
||||
if (aux == NULL) {
|
||||
*err = -ENOMEM;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
aux->parse_snapshot_options = cpumsf_parse_snapshot_options;
|
||||
aux->recording_options = cpumsf_recording_options;
|
||||
aux->info_priv_size = cpumsf_info_priv_size;
|
||||
aux->info_fill = cpumsf_info_fill;
|
||||
aux->free = cpumsf_free;
|
||||
aux->reference = cpumsf_reference;
|
||||
|
||||
return aux;
|
||||
}
|
@@ -9,15 +9,10 @@
|
||||
|
||||
#include <stddef.h>
|
||||
#include <dwarf-regs.h>
|
||||
|
||||
#define NUM_GPRS 16
|
||||
|
||||
static const char *gpr_names[NUM_GPRS] = {
|
||||
"%r0", "%r1", "%r2", "%r3", "%r4", "%r5", "%r6", "%r7",
|
||||
"%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
|
||||
};
|
||||
#include <linux/kernel.h>
|
||||
#include "dwarf-regs-table.h"
|
||||
|
||||
const char *get_arch_regstr(unsigned int n)
|
||||
{
|
||||
return (n >= NUM_GPRS) ? NULL : gpr_names[n];
|
||||
return (n >= ARRAY_SIZE(s390_dwarf_regs)) ? NULL : s390_dwarf_regs[n];
|
||||
}
|
||||
|
63
tools/perf/arch/s390/util/unwind-libdw.c
Normal file
63
tools/perf/arch/s390/util/unwind-libdw.c
Normal file
@@ -0,0 +1,63 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <elfutils/libdwfl.h>
|
||||
#include "../../util/unwind-libdw.h"
|
||||
#include "../../util/perf_regs.h"
|
||||
#include "../../util/event.h"
|
||||
#include "dwarf-regs-table.h"
|
||||
|
||||
|
||||
bool libdw__arch_set_initial_registers(Dwfl_Thread *thread, void *arg)
|
||||
{
|
||||
struct unwind_info *ui = arg;
|
||||
struct regs_dump *user_regs = &ui->sample->user_regs;
|
||||
Dwarf_Word dwarf_regs[ARRAY_SIZE(s390_dwarf_regs)];
|
||||
|
||||
#define REG(r) ({ \
|
||||
Dwarf_Word val = 0; \
|
||||
perf_reg_value(&val, user_regs, PERF_REG_S390_##r); \
|
||||
val; \
|
||||
})
|
||||
/*
|
||||
* For DWARF register mapping details,
|
||||
* see also perf/arch/s390/include/dwarf-regs-table.h
|
||||
*/
|
||||
dwarf_regs[0] = REG(R0);
|
||||
dwarf_regs[1] = REG(R1);
|
||||
dwarf_regs[2] = REG(R2);
|
||||
dwarf_regs[3] = REG(R3);
|
||||
dwarf_regs[4] = REG(R4);
|
||||
dwarf_regs[5] = REG(R5);
|
||||
dwarf_regs[6] = REG(R6);
|
||||
dwarf_regs[7] = REG(R7);
|
||||
dwarf_regs[8] = REG(R8);
|
||||
dwarf_regs[9] = REG(R9);
|
||||
dwarf_regs[10] = REG(R10);
|
||||
dwarf_regs[11] = REG(R11);
|
||||
dwarf_regs[12] = REG(R12);
|
||||
dwarf_regs[13] = REG(R13);
|
||||
dwarf_regs[14] = REG(R14);
|
||||
dwarf_regs[15] = REG(R15);
|
||||
|
||||
dwarf_regs[16] = REG(FP0);
|
||||
dwarf_regs[17] = REG(FP2);
|
||||
dwarf_regs[18] = REG(FP4);
|
||||
dwarf_regs[19] = REG(FP6);
|
||||
dwarf_regs[20] = REG(FP1);
|
||||
dwarf_regs[21] = REG(FP3);
|
||||
dwarf_regs[22] = REG(FP5);
|
||||
dwarf_regs[23] = REG(FP7);
|
||||
dwarf_regs[24] = REG(FP8);
|
||||
dwarf_regs[25] = REG(FP10);
|
||||
dwarf_regs[26] = REG(FP12);
|
||||
dwarf_regs[27] = REG(FP14);
|
||||
dwarf_regs[28] = REG(FP9);
|
||||
dwarf_regs[29] = REG(FP11);
|
||||
dwarf_regs[30] = REG(FP13);
|
||||
dwarf_regs[31] = REG(FP15);
|
||||
|
||||
dwarf_regs[64] = REG(MASK);
|
||||
dwarf_regs[65] = REG(PC);
|
||||
|
||||
dwfl_thread_state_register_pc(thread, dwarf_regs[65]);
|
||||
return dwfl_thread_state_registers(thread, 0, 32, dwarf_regs);
|
||||
}
|
Reference in New Issue
Block a user