CTIs are defined in the device tree and associated with other CoreSight
devices. The core CoreSight code has been modified to enable the registration
of the CTI devices on the same bus as the other CoreSight components,
but as these are not actually trace generation / capture devices, they
are not part of the Coresight path when generating trace.
However, the definition of the standard CoreSight device has been extended
to include a reference to an associated CTI device, and the enable / disable
trace path operations will auto enable/disable any associated CTI devices at
the same time.
Programming is at present via sysfs - a full API is provided to utilise the
hardware capabilities. As CTI devices are unprogrammed by default, the auto
enable describe above will have no effect until explicit programming takes
place.
A set of device tree bindings specific to the CTI topology has been defined.
The driver accesses these in a platform agnostic manner, so ACPI bindings
can be added later, once they have been agreed and defined for the CTI device.
Documentation has been updated to describe both the CTI hardware, its use and
programming in sysfs, and the new dts bindings required.
Tested on DB410 board, on coresight/next tree - 5.2-rc1 based.
Changes since v2:
Updates to allow for new features on coresight/next and feedback from
Mathieu and Leo.
1) Rebase and restructuring to apply on top of ACPI support patch set,
currently on coresight/next. of_coresight_cti has been renamed to
coresight-cti-platform and device tree bindings added to this but accessed
in a platform agnostic manner using fwnode for later ACPI support
to be added.
2) Split the sysfs patch info a series of functional patches.
3) Revised the refcount and enabling support.
4) Adopted the generic naming protocol - CTIs are either cti_cpuN or
cti_sysM
5) Various minor presentation /checkpatch issues highlighted in feedback.
6) revised CPU hotplug to cover missing cases needed by ETM.
Changes since v1:
1) Significant restructuring of the source code. Adds cti-sysfs file and
cti device tree file. Patches add per feature rather than per source
file.
2) CPU type power event handling for hotplug moved to CoreSight core,
with generic registration interface provided for all CPU bound CS devices
to use.
3) CTI signal interconnection details in sysfs now generated dynamically
from connection lists in driver. This to fix issue with multi-line sysfs
output in previous version.
4) Full device tree bindings for DB410 and Juno provided (to the extent
that CTI information is available).
5) AMBA driver update for UCI IDs are now upstream so no longer included
in this set.
Mike Leach (16):
coresight: cti: Initial CoreSight CTI Driver
coresight: cti: Add sysfs coresight mgmt reg access.
coresight: cti: Add sysfs access to program function regs
coresight: cti: Add sysfs trigger / channel programming API
devicetree: bindings: Documentation for CTI bindings.
coresight: cti: Add device tree support for v8 arch CTI
coresight: cti: Add device tree support for impdef CTI.
coresight: cti: Enable CTI associated with devices.
coresight: cti: Add connection information to sysfs
devicetree: bindings: Add header with CTI trigger signal type
constants.
drivers: dts: Add CTI options for qcom msm8916
drivers: dts: Juno platform - add CTI entries to device tree.
docs: coresight: Update documentation for CoreSight to cover CTI.
docs: sysfs: coresight: Add sysfs documentation for CTI
drivers: coresight: Add generic CoreSight cpu power notifications.
drivers: coresight: cti: Add CPU power event handling.
.../testing/sysfs-bus-coresight-devices-cti | 225 +++
.../bindings/arm/coresight-ect-cti.txt | 203 +++
.../devicetree/bindings/arm/coresight.txt | 7 +
Documentation/trace/coresight.txt | 139 ++
MAINTAINERS | 2 +
arch/arm64/boot/dts/arm/juno-base.dtsi | 149 +-
arch/arm64/boot/dts/arm/juno-cs-r1r2.dtsi | 31 +-
arch/arm64/boot/dts/arm/juno-r1.dts | 25 +
arch/arm64/boot/dts/arm/juno-r2.dts | 25 +
arch/arm64/boot/dts/arm/juno.dts | 25 +
arch/arm64/boot/dts/qcom/msm8916.dtsi | 85 +-
drivers/hwtracing/coresight/Kconfig | 13 +
drivers/hwtracing/coresight/Makefile | 4 +
.../coresight/coresight-cti-platform.c | 501 +++++++
.../hwtracing/coresight/coresight-cti-sysfs.c | 1240 +++++++++++++++++
drivers/hwtracing/coresight/coresight-cti.c | 835 +++++++++++
drivers/hwtracing/coresight/coresight-cti.h | 262 ++++
drivers/hwtracing/coresight/coresight-priv.h | 36 +
drivers/hwtracing/coresight/coresight.c | 232 ++-
include/dt-bindings/arm/coresight-cti-dt.h | 36 +
include/linux/coresight.h | 30 +
21 files changed, 4090 insertions(+), 15 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-bus-coresight-devices-cti
create mode 100644 Documentation/devicetree/bindings/arm/coresight-ect-cti.txt
create mode 100644 drivers/hwtracing/coresight/coresight-cti-platform.c
create mode 100644 drivers/hwtracing/coresight/coresight-cti-sysfs.c
create mode 100644 drivers/hwtracing/coresight/coresight-cti.c
create mode 100644 drivers/hwtracing/coresight/coresight-cti.h
create mode 100644 include/dt-bindings/arm/coresight-cti-dt.h
--
2.20.1
Arm and arm64 architecture reserve some memory regions prior to the
symbol '_stext' and these memory regions later will be used by device
module and BPF jit. The current code misses to consider these memory
regions thus any address in the regions will be taken as user space
mode, but perf cannot find the corresponding dso with the wrong CPU
mode so we misses to generate samples for device module and BPF
related trace data.
This patch parse the link scripts to get the memory size prior to start
address and reduce this size from 'etmq->etm->kernel_start', then can
get a fixed up kernel start address which contain memory regions for
device module and BPF. Finally, cs_etm__cpu_mode() can return right
mode for these memory regions and perf can successfully generate
samples.
The reason for parsing the link scripts is Arm architecture changes text
offset dependent on different platforms, which define multiple text
offsets in $kernel/arch/arm/Makefile. This offset is decided when build
kernel and the final value is extended in the link script, so we can
extract the used value from the link script. We use the same way to
parse arm64 link script as well. If fail to find the link script, the
pre start memory size is assumed as zero, in this case it has no any
change caused with this patch.
Below is detailed info for testing this patch:
- Build LLVM/Clang 8.0 or later version;
- Configure perf with ~/.perfconfig:
root@debian:~# cat ~/.perfconfig
# this file is auto-generated.
[llvm]
clang-path = /mnt/build/llvm-build/build/install/bin/clang
kbuild-dir = /mnt/linux-kernel/linux-cs-dev/
clang-opt = "-g"
dump-obj = true
[trace]
show_zeros = yes
show_duration = no
no_inherit = yes
show_timestamp = no
show_arg_names = no
args_alignment = 40
show_prefix = yes
- Run 'perf trace' command with eBPF event:
root@debian:~# perf trace -e string \
-e $kernel/tools/perf/examples/bpf/augmented_raw_syscalls.c
- Read eBPF program memory mapping in kernel:
root@debian:~# echo 1 > /proc/sys/net/core/bpf_jit_kallsyms
root@debian:~# cat /proc/kallsyms | grep -E "bpf_prog_.+_sys_[enter|exit]"
ffff000000086a84 t bpf_prog_f173133dc38ccf87_sys_enter [bpf]
ffff000000088618 t bpf_prog_c1bd85c092d6e4aa_sys_exit [bpf]
- Launch any program which accesses file system frequently so can hit
the system calls trace flow with eBPF event;
- Capture CoreSight trace data with filtering eBPF program:
root@debian:~# perf record -e cs_etm/(a)20070000.etr/ \
--filter 'filter 0xffff000000086a84/0x800' -a sleep 5s
- Annotate for symbol 'bpf_prog_f173133dc38ccf87_sys_enter':
root@debian:~# perf report
Then select 'branches' samples and press 'a' to annotate symbol
'bpf_prog_f173133dc38ccf87_sys_enter', press 'P' to print to the
bpf_prog_f173133dc38ccf87_sys_enter.annotation file:
root@debian:~# cat bpf_prog_f173133dc38ccf87_sys_enter.annotation
bpf_prog_f173133dc38ccf87_sys_enter() bpf_prog_f173133dc38ccf87_sys_enter
Event: branches
Percent int sys_enter(struct syscall_enter_args *args)
stp x29, x30, [sp, #-16]!
int key = 0;
mov x29, sp
augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key);
stp x19, x20, [sp, #-16]!
augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key);
stp x21, x22, [sp, #-16]!
stp x25, x26, [sp, #-16]!
return bpf_get_current_pid_tgid();
mov x25, sp
return bpf_get_current_pid_tgid();
mov x26, #0x0 // #0
sub sp, sp, #0x10
return bpf_map_lookup_elem(pids, &pid) != NULL;
add x19, x0, #0x0
mov x0, #0x0 // #0
mov x10, #0xfffffffffffffff8 // #-8
if (pid_filter__has(&pids_filtered, getpid()))
str w0, [x25, x10]
probe_read(&augmented_args->args, sizeof(augmented_args->args), args);
add x1, x25, #0x0
probe_read(&augmented_args->args, sizeof(augmented_args->args), args);
mov x10, #0xfffffffffffffff8 // #-8
syscall = bpf_map_lookup_elem(&syscalls, &augmented_args->args.syscall_nr);
add x1, x1, x10
syscall = bpf_map_lookup_elem(&syscalls, &augmented_args->args.syscall_nr);
mov x0, #0xffff8009ffffffff // #-140694538682369
movk x0, #0x6698, lsl #16
movk x0, #0x3e00
mov x10, #0xffffffffffff1040 // #-61376
if (syscall == NULL || !syscall->enabled)
movk x10, #0x1023, lsl #16
if (syscall == NULL || !syscall->enabled)
movk x10, #0x0, lsl #32
loop_iter_first()
3.69 → blr bpf_prog_f173133dc38ccf87_sys_enter
loop_iter_first()
add x7, x0, #0x0
loop_iter_first()
add x20, x7, #0x0
int size = probe_read_str(&augmented_filename->value, filename_len, filename_arg);
mov x0, #0x1 // #1
[...]
Cc: Mathieu Poirier <mathieu.poirier(a)linaro.org>
Cc: Alexander Shishkin <alexander.shishkin(a)linux.intel.com>
Cc: Jiri Olsa <jolsa(a)redhat.com>
Cc: Namhyung Kim <namhyung(a)kernel.org>
Cc: Peter Zijlstra <peterz(a)infradead.org>
Cc: Suzuki Poulouse <suzuki.poulose(a)arm.com>
Cc: coresight(a)lists.linaro.org
Cc: linux-arm-kernel(a)lists.infradead.org
Signed-off-by: Leo Yan <leo.yan(a)linaro.org>
---
tools/perf/Makefile.config | 22 ++++++++++++++++++++++
tools/perf/util/cs-etm.c | 19 ++++++++++++++++++-
2 files changed, 40 insertions(+), 1 deletion(-)
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 51dd00f65709..a58cd5a43a98 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -418,6 +418,28 @@ ifdef CORESIGHT
endif
LDFLAGS += $(LIBOPENCSD_LDFLAGS)
EXTLIBS += $(OPENCSDLIBS)
+ PRE_START_SIZE := 0
+ ifneq ($(wildcard $(srctree)/arch/$(SRCARCH)/kernel/vmlinux.lds),)
+ ifeq ($(SRCARCH),arm64)
+ # Extract info from lds:
+ # . = ((((((((0xffffffffffffffff)) - (((1)) << (48)) + 1) + (0)) + (0x08000000))) + (0x08000000))) + 0x00080000;
+ # PRE_START_SIZE := (0x08000000 + 0x08000000 + 0x00080000) = 0x10080000
+ PRE_START_SIZE := $(shell egrep ' \. \= \({8}0x[0-9a-fA-F]+\){2}' \
+ $(srctree)/arch/$(SRCARCH)/kernel/vmlinux.lds | \
+ sed -e 's/[(|)|.|=|+|<|;|-]//g' -e 's/ \+/ /g' -e 's/^[ \t]*//' | \
+ awk -F' ' '{printf "0x%x", $$6+$$7+$$8}' 2>/dev/null)
+ endif
+ ifeq ($(SRCARCH),arm)
+ # Extract info from lds:
+ # . = ((0xC0000000)) + 0x00208000;
+ # PRE_START_SIZE := 0x00208000
+ PRE_START_SIZE := $(shell egrep ' \. \= \({2}0x[0-9a-fA-F]+\){2}' \
+ $(srctree)/arch/$(SRCARCH)/kernel/vmlinux.lds | \
+ sed -e 's/[(|)|.|=|+|<|;|-]//g' -e 's/ \+/ /g' -e 's/^[ \t]*//' | \
+ awk -F' ' '{printf "0x%x", $$2}' 2>/dev/null)
+ endif
+ endif
+ CFLAGS += -DARM_PRE_START_SIZE=$(PRE_START_SIZE)
$(call detected,CONFIG_LIBOPENCSD)
ifdef CSTRACE_RAW
CFLAGS += -DCS_DEBUG_RAW
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 0c7776b51045..5fa0be3a3904 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -613,10 +613,27 @@ static void cs_etm__free(struct perf_session *session)
static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address)
{
struct machine *machine;
+ u64 fixup_kernel_start = 0;
machine = etmq->etm->machine;
- if (address >= etmq->etm->kernel_start) {
+ /*
+ * Since arm and arm64 specify some memory regions prior to
+ * 'kernel_start', kernel addresses can be less than 'kernel_start'.
+ *
+ * For arm architecture, the 16MB virtual memory space prior to
+ * 'kernel_start' is allocated to device modules, a PMD table if
+ * CONFIG_HIGHMEM is enabled and a PGD table.
+ *
+ * For arm64 architecture, the root PGD table, device module memory
+ * region and BPF jit region are prior to 'kernel_start'.
+ *
+ * To reflect the complete kernel address space, compensate these
+ * pre-defined regions for kernel start address.
+ */
+ fixup_kernel_start = etmq->etm->kernel_start - ARM_PRE_START_SIZE;
+
+ if (address >= fixup_kernel_start) {
if (machine__is_host(machine))
return PERF_RECORD_MISC_KERNEL;
else
--
2.17.1
Some hardware will ignore bit TRCPDCR.PU which is used to signal
to hardware that power should not be removed from the trace unit.
Let's mitigate against this by conditionally saving and restoring
the trace unit state when the CPU enters low power states.
This patchset introduces a firmware property named
'arm,coresight-needs-save-restore' - when this is present the
hardware state will be conditionally saved and restored.
A module parameter 'pm_save_enable' is also introduced which can
be configured to override the firmware property.
The hardware state is only ever saved and restored when the claim
tags indicate that self-hosted mode is in use.
Changes since v1:
- Rebased onto coresight/next
- Correcly pass bit number rather than BIT macro to coresight_timeout
- Abort saving state if a timeout occurs
- Fix completely broken pm_notify handling and unregister handler on error
- Use state_needs_restore to ensure state is restored only once
- Add module parameter description to existing boot_enable parameter
and use module_param instead of module_param_named
- Add firmware bindings for coresight-needs-save-restore
- Rename 'disable_pm_save' to 'pm_save_enable' which allows for
disabled, enabled or firmware
- Update comment on etm4_os_lock, it incorrectly indicated that
the code unlocks the trace registers
- Add comments to explain use of OS lock during save/restore
- Fix incorrect error description whilst waiting for PM stable
- Add WARN_ON_ONCE when cpu isn't as expected during save/restore
- Various updates to commit messages
Andrew Murray (5):
coresight: etm4x: remove superfluous setting of os_unlock
coresight: etm4x: use explicit barriers on enable/disable
coresight: etm4x: use module_param instead of module_param_named
coresight: etm4x: improve clarity of etm4_os_unlock comment
coresight: etm4x: save/restore state across CPU low power states
.../devicetree/bindings/arm/coresight.txt | 3 +
drivers/hwtracing/coresight/coresight-etm4x.c | 315 +++++++++++++++++-
drivers/hwtracing/coresight/coresight-etm4x.h | 66 ++++
drivers/hwtracing/coresight/coresight.c | 2 +-
include/linux/coresight.h | 8 +
5 files changed, 387 insertions(+), 7 deletions(-)
--
2.21.0
Hello,
I am trying to trace a statically linked application on my ZedBoard (Zynq-7000 SoC).
Please find attached the ELF file and the assembler file of the application.
For the context:
- The CPU0 runs at 333 MHz
- The TPIU runs at 200 MHz
- The PL (FPGA) runs at 250 MHz
For tracing the application, I use the attached script.sh file, which mainly:
- Disable the CPU1
- Setting up the address comparator
- Activate the Branch Broadcast mode
- Specify the address range to trace
- Activate the PTM and the TPIU
- Execute the application
- Retrieve the trace in a dedicated BRAM memory in the PL.
When I trace the whole .text section (from 0x100e0 to 0x15140)
I receive incomplete and inconsistent traces, for example:
00 9c 148d4 15d4c 10db4 13ecc b6fa3f44 14568 b6f85720 148d4 b6fa5d4c 13ecc b6fa3f44
14568 b6f85720 148d4 b6fa5d4c 147c0 b6f78030 14784 b6f6f3c8 13ecc b6f9df44 14704
b6f6f3c8 14784 b6f6f3c8 13d08 b6f9ea70 13d88 b6f9ea70 13c68 b6f99484 14628 b6f994b4
1485c b6fa0174 1452c b6faa2c4 14094 b6fabcb0 142b0 b6fab754 14784 b6f6f3c8 13ecc
b6f9df44 14784 b6f6f3c8 14784 b6f6f3c8 13d88 b6f9ea70 13d88 b6f9ea70 13c68 b6f99484
14628 b6f994b4 1485c b6fa0174 1452c b6faa2c4 14094 b6fabcb0 142b0
b6fab754 10104 10128 105d0 10390 136a0 00 00 00 00 00 00 00 00
Note that the addresses (10104 10128 105d0 10390 136a0) in bold above correspond to:
10104 _start ( entry point )
10128 _ start_c
105d0 __libc_start_main
10390 __init_libc
136a0 memset
1) How the entry point can end up at the end of the traces?
But when I trace a tiny interval of the .text section, for example from 0x100e0 to 0x136ac, I receive correct traces.
00 10104 10128 105d0 10390 136a0 10338 103c4 103c4 103c4 103c4 103c4 103c4 103c4 103c4 103c4
103c4 103c4 103c4 103e8 103e8 103e8 103e8 103e8 103e8 103e8 103e8 103e8 103e8 103e8 103e8
103e8 103e8 103e8 103e8 103e8 10420 10468 10480 10464 10464 10464 10464 10464 10480 10464
10464 10464 10464 10464 10480 10464 10464 10464 10464 10464 10464 10464 10464 10464 10464
10464 10464 10464 10464 10464 10464 10464 10464 10464 10464 10464 10464 10464 10464 10464
10464 10464 10464 10464 10464 10464 10464 10464 10464 10464 10464 10464 10464 10464 10488
138b4 10490 10388 10498 1048c 10404 1049c 10590 105f8 10598 100d4 100a4 10008 1fff0010 1fff009c
105bc 10214 1023c 10198 105c4 105fc 102c4 102a0 10300 1361c 13658 10310 10270 102b8 10330 10650
10698 10810 13318 108c8 108e4 108e0 108e0 108e0 108e0 108e0 108e0 108e0 108e0 108e0 108e0 10820
10810 10868 13318 108c8 108e4 10920 10968 10980 109c0 10a0c 10a68 10b20 10b34 10ba4 10ba0 10bec
10d20 13468 134e4 106ec 1070c 10810 13318 108c8 108e4 108e0 108e0 108e0 108e0 108e0 108e0 108e0
108e0 108e0 108e0 ………………
These addresses correspond to:
10104 _start
10128 _ start_c
105d0 __libc_start_main
10390 __init_libc
136a0 memset
10338
103c4 Loop in __init_libc
…..
103e8 Loop in __init_libc
….
102c4 main
…
2) Is there a limitation for the traced address range ? The only difference between those traces is the addr_range value:
For tracing the whole .text section :
echo -n 0x100e0 0x15140 > $PTM_CPU_0/addr_range
For tracing a tiny interval in the .text section
echo -n 0x100e0 0x136ac > $PTM_CPU_0/addr_range
If there is no limitation, what can explain this behaviour? A wrong configuration of the Coresight Components?
Kind Regards,
Mounir NASR ALLAH
Dear Mathieu,
I will like to clarify more on the `mode` file found in the mgmt of one of the ETM drivers.
The following is from the Documentations found in Documentation/ABI/testing/sysfs-bus-coresight-devices-etm4x
What: /sys/bus/coresight/devices/<memory_map>.etm/mode
Date: April 2015
KernelVersion: 4.01
Contact: Mathieu Poirier <mathieu.poirier(a)linaro.org>
Description: (RW) Controls various modes supported by this ETM, for example
P0 instruction tracing, branch broadcast, cycle counting and
context ID tracing.
I am asking about the functionality of this file because I want to be able to see how my traces will differ when i change the mode.
I have tweaked different values in mode and I realized that if the value != 0, it will not trace my program instruction addresses. I will only retrieve instruction addresses from kernel symbols (CPU_do_idle is found to be the specific instruction delivered by the CPU)
This is the snippet of the decoded trace using ptm2human ( I am also trying to figure if the decoder is indeed decoding the correct instructions from the trace dumps):
Context - Context ID = 0x0,
VMID = 0x0,
Address - Instruction address 0xffffff800895af78, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff8008161594, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff800898b3c0, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff800898b3c4, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff80081615c8, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff800895af80, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff800895b024, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff80081260e0, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff800855cbd0, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff800855cbf4, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff800855cbec, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff8008126104, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff800855cbd0, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff800855cbf4, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff800855cbec, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff800812611c, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff800895b030, Instruction set Aarch32 (Thumb)
Address - Instruction address 0xffffff800895b054, Instruction set Aarch32 (Thumb)
Exception - exception type IRQ, address 0xffffff800895b054
I will also upload the decoded trace dumps of the above (mode manipulated dump) in ed002000_mode.log
On another topic, I find it extremely amusing that I am able to trace my simple program. However,
according to the ETM options implemented, it should not be tracing any LDR/STR/conditional instructions yet
I have found the decoded traces to only be tracing LDR and STR. I have attached the source code of my math program and both the decoded (ec036000.etf.log) and the trace dump (ec036000.etf.bin). To make viewing of
the instructions better, please look at ec036000.etf_addr.log. A snippet of the decoded dump is found here:
Address - Instruction address 0x0000ffbefe7fc400, Instruction set Aarch32 (Thumb)
Address - Instruction address 0x0000005555555b9c, Instruction set Aarch32 (Thumb)
Address - Instruction address 0x0000005555555ba4, Instruction set Aarch32 (Thumb)
Address - Instruction address 0x0000005555555bac, Instruction set Aarch32 (Thumb)
Address - Instruction address 0x0000005555555bb4, Instruction set Aarch32 (Thumb)
Address - Instruction address 0x0000005555555bbc, Instruction set Aarch32 (Thumb)
Address - Instruction address 0x0000005555555bc4, Instruction set Aarch32 (Thumb)
Address - Instruction address 0x0000005555555bcc, Instruction set Aarch32 (Thumb)
Address - Instruction address 0x0000005555555bd4, Instruction set Aarch32 (Thumb)
Address - Instruction address 0x0000005555555bdc, Instruction set Aarch32 (Thumb)
Address - Instruction address 0x0000005555555be4, Instruction set Aarch32 (Thumb)
Address - Instruction address 0x0000005555555bec, Instruction set Aarch32 (Thumb)
Address - Instruction address 0x0000005555555bf4, Instruction set Aarch32 (Thumb)
Address - Instruction address 0x0000005555555bfc, Instruction set Aarch32 (Thumb)
Address - Instruction address 0x0000005555555c04, Instruction set Aarch32 (Thumb)
I am using gdb to compare the program instruction addresses against the trace instruction addresses.
I have also deactivated ASLR to ensure that the values are always comparable. A snippet
of the instructions of my program using gdb is attached below:
|0x5555555b9c <main+500> add x8, x8, x10
|0x5555555ba0 <main+504> ldr x8, [x8]
|0x5555555ba4 <main+508> ldr x10, [sp,#144]
|0x5555555ba8 <main+512> and x10, x10, x13
|0x5555555bac <main+516> lsl x10, x12, x10
|0x5555555bb0 <main+520> and x8, x8, x10
|0x5555555bb4 <main+524> cmp x8, x9
|0x5555555bb8 <main+528> cset w15, ne
|0x5555555bbc <main+532> orr w16, wzr, #0x1
|0x5555555bc0 <main+536> and w15, w15, w16
|0x5555555bc4 <main+540> str w15, [sp,#20]
|0x5555555bc8 <main+544> b 0x5555555bd4 <main+556>
|0x5555555bcc <main+548> mov w8, #0x0 // #0
|0x5555555bd0 <main+552> str w8, [sp,#20]
|0x5555555bd4 <main+556> ldr w8, [sp,#20]
|0x5555555bd8 <main+560> str w8, [sp,#140]
|0x5555555bdc <main+564> ldr w8, [sp,#140]
|0x5555555be0 <main+568> cbnz w8, 0x5555555be8 <main+576>
|0x5555555be4 <main+572> b 0x5555555c80 <main+728>
|0x5555555be8 <main+576> orr x0, xzr, #0x10
|0x5555555bec <main+580> orr w3, wzr, #0x4
|0x5555555bf0 <main+584> ldur w2, [x29,#-40]
|0x5555555bf4 <main+588> ldr x8, [sp,#80]
|0x5555555bf8 <main+592> str x0, [sp,#8]
|0x5555555bfc <main+596> mov x0, x8
|0x5555555c00 <main+600> ldr x1, [sp,#72]
|0x5555555c04 <main+604> bl 0x55555558d0 <fprintf@plt>
The following are the trcidr values of my ETM:
trcidr0: 0x28000ea1
trcidr1: 0x4100f404
trcidr2: 0x488
trcidr3: 0xd7b00004
trcidr4: 0x11170004
trcidr5: 0x28c7081e
trcidr8: 0x0
trcidr9: 0x0
trcidr10: 0x0
trcidr11: 0x0
trcidr12: 0x0
trcidr13: 0x0
Hope I have provided sufficient information. Please advise!
Yours Sincerely,
Jeremy
This email may contain confidential and/or proprietary information that is exempt from disclosure under applicable law and is intended for receipt and use solely by the addressee(s) named above. If you are not the intended recipient, you are notified that any use, dissemination, distribution, or copying of this email, or any attachment, is strictly prohibited. Please delete the email immediately and inform the sender. Thank You
The above message may contain confidential and/or proprietary information that is exempt from disclosure under applicable law and is intended for receipt and use solely by the addressee(s) named above. If you are not the intended recipient, you are hereby notified that any use, dissemination, distribution, or copying of this message, or any attachment, is strictly prohibited. If you have received this email in error, please inform the sender immediately by reply e-mail or telephone, reversing the charge if necessary. Please delete the message thereafter. Thank you.
From: Wojciech Zmuda <wzmuda(a)n7space.com>
This patchset adds time notion to perf instruction and branch samples to allow
coarse time measurement of code blocks execution.
The simplest verification is visibility of the time field in 'perf script' output:
root@zynq:~# perf record -e cs_etm/timestamp,(a)fe970000.etr/u -a sleep 1
Couldn't synthesize bpf events.
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.262 MB perf.data ]
root@zynq:~# perf script --ns -F cpu,comm,time
perf [002] 9546.053455325:
perf [002] 9546.053455340:
perf [002] 9546.053455344:
(...)
sleep [003] 9546.060163742:
sleep [003] 9546.060163754:
sleep [003] 9546.060163766:
(...)
ntpd [001] 9546.389083194:
ntpd [001] 9546.389083400:
ntpd [001] 9546.389086319:
(...)
The step above works only if trace has been collected in CPU-wide mode because of some
perf event flags mismatch I'm working on fixing.
In general, timestamps in subsequent samples are monotonically increasing. Exceptions are:
- discontinuities in trace. From my understanding, we can't timestamp discontinuities
reasonably, since after decoder synchronizes back after trace loss, it needs to wait for
another timestamp packet. Thus, time value of such samples stays at 0x0.
- cases when a lot of non-branching instructions is executed between two subsequent timestamps.
Since we use approximation of timestamps for subsequent samples by increasing the timestamp
value by instruction count, it is possible that we go past the value of the next hardware
timestamp.
Another way to access these values is to use the perf script engine, which I used for validation
of the feature. The script below calculates timestamp differences of two consecutive branches
sharing the same branch address. This is a simple example of execution time fluctuation detector.
from __future__ import print_function
import os
import sys
sys.path.append(os.environ['PERF_EXEC_PATH'] + \
'/scripts/python/Perf-Trace-Util/lib/Perf/Trace')
from perf_trace_context import *
target_start_addr = int('4005e4', 16) # 0x4005e4 is func() from listing below
branch = dict()
branch['from'] = 0
branches = []
def process_event(s):
global branch
global branches
sample = s['sample']
branch['cpu'] = sample['cpu']
if not branch['from']:
branch['from'] = sample['addr']
branch['ts'] = sample['time']
return
branch['to'] = sample['ip']
if not branch['to']:
branch['from'] = 0
branch['ts'] = 0
return
if branch['from'] and branch['to']:
branches.append(branch.copy())
branch['from'] = 0
return
def trace_end():
global branches
count = 0
timestamp_start = 0
print("Got {0} samples:".format(len(branches)))
for b in branches:
if b['from'] == target_start_addr:
if not timestamp_start:
timestamp_start = b['ts']
continue
print("[{0}]: ts diff = 0x{1:x} - 0x{2:x} = {3:d}".format(count,
b['ts'], timestamp_start, b['ts'] - timestamp_start))
count = count + 1
timestamp_start = b['ts']
The following function was traced:
static int func(int cnt)
{
volatile int x = 0;
static int i;
x += cnt + 0xdeadbeefcafeb00b;
(...) /* repeats ~100 times */
if (i++ % 3 == 0) // Every third execution is longer
usleep(1000);
return x;
}
root@zynq:~# perf record -m,16K -e cs_etm/timestamp,(a)fe970000.etr/u \
--filter 'filter func @./program \
--per-thread ./program
Couldn't synthesize bpf events.
CTRL+C me when you find appropriate.
^C[ perf record: Woken up 12 times to write data ]
[ perf record: Captured and wrote 0.135 MB perf.data ]
root@zynq:~# perf script -s exectime.py
Got 2469 samples:
[0]: ts diff = 0x92f2752e512 - 0x92f274a7ae9 = 551465
[1]: ts diff = 0x92f2752e694 - 0x92f2752e512 = 386
[2]: ts diff = 0x92f2752e817 - 0x92f2752e694 = 387
[3]: ts diff = 0x92f275bef12 - 0x92f2752e817 = 591611
[4]: ts diff = 0x92f275bf093 - 0x92f275bef12 = 385
[5]: ts diff = 0x92f275bf211 - 0x92f275bf093 = 382
[6]: ts diff = 0x92f276451d7 - 0x92f275bf211 = 548806
[7]: ts diff = 0x92f2764535a - 0x92f276451d7 = 387
[8]: ts diff = 0x92f276454d7 - 0x92f2764535a = 381
[9]: ts diff = 0x92f276cb256 - 0x92f276454d7 = 548223
[10]: ts diff = 0x92f276cb3d9 - 0x92f276cb256 = 387
[11]: ts diff = 0x92f276cb556 - 0x92f276cb3d9 = 381
(...)
At the listing above it is visible that every third execution of the function lasted longer
than the other two. It is a naive example and could be enhanced to point to the area that
caused the disruption by examining events 'in the middle' of the traced code range.
Applies cleanly on Mathieu's 5.1-rc3-cpu-wide-v3 branch.
Changes for V3:
- fix checkpatch warnings
- don't timestamp discontinuity packets with hardware timestamp, as it is
for range packets only
- fix timestamping packets on full queue in per-thread mode
- simplify code in timestamping last branch samples before discontinuity
and in timestamping pending packets
Changes for V2:
- move packet timestamping logic to decoder. Front end only uses this information
to timestamp samples (as suggested by Mathieu).
- leave original behaviour of CPU-wide mode, where decoder is stopped
and front end is triggered about pending queue with timestamp packet.
At the same time, always adjust next and current timestamp in both CPU-wide
and per-thread modes (as suggested by Mathieu).
- when timestamp packet is encountered, timestamp range and discontinuity packets
waiting in the queue, that are not yet consumed by the front end (as suggested by Mathieu).
- don't timestamp exceptions, since they are not turned into branch nor instruction
samples.
- fix timestamping of the last branch sample before discontinuity appears (as suggested by Leo).
Wojciech Zmuda (1):
perf cs-etm: Set time value for samples
tools/perf/util/cs-etm-decoder/cs-etm-decoder.c | 70 ++++++++++++++++++-------
tools/perf/util/cs-etm.c | 3 ++
tools/perf/util/cs-etm.h | 1 +
3 files changed, 55 insertions(+), 19 deletions(-)
--
2.11.0
Arm and arm64 architecture reserve some memory regions prior to the
symbol '_stext' and these memory regions later will be used by device
module and BPF jit. The current code misses to consider these memory
regions thus any address in the regions will be taken as user space
mode, but perf cannot find the corresponding dso with the wrong CPU
mode so we misses to generate samples for device module and BPF
related trace data.
This patch parse the link scripts to get the memory size prior to start
address and reduce this size from 'etmq->etm->kernel_start', then can
get a fixed up kernel start address which contain memory regions for
device module and BPF. Finally, cs_etm__cpu_mode() can return right
mode for these memory regions and perf can successfully generate
samples.
The reason for parsing the link scripts is Arm architecture changes text
offset dependent on different platforms, which define multiple text
offsets in $kernel/arch/arm/Makefile. This offset is decided when build
kernel and the final value is extended in the link script, so we can
extract the used value from the link script. We use the same way to
parse arm64 link script as well. If fail to find the link script, the
pre start memory size is assumed as zero, in this case it has no any
change caused with this patch.
Below is detailed info for testing this patch:
- Build LLVM/Clang 8.0 or later version;
- Configure perf with ~/.perfconfig:
root@debian:~# cat ~/.perfconfig
# this file is auto-generated.
[llvm]
clang-path = /mnt/build/llvm-build/build/install/bin/clang
kbuild-dir = /mnt/linux-kernel/linux-cs-dev/
clang-opt = "-DLINUX_VERSION_CODE=0x50200 -g"
dump-obj = true
[trace]
show_zeros = yes
show_duration = no
no_inherit = yes
show_timestamp = no
show_arg_names = no
args_alignment = 40
show_prefix = yes
- Run 'perf trace' command with eBPF event:
root@debian:~# perf trace -e string \
-e $kernel/tools/perf/examples/bpf/augmented_raw_syscalls.c
- Read eBPF program memory mapping in kernel:
root@debian:~# echo 1 > /proc/sys/net/core/bpf_jit_kallsyms
root@debian:~# cat /proc/kallsyms | grep -E "bpf_prog_.+_sys_[enter|exit]"
ffff000000086a84 t bpf_prog_f173133dc38ccf87_sys_enter [bpf]
ffff000000088618 t bpf_prog_c1bd85c092d6e4aa_sys_exit [bpf]
- Launch any program which accesses file system frequently so can hit
the system calls trace flow with eBPF event;
- Capture CoreSight trace data with filtering eBPF program:
root@debian:~# perf record -e cs_etm/(a)20070000.etr/ \
--filter 'filter 0xffff000000086a84/0x800' -a sleep 5s
- Annotate for symbol 'bpf_prog_f173133dc38ccf87_sys_enter':
root@debian:~# perf report
Then select 'branches' samples and press 'a' to annotate symbol
'bpf_prog_f173133dc38ccf87_sys_enter', press 'P' to print to the
bpf_prog_f173133dc38ccf87_sys_enter.annotation file:
root@debian:~# cat bpf_prog_f173133dc38ccf87_sys_enter.annotation
bpf_prog_f173133dc38ccf87_sys_enter() bpf_prog_f173133dc38ccf87_sys_enter
Event: branches
Percent int sys_enter(struct syscall_enter_args *args)
stp x29, x30, [sp, #-16]!
int key = 0;
mov x29, sp
augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key);
stp x19, x20, [sp, #-16]!
augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key);
stp x21, x22, [sp, #-16]!
stp x25, x26, [sp, #-16]!
return bpf_get_current_pid_tgid();
mov x25, sp
return bpf_get_current_pid_tgid();
mov x26, #0x0 // #0
sub sp, sp, #0x10
return bpf_map_lookup_elem(pids, &pid) != NULL;
add x19, x0, #0x0
mov x0, #0x0 // #0
mov x10, #0xfffffffffffffff8 // #-8
if (pid_filter__has(&pids_filtered, getpid()))
str w0, [x25, x10]
probe_read(&augmented_args->args, sizeof(augmented_args->args), args);
add x1, x25, #0x0
probe_read(&augmented_args->args, sizeof(augmented_args->args), args);
mov x10, #0xfffffffffffffff8 // #-8
syscall = bpf_map_lookup_elem(&syscalls, &augmented_args->args.syscall_nr);
add x1, x1, x10
syscall = bpf_map_lookup_elem(&syscalls, &augmented_args->args.syscall_nr);
mov x0, #0xffff8009ffffffff // #-140694538682369
movk x0, #0x6698, lsl #16
movk x0, #0x3e00
mov x10, #0xffffffffffff1040 // #-61376
if (syscall == NULL || !syscall->enabled)
movk x10, #0x1023, lsl #16
if (syscall == NULL || !syscall->enabled)
movk x10, #0x0, lsl #32
loop_iter_first()
3.69 → blr bpf_prog_f173133dc38ccf87_sys_enter
loop_iter_first()
add x7, x0, #0x0
loop_iter_first()
add x20, x7, #0x0
int size = probe_read_str(&augmented_filename->value, filename_len, filename_arg);
mov x0, #0x1 // #1
[...]
Cc: Mathieu Poirier <mathieu.poirier(a)linaro.org>
Cc: Alexander Shishkin <alexander.shishkin(a)linux.intel.com>
Cc: Jiri Olsa <jolsa(a)redhat.com>
Cc: Namhyung Kim <namhyung(a)kernel.org>
Cc: Peter Zijlstra <peterz(a)infradead.org>
Cc: Suzuki Poulouse <suzuki.poulose(a)arm.com>
Cc: coresight(a)lists.linaro.org
Cc: linux-arm-kernel(a)lists.infradead.org
Signed-off-by: Leo Yan <leo.yan(a)linaro.org>
---
tools/perf/Makefile.config | 24 ++++++++++++++++++++++++
tools/perf/util/cs-etm.c | 26 +++++++++++++++++++++++++-
2 files changed, 49 insertions(+), 1 deletion(-)
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 51dd00f65709..4776c2c1fb6d 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -418,6 +418,30 @@ ifdef CORESIGHT
endif
LDFLAGS += $(LIBOPENCSD_LDFLAGS)
EXTLIBS += $(OPENCSDLIBS)
+ ifneq ($(wildcard $(srctree)/arch/arm64/kernel/vmlinux.lds),)
+ # Extract info from lds:
+ # . = ((((((((0xffffffffffffffff)) - (((1)) << (48)) + 1) + (0)) + (0x08000000))) + (0x08000000))) + 0x00080000;
+ # ARM64_PRE_START_SIZE := (0x08000000 + 0x08000000 + 0x00080000)
+ ARM64_PRE_START_SIZE := $(shell egrep ' \. \= \({8}0x[0-9a-fA-F]+\){2}' \
+ $(srctree)/arch/arm64/kernel/vmlinux.lds | \
+ sed -e 's/[(|)|.|=|+|<|;|-]//g' -e 's/ \+/ /g' -e 's/^[ \t]*//' | \
+ awk -F' ' '{print "("$$6 "+" $$7 "+" $$8")"}' 2>/dev/null)
+ else
+ ARM64_PRE_START_SIZE := 0
+ endif
+ CFLAGS += -DARM64_PRE_START_SIZE="$(ARM64_PRE_START_SIZE)"
+ ifneq ($(wildcard $(srctree)/arch/arm/kernel/vmlinux.lds),)
+ # Extract info from lds:
+ # . = ((0xC0000000)) + 0x00208000;
+ # ARM_PRE_START_SIZE := 0x00208000
+ ARM_PRE_START_SIZE := $(shell egrep ' \. \= \({2}0x[0-9a-fA-F]+\){2}' \
+ $(srctree)/arch/arm/kernel/vmlinux.lds | \
+ sed -e 's/[(|)|.|=|+|<|;|-]//g' -e 's/ \+/ /g' -e 's/^[ \t]*//' | \
+ awk -F' ' '{print "("$$2")"}' 2>/dev/null)
+ else
+ ARM_PRE_START_SIZE := 0
+ endif
+ CFLAGS += -DARM_PRE_START_SIZE="$(ARM_PRE_START_SIZE)"
$(call detected,CONFIG_LIBOPENCSD)
ifdef CSTRACE_RAW
CFLAGS += -DCS_DEBUG_RAW
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 0c7776b51045..ae831f836c70 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -613,10 +613,34 @@ static void cs_etm__free(struct perf_session *session)
static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address)
{
struct machine *machine;
+ u64 fixup_kernel_start = 0;
+ const char *arch;
machine = etmq->etm->machine;
+ arch = perf_env__arch(machine->env);
- if (address >= etmq->etm->kernel_start) {
+ /*
+ * Since arm and arm64 specify some memory regions prior to
+ * 'kernel_start', kernel addresses can be less than 'kernel_start'.
+ *
+ * For arm architecture, the 16MB virtual memory space prior to
+ * 'kernel_start' is allocated to device modules, a PMD table if
+ * CONFIG_HIGHMEM is enabled and a PGD table.
+ *
+ * For arm64 architecture, the root PGD table, device module memory
+ * region and BPF jit region are prior to 'kernel_start'.
+ *
+ * To reflect the complete kernel address space, compensate these
+ * pre-defined regions for kernel start address.
+ */
+ if (!strcmp(arch, "arm64"))
+ fixup_kernel_start = etmq->etm->kernel_start -
+ ARM64_PRE_START_SIZE;
+ else if (!strcmp(arch, "arm"))
+ fixup_kernel_start = etmq->etm->kernel_start -
+ ARM_PRE_START_SIZE;
+
+ if (address >= fixup_kernel_start) {
if (machine__is_host(machine))
return PERF_RECORD_MISC_KERNEL;
else
--
2.17.1
Arm and arm64 architecture reserve some memory regions prior to the
symbol '_stext' and these memory regions later will be used by device
module and BPF jit. The current code misses to consider these memory
regions thus any address in the regions will be taken as user space
mode, but perf cannot find the corresponding dso with the wrong CPU
mode so we misses to generate samples for device module and BPF
related trace data.
This patch parse the link scripts to get the memory size prior to start
address and reduce this size from 'etmq->etm->kernel_start', then can
get a fixed up kernel start address which contain memory regions for
device module and BPF. Finally, cs_etm__cpu_mode() can return right
mode for these memory regions and perf can successfully generate
samples.
The reason for parsing the link scripts is Arm architecture changes text
offset dependent on different platforms, which define multiple text
offsets in $kernel/arch/arm/Makefile. This offset is decided when build
kernel and the final value is extended in the link script, so we can
extract the used value from the link script. We use the same way to
parse arm64 link script as well. If fail to find the link script, the
pre start memory size is assumed as zero, in this case it has no any
change caused with this patch.
Below is detailed info for testing this patch:
- Build LLVM/Clang 8.0 or later version;
- Configure perf with ~/.perfconfig:
root@debian:~# cat ~/.perfconfig
# this file is auto-generated.
[llvm]
clang-path = /mnt/build/llvm-build/build/install/bin/clang
kbuild-dir = /mnt/linux-kernel/linux-cs-dev/
clang-opt = "-g"
dump-obj = true
[trace]
show_zeros = yes
show_duration = no
no_inherit = yes
show_timestamp = no
show_arg_names = no
args_alignment = 40
show_prefix = yes
- Run 'perf trace' command with eBPF event:
root@debian:~# perf trace -e string \
-e $kernel/tools/perf/examples/bpf/augmented_raw_syscalls.c
- Read eBPF program memory mapping in kernel:
root@debian:~# echo 1 > /proc/sys/net/core/bpf_jit_kallsyms
root@debian:~# cat /proc/kallsyms | grep -E "bpf_prog_.+_sys_[enter|exit]"
ffff000000086a84 t bpf_prog_f173133dc38ccf87_sys_enter [bpf]
ffff000000088618 t bpf_prog_c1bd85c092d6e4aa_sys_exit [bpf]
- Launch any program which accesses file system frequently so can hit
the system calls trace flow with eBPF event;
- Capture CoreSight trace data with filtering eBPF program:
root@debian:~# perf record -e cs_etm/(a)20070000.etr/ \
--filter 'filter 0xffff000000086a84/0x800' -a sleep 5s
- Annotate for symbol 'bpf_prog_f173133dc38ccf87_sys_enter':
root@debian:~# perf report
Then select 'branches' samples and press 'a' to annotate symbol
'bpf_prog_f173133dc38ccf87_sys_enter', press 'P' to print to the
bpf_prog_f173133dc38ccf87_sys_enter.annotation file:
root@debian:~# cat bpf_prog_f173133dc38ccf87_sys_enter.annotation
bpf_prog_f173133dc38ccf87_sys_enter() bpf_prog_f173133dc38ccf87_sys_enter
Event: branches
Percent int sys_enter(struct syscall_enter_args *args)
stp x29, x30, [sp, #-16]!
int key = 0;
mov x29, sp
augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key);
stp x19, x20, [sp, #-16]!
augmented_args = bpf_map_lookup_elem(&augmented_filename_map, &key);
stp x21, x22, [sp, #-16]!
stp x25, x26, [sp, #-16]!
return bpf_get_current_pid_tgid();
mov x25, sp
return bpf_get_current_pid_tgid();
mov x26, #0x0 // #0
sub sp, sp, #0x10
return bpf_map_lookup_elem(pids, &pid) != NULL;
add x19, x0, #0x0
mov x0, #0x0 // #0
mov x10, #0xfffffffffffffff8 // #-8
if (pid_filter__has(&pids_filtered, getpid()))
str w0, [x25, x10]
probe_read(&augmented_args->args, sizeof(augmented_args->args), args);
add x1, x25, #0x0
probe_read(&augmented_args->args, sizeof(augmented_args->args), args);
mov x10, #0xfffffffffffffff8 // #-8
syscall = bpf_map_lookup_elem(&syscalls, &augmented_args->args.syscall_nr);
add x1, x1, x10
syscall = bpf_map_lookup_elem(&syscalls, &augmented_args->args.syscall_nr);
mov x0, #0xffff8009ffffffff // #-140694538682369
movk x0, #0x6698, lsl #16
movk x0, #0x3e00
mov x10, #0xffffffffffff1040 // #-61376
if (syscall == NULL || !syscall->enabled)
movk x10, #0x1023, lsl #16
if (syscall == NULL || !syscall->enabled)
movk x10, #0x0, lsl #32
loop_iter_first()
3.69 → blr bpf_prog_f173133dc38ccf87_sys_enter
loop_iter_first()
add x7, x0, #0x0
loop_iter_first()
add x20, x7, #0x0
int size = probe_read_str(&augmented_filename->value, filename_len, filename_arg);
mov x0, #0x1 // #1
[...]
Cc: Mathieu Poirier <mathieu.poirier(a)linaro.org>
Cc: Alexander Shishkin <alexander.shishkin(a)linux.intel.com>
Cc: Jiri Olsa <jolsa(a)redhat.com>
Cc: Namhyung Kim <namhyung(a)kernel.org>
Cc: Peter Zijlstra <peterz(a)infradead.org>
Cc: Suzuki Poulouse <suzuki.poulose(a)arm.com>
Cc: coresight(a)lists.linaro.org
Cc: linux-arm-kernel(a)lists.infradead.org
Signed-off-by: Leo Yan <leo.yan(a)linaro.org>
---
tools/perf/Makefile.config | 20 ++++++++++++++++++++
tools/perf/util/cs-etm.c | 19 ++++++++++++++++++-
2 files changed, 38 insertions(+), 1 deletion(-)
diff --git a/tools/perf/Makefile.config b/tools/perf/Makefile.config
index 51dd00f65709..cf5906d667aa 100644
--- a/tools/perf/Makefile.config
+++ b/tools/perf/Makefile.config
@@ -418,6 +418,26 @@ ifdef CORESIGHT
endif
LDFLAGS += $(LIBOPENCSD_LDFLAGS)
EXTLIBS += $(OPENCSDLIBS)
+ ARM_PRE_START_SIZE := 0
+ ifeq ($(SRCARCH),arm64)
+ # Extract info from lds:
+ # . = ((((((((0xffffffffffffffff)) - (((1)) << (48)) + 1) + (0)) + (0x08000000))) + (0x08000000))) + 0x00080000;
+ # ARM_PRE_START_SIZE := (0x08000000 + 0x08000000 + 0x00080000)
+ ARM_PRE_START_SIZE := $(shell egrep ' \. \= \({8}0x[0-9a-fA-F]+\){2}' \
+ $(srctree)/arch/arm64/kernel/vmlinux.lds | \
+ sed -e 's/[(|)|.|=|+|<|;|-]//g' -e 's/ \+/ /g' -e 's/^[ \t]*//' | \
+ awk -F' ' '{print "("$$6 "+" $$7 "+" $$8")"}' 2>/dev/null)
+ endif
+ ifeq ($(SRCARCH),arm)
+ # Extract info from lds:
+ # . = ((0xC0000000)) + 0x00208000;
+ # ARM_PRE_START_SIZE := 0x00208000
+ ARM_PRE_START_SIZE := $(shell egrep ' \. \= \({2}0x[0-9a-fA-F]+\){2}' \
+ $(srctree)/arch/arm/kernel/vmlinux.lds | \
+ sed -e 's/[(|)|.|=|+|<|;|-]//g' -e 's/ \+/ /g' -e 's/^[ \t]*//' | \
+ awk -F' ' '{print "("$$2")"}' 2>/dev/null)
+ endif
+ CFLAGS += -DARM_PRE_START_SIZE="$(ARM_PRE_START_SIZE)"
$(call detected,CONFIG_LIBOPENCSD)
ifdef CSTRACE_RAW
CFLAGS += -DCS_DEBUG_RAW
diff --git a/tools/perf/util/cs-etm.c b/tools/perf/util/cs-etm.c
index 0c7776b51045..5fa0be3a3904 100644
--- a/tools/perf/util/cs-etm.c
+++ b/tools/perf/util/cs-etm.c
@@ -613,10 +613,27 @@ static void cs_etm__free(struct perf_session *session)
static u8 cs_etm__cpu_mode(struct cs_etm_queue *etmq, u64 address)
{
struct machine *machine;
+ u64 fixup_kernel_start = 0;
machine = etmq->etm->machine;
- if (address >= etmq->etm->kernel_start) {
+ /*
+ * Since arm and arm64 specify some memory regions prior to
+ * 'kernel_start', kernel addresses can be less than 'kernel_start'.
+ *
+ * For arm architecture, the 16MB virtual memory space prior to
+ * 'kernel_start' is allocated to device modules, a PMD table if
+ * CONFIG_HIGHMEM is enabled and a PGD table.
+ *
+ * For arm64 architecture, the root PGD table, device module memory
+ * region and BPF jit region are prior to 'kernel_start'.
+ *
+ * To reflect the complete kernel address space, compensate these
+ * pre-defined regions for kernel start address.
+ */
+ fixup_kernel_start = etmq->etm->kernel_start - ARM_PRE_START_SIZE;
+
+ if (address >= fixup_kernel_start) {
if (machine__is_host(machine))
return PERF_RECORD_MISC_KERNEL;
else
--
2.17.1
Based on the following report from Smatch tool, make sure we have a
valid drvdata before we dereference it to find the real dev.
The patch 21d26b905c05: "coresight: etm: Clean up device specific
data" from May 22, 2019, leads to the following Smatch complaint:
./drivers/hwtracing/coresight/coresight-etm3x.c:460 etm_get_trace_id()
warn: variable dereferenced before check 'drvdata' (see line 458)
./drivers/hwtracing/coresight/coresight-etm3x.c
457 int trace_id = -1;
458 struct device *etm_dev = drvdata->csdev->dev.parent;
^^^^^^^^^
New dereference
459
460 if (!drvdata)
^^^^^^^^
Checked too late. Delete the check?
461 goto out;
462
Cc: Mathieu Poirier <mathieu.poirier(a)linaro.org>
Cc: Dan Carpenter <dan.carpenter(a)oracle.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose(a)arm.com>
---
drivers/hwtracing/coresight/coresight-etm3x.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c
index bed7291..225c298 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x.c
@@ -455,11 +455,12 @@ int etm_get_trace_id(struct etm_drvdata *drvdata)
{
unsigned long flags;
int trace_id = -1;
- struct device *etm_dev = drvdata->csdev->dev.parent;
+ struct device *etm_dev;
if (!drvdata)
goto out;
+ etm_dev = drvdata->csdev->dev.parent;
if (!local_read(&drvdata->mode))
return drvdata->traceid;
--
2.7.4