Commit 3237f281 authored by Wang Nan's avatar Wang Nan Committed by Arnaldo Carvalho de Melo

perf tools: Add ARM64 perf_regs_load to support libunwind and enable testing

Newest libunwind does support ARM64, and perf is able to utilize it
also.

This patch enables the perf test dwarf unwind for arm64.

 Test result:
  # ./perf test unwind
  25: Test dwarf unwind                                      : Ok
Signed-off-by: default avatarWang Nan <wangnan0@huawei.com>
Acked-by: default avatarJiri Olsa <jolsa@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Zefan Li <lizefan@huawei.com>
Link: http://lkml.kernel.org/r/1427461681-72971-1-git-send-email-wangnan0@huawei.comSigned-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
parent b2365122
libperf-y += util/ libperf-y += util/
libperf-$(CONFIG_DWARF_UNWIND) += tests/
...@@ -5,8 +5,11 @@ ...@@ -5,8 +5,11 @@
#include <linux/types.h> #include <linux/types.h>
#include <asm/perf_regs.h> #include <asm/perf_regs.h>
void perf_regs_load(u64 *regs);
#define PERF_REGS_MASK ((1ULL << PERF_REG_ARM64_MAX) - 1) #define PERF_REGS_MASK ((1ULL << PERF_REG_ARM64_MAX) - 1)
#define PERF_REGS_MAX PERF_REG_ARM64_MAX #define PERF_REGS_MAX PERF_REG_ARM64_MAX
#define PERF_SAMPLE_REGS_ABI PERF_SAMPLE_REGS_ABI_64
#define PERF_REG_IP PERF_REG_ARM64_PC #define PERF_REG_IP PERF_REG_ARM64_PC
#define PERF_REG_SP PERF_REG_ARM64_SP #define PERF_REG_SP PERF_REG_ARM64_SP
......
libperf-y += regs_load.o
libperf-y += dwarf-unwind.o
#include <string.h>
#include "perf_regs.h"
#include "thread.h"
#include "map.h"
#include "event.h"
#include "debug.h"
#include "tests/tests.h"
#define STACK_SIZE 8192
static int sample_ustack(struct perf_sample *sample,
struct thread *thread, u64 *regs)
{
struct stack_dump *stack = &sample->user_stack;
struct map *map;
unsigned long sp;
u64 stack_size, *buf;
buf = malloc(STACK_SIZE);
if (!buf) {
pr_debug("failed to allocate sample uregs data\n");
return -1;
}
sp = (unsigned long) regs[PERF_REG_ARM64_SP];
map = map_groups__find(thread->mg, MAP__VARIABLE, (u64) sp);
if (!map) {
pr_debug("failed to get stack map\n");
free(buf);
return -1;
}
stack_size = map->end - sp;
stack_size = stack_size > STACK_SIZE ? STACK_SIZE : stack_size;
memcpy(buf, (void *) sp, stack_size);
stack->data = (char *) buf;
stack->size = stack_size;
return 0;
}
int test__arch_unwind_sample(struct perf_sample *sample,
struct thread *thread)
{
struct regs_dump *regs = &sample->user_regs;
u64 *buf;
buf = calloc(1, sizeof(u64) * PERF_REGS_MAX);
if (!buf) {
pr_debug("failed to allocate sample uregs data\n");
return -1;
}
perf_regs_load(buf);
regs->abi = PERF_SAMPLE_REGS_ABI;
regs->regs = buf;
regs->mask = PERF_REGS_MASK;
return sample_ustack(sample, thread, buf);
}
#include <linux/linkage.h>
.text
.type perf_regs_load,%function
#define STR_REG(r) str x##r, [x0, 8 * r]
#define LDR_REG(r) ldr x##r, [x0, 8 * r]
#define SP (8 * 31)
#define PC (8 * 32)
ENTRY(perf_regs_load)
STR_REG(0)
STR_REG(1)
STR_REG(2)
STR_REG(3)
STR_REG(4)
STR_REG(5)
STR_REG(6)
STR_REG(7)
STR_REG(8)
STR_REG(9)
STR_REG(10)
STR_REG(11)
STR_REG(12)
STR_REG(13)
STR_REG(14)
STR_REG(15)
STR_REG(16)
STR_REG(17)
STR_REG(18)
STR_REG(19)
STR_REG(20)
STR_REG(21)
STR_REG(22)
STR_REG(23)
STR_REG(24)
STR_REG(25)
STR_REG(26)
STR_REG(27)
STR_REG(28)
STR_REG(29)
STR_REG(30)
mov x1, sp
str x1, [x0, #SP]
str x30, [x0, #PC]
LDR_REG(1)
ret
ENDPROC(perf_regs_load)
...@@ -34,7 +34,7 @@ perf-y += kmod-path.o ...@@ -34,7 +34,7 @@ perf-y += kmod-path.o
perf-$(CONFIG_X86) += perf-time-to-tsc.o perf-$(CONFIG_X86) += perf-time-to-tsc.o
ifeq ($(ARCH),$(filter $(ARCH),x86 arm)) ifeq ($(ARCH),$(filter $(ARCH),x86 arm arm64))
perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o perf-$(CONFIG_DWARF_UNWIND) += dwarf-unwind.o
endif endif
......
...@@ -126,7 +126,7 @@ static struct test { ...@@ -126,7 +126,7 @@ static struct test {
.desc = "Test parsing with no sample_id_all bit set", .desc = "Test parsing with no sample_id_all bit set",
.func = test__parse_no_sample_id_all, .func = test__parse_no_sample_id_all,
}, },
#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
#ifdef HAVE_DWARF_UNWIND_SUPPORT #ifdef HAVE_DWARF_UNWIND_SUPPORT
{ {
.desc = "Test dwarf unwind", .desc = "Test dwarf unwind",
......
...@@ -62,7 +62,7 @@ int test__fdarray__filter(void); ...@@ -62,7 +62,7 @@ int test__fdarray__filter(void);
int test__fdarray__add(void); int test__fdarray__add(void);
int test__kmod_path__parse(void); int test__kmod_path__parse(void);
#if defined(__x86_64__) || defined(__i386__) || defined(__arm__) #if defined(__x86_64__) || defined(__i386__) || defined(__arm__) || defined(__aarch64__)
#ifdef HAVE_DWARF_UNWIND_SUPPORT #ifdef HAVE_DWARF_UNWIND_SUPPORT
struct thread; struct thread;
struct perf_sample; struct perf_sample;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment