Skip to content

Commit 6414239

Browse files
authored
[SystemZ][XRay] Reland XRay runtime support for SystemZ (llvm#124611)
Adds the runtime support routines for XRay on SystemZ. Only function entry/exit is implemented. The original PR 113252 was reverted due to errors caused by adding DSO support to XRay. This PR is the original implementation with the changed function signatures. I'll add an implementation with DSO support later.
1 parent b9207ae commit 6414239

File tree

7 files changed

+318
-1
lines changed

7 files changed

+318
-1
lines changed

compiler-rt/cmake/Modules/AllSupportedArchDefs.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ if(APPLE)
103103
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM64})
104104
else()
105105
set(ALL_XRAY_SUPPORTED_ARCH ${X86_64} ${ARM32} ${ARM64} ${MIPS32} ${MIPS64}
106-
powerpc64le ${HEXAGON} ${LOONGARCH64} ${RISCV32} ${RISCV64})
106+
powerpc64le ${HEXAGON} ${LOONGARCH64} ${RISCV32} ${RISCV64} ${S390X})
107107
endif()
108108
set(ALL_XRAY_DSO_SUPPORTED_ARCH ${X86_64} ${ARM64})
109109
set(ALL_SHADOWCALLSTACK_SUPPORTED_ARCH ${ARM64})

compiler-rt/lib/xray/CMakeLists.txt

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,13 @@ set(riscv64_SOURCES
106106
xray_trampoline_riscv64.S
107107
)
108108

109+
set(s390x_SOURCES
110+
xray_s390x.cpp
111+
xray_trampoline_s390x.S
112+
)
113+
# Enable vector instructions in the assembly file.
114+
set_source_files_properties(xray_trampoline_s390x.S PROPERTIES COMPILE_FLAGS -mvx)
115+
109116
set(XRAY_SOURCE_ARCHS
110117
arm
111118
armhf
@@ -116,6 +123,7 @@ set(XRAY_SOURCE_ARCHS
116123
mips64
117124
mips64el
118125
powerpc64le
126+
s390x
119127
x86_64
120128
)
121129

@@ -168,6 +176,7 @@ set(XRAY_ALL_SOURCE_FILES
168176
${powerpc64le_SOURCES}
169177
${riscv32_SOURCES}
170178
${riscv64_SOURCES}
179+
${s390x_SOURCES}
171180
${XRAY_IMPL_HEADERS}
172181
)
173182
list(REMOVE_DUPLICATES XRAY_ALL_SOURCE_FILES)

compiler-rt/lib/xray/xray_interface.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ static const int16_t cSledLength = 20;
6161
static const int16_t cSledLength = 68;
6262
#elif defined(__riscv) && (__riscv_xlen == 32)
6363
static const int16_t cSledLength = 52;
64+
#elif defined(__s390x__)
65+
static const int16_t cSledLength = 18;
6466
#else
6567
#error "Unsupported CPU Architecture"
6668
#endif /* CPU architecture */

compiler-rt/lib/xray/xray_interface_internal.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ extern void __xray_FunctionTailExit();
2929
extern void __xray_ArgLoggerEntry();
3030
extern void __xray_CustomEvent();
3131
extern void __xray_TypedEvent();
32+
#if defined(__s390x__)
33+
extern void __xray_FunctionEntryVec();
34+
extern void __xray_FunctionExitVec();
35+
#endif
3236
}
3337

3438
extern "C" {

compiler-rt/lib/xray/xray_s390x.cpp

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
//===-- xray_s390x.cpp ------------------------------------------*- C++ -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file is a part of XRay, a dynamic runtime instrumentation system.
10+
//
11+
// Implementation of s390x routines.
12+
//
13+
//===----------------------------------------------------------------------===//
14+
#include "sanitizer_common/sanitizer_common.h"
15+
#include "xray_defs.h"
16+
#include "xray_interface_internal.h"
17+
#include <cassert>
18+
#include <cstring>
19+
20+
bool __xray::patchFunctionEntry(const bool Enable, const uint32_t FuncId,
21+
const XRaySledEntry &Sled,
22+
const XRayTrampolines &Trampolines,
23+
bool LogArgs) XRAY_NEVER_INSTRUMENT {
24+
uint32_t *Address = reinterpret_cast<uint32_t *>(Sled.address());
25+
// TODO: Trampoline addresses are currently inserted at compile-time, using
26+
// __xray_FunctionEntry and __xray_FunctionExit only.
27+
// To support DSO instrumentation, trampolines have to be written during
28+
// patching (see implementation on X86_64, e.g.).
29+
if (Enable) {
30+
// The resulting code is:
31+
// stmg %r2, %r15, 16(%r15)
32+
// llilf %2, FuncID
33+
// brasl %r14, __xray_FunctionEntry@GOT
34+
// The FuncId and the stmg instruction must be written.
35+
36+
// Write FuncId into llilf.
37+
Address[2] = FuncId;
38+
// Write last part of stmg.
39+
reinterpret_cast<uint16_t *>(Address)[2] = 0x24;
40+
// Write first part of stmg.
41+
Address[0] = 0xeb2ff010;
42+
} else {
43+
// j +16 instructions.
44+
Address[0] = 0xa7f4000b;
45+
}
46+
return true;
47+
}
48+
49+
bool __xray::patchFunctionExit(
50+
const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled,
51+
const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT {
52+
uint32_t *Address = reinterpret_cast<uint32_t *>(Sled.address());
53+
// TODO: Trampoline addresses are currently inserted at compile-time, using
54+
// __xray_FunctionEntry and __xray_FunctionExit only.
55+
// To support DSO instrumentation, trampolines have to be written during
56+
// patching (see implementation on X86_64, e.g.).
57+
if (Enable) {
58+
// The resulting code is:
59+
// stmg %r2, %r15, 24(%r15)
60+
// llilf %2,FuncID
61+
// j __xray_FunctionEntry@GOT
62+
// The FuncId and the stmg instruction must be written.
63+
64+
// Write FuncId into llilf.
65+
Address[2] = FuncId;
66+
// Write last part of of stmg.
67+
reinterpret_cast<uint16_t *>(Address)[2] = 0x24;
68+
// Write first part of stmg.
69+
Address[0] = 0xeb2ff010;
70+
} else {
71+
// br %14 instruction.
72+
reinterpret_cast<uint16_t *>(Address)[0] = 0x07fe;
73+
}
74+
return true;
75+
}
76+
77+
bool __xray::patchFunctionTailExit(
78+
const bool Enable, const uint32_t FuncId, const XRaySledEntry &Sled,
79+
const XRayTrampolines &Trampolines) XRAY_NEVER_INSTRUMENT {
80+
return patchFunctionExit(Enable, FuncId, Sled, Trampolines);
81+
}
82+
83+
bool __xray::patchCustomEvent(const bool Enable, const uint32_t FuncId,
84+
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
85+
// TODO Implement.
86+
return false;
87+
}
88+
89+
bool __xray::patchTypedEvent(const bool Enable, const uint32_t FuncId,
90+
const XRaySledEntry &Sled) XRAY_NEVER_INSTRUMENT {
91+
// TODO Implement.
92+
return false;
93+
}
94+
95+
extern "C" void __xray_ArgLoggerEntry() XRAY_NEVER_INSTRUMENT {
96+
// TODO this will have to be implemented in the trampoline assembly file.
97+
}
98+
99+
extern "C" void __xray_FunctionTailExit() XRAY_NEVER_INSTRUMENT {
100+
// For PowerPC, calls to __xray_FunctionEntry and __xray_FunctionExit
101+
// are statically inserted into the sled. Tail exits are handled like normal
102+
// function exits. This trampoline is therefore not implemented.
103+
// This stub is placed here to avoid linking issues.
104+
}
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
//===-- xray_trampoline_s390x.s ---------------------------------*- ASM -*-===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
//
9+
// This file is a part of XRay, a dynamic runtime instrumentation system.
10+
//
11+
// This implements the s390x-specific assembler for the trampolines.
12+
// 2 versions of the functions are provided: one which does not store the
13+
// vector registers, and one which does store them. The compiler decides
14+
// which to call based on the availability of the vector extension.
15+
//
16+
//===----------------------------------------------------------------------===//
17+
18+
.text
19+
20+
// Minimal stack frame size
21+
#define STACKSZ 160
22+
23+
// Minimal stack frame size (160) plus space for 8 vector registers a 16 bytes.
24+
#define STACKSZ_VEC 288
25+
26+
//===----------------------------------------------------------------------===//
27+
28+
.globl __xray_FunctionEntry
29+
.p2align 4
30+
.type __xray_FunctionEntry,@function
31+
__xray_FunctionEntry:
32+
# The registers r2-15 of the instrumented function are already saved in the
33+
# stack frame. On entry, r2 contains the function id, and %r14 the address
34+
# of the first instruction of the instrumented function.
35+
# Register r14 will be stored in the slot reserved for compiler use.
36+
stg %r14, 8(%r15)
37+
std %f0, 128(%r15)
38+
std %f2, 136(%r15)
39+
std %f4, 144(%r15)
40+
std %f6, 152(%r15)
41+
aghi %r15, -STACKSZ
42+
43+
lgrl %r1, _ZN6__xray19XRayPatchedFunctionE@GOT
44+
ltg %r1, 0(%r1)
45+
je .Lrestore0
46+
47+
# Set r3 to XRayEntryType::ENTRY = 0.
48+
# The FuncId is still stored in r2.
49+
lghi %r3, 0
50+
basr %r14, %r1
51+
52+
.Lrestore0:
53+
ld %f6, STACKSZ+152(%r15)
54+
ld %f4, STACKSZ+144(%r15)
55+
ld %f2, STACKSZ+136(%r15)
56+
ld %f0, STACKSZ+128(%r15)
57+
lmg %r1, %r15, STACKSZ+8(%r15)
58+
br %r1
59+
.Lfunc_end0:
60+
.size __xray_FunctionEntry, .Lfunc_end0-__xray_FunctionEntry
61+
62+
//===----------------------------------------------------------------------===//
63+
64+
.globl __xray_FunctionEntryVec
65+
.p2align 4
66+
.type __xray_FunctionEntryVec,@function
67+
__xray_FunctionEntryVec:
68+
# The registers r2-15 of the instrumented function are already saved in the
69+
# stack frame. On entry, r2 contains the function id, and %r14 the address
70+
# of the first instruction of the instrumented function.
71+
# Register r14 will be stored in the slot reserved for compiler use.
72+
stg %r14, 8(%r15)
73+
std %f0, 128(%r15)
74+
std %f2, 136(%r15)
75+
std %f4, 144(%r15)
76+
std %f6, 152(%r15)
77+
aghi %r15, -STACKSZ_VEC
78+
vstm %v24, %v31, 160(%r15)
79+
80+
lgrl %r1, _ZN6__xray19XRayPatchedFunctionE@GOT
81+
ltg %r1, 0(%r1)
82+
je .Lrestore1
83+
84+
# Set r3 to XRayEntryType::ENTRY = 0.
85+
# The FuncId is still stored in r2.
86+
lghi %r3, 0
87+
basr %r14, %r1
88+
89+
.Lrestore1:
90+
vlm %v24, %v31, 160(%r15)
91+
ld %f6, STACKSZ_VEC+152(%r15)
92+
ld %f4, STACKSZ_VEC+144(%r15)
93+
ld %f2, STACKSZ_VEC+136(%r15)
94+
ld %f0, STACKSZ_VEC+128(%r15)
95+
lmg %r1, %r15, STACKSZ_VEC+8(%r15)
96+
br %r1
97+
.Lfunc_end1:
98+
.size __xray_FunctionEntryVec, .Lfunc_end1-__xray_FunctionEntryVec
99+
100+
//===----------------------------------------------------------------------===//
101+
102+
.globl __xray_FunctionExit
103+
.p2align 4
104+
.type __xray_FunctionExit,@function
105+
__xray_FunctionExit:
106+
# The registers r2-15 of the instrumented function are already saved in the
107+
# stack frame. On entry, the register r2 contains the function id.
108+
# At the end, the function jumps to the address saved in the slot for r14,
109+
# which contains the return address into the caller of the instrumented
110+
# function.
111+
std %f0, 128(%r15)
112+
std %f2, 136(%r15)
113+
std %f4, 144(%r15)
114+
std %f6, 152(%r15)
115+
aghi %r15, -STACKSZ
116+
117+
lgrl %r1, _ZN6__xray19XRayPatchedFunctionE@GOT
118+
ltg %r1, 0(%r1)
119+
je .Lrestore2
120+
121+
# Set r3 to XRayEntryType::EXIT = 1.
122+
# The FuncId is still stored in r2.
123+
lghi %r3, 1
124+
basr %r14, %r1
125+
126+
.Lrestore2:
127+
ld %f6, STACKSZ+152(%r15)
128+
ld %f4, STACKSZ+144(%r15)
129+
ld %f2, STACKSZ+136(%r15)
130+
ld %f0, STACKSZ+128(%r15)
131+
lmg %r2, %r15, STACKSZ+16(%r15)
132+
br %r14
133+
.Lfunc_end2:
134+
.size __xray_FunctionExit, .Lfunc_end2-__xray_FunctionExit
135+
136+
//===----------------------------------------------------------------------===//
137+
138+
.globl __xray_FunctionExitVec
139+
.p2align 4
140+
.type __xray_FunctionExitVec,@function
141+
__xray_FunctionExitVec:
142+
# The registers r2-15 of the instrumented function are already saved in the
143+
# stack frame. On entry, the register r2 contains the function id.
144+
# At the end, the function jumps to the address saved in the slot for r14,
145+
# which contains the return address into the caller of the instrumented
146+
# function.
147+
std %f0, 128(%r15)
148+
std %f2, 136(%r15)
149+
std %f4, 144(%r15)
150+
std %f6, 152(%r15)
151+
aghi %r15, -STACKSZ_VEC
152+
vstm %v24, %v31, 160(%r15)
153+
154+
lgrl %r1, _ZN6__xray19XRayPatchedFunctionE@GOT
155+
ltg %r1, 0(%r1)
156+
je .Lrestore3
157+
158+
# Set r3 to XRayEntryType::EXIT = 1.
159+
# The FuncId is still stored in r2.
160+
lghi %r3, 1
161+
basr %r14, %r1
162+
163+
.Lrestore3:
164+
vlm %v24, %v31, 160(%r15)
165+
ld %f6, STACKSZ_VEC+152(%r15)
166+
ld %f4, STACKSZ_VEC+144(%r15)
167+
ld %f2, STACKSZ_VEC+136(%r15)
168+
ld %f0, STACKSZ_VEC+128(%r15)
169+
lmg %r2, %r15, STACKSZ_VEC+16(%r15)
170+
br %r14
171+
.Lfunc_end3:
172+
.size __xray_FunctionExit, .Lfunc_end3-__xray_FunctionExit
173+
174+
//===----------------------------------------------------------------------===//
175+
176+
.section ".note.GNU-stack","",@progbits

compiler-rt/lib/xray/xray_tsc.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,28 @@ inline uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT {
8383

8484
} // namespace __xray
8585

86+
#elif defined(__s390x__)
87+
#include "sanitizer_common/sanitizer_common.h"
88+
#include "sanitizer_common/sanitizer_internal_defs.h"
89+
#include "xray_defs.h"
90+
#include <cerrno>
91+
#include <cstdint>
92+
#include <time.h>
93+
94+
namespace __xray {
95+
96+
inline bool probeRequiredCPUFeatures() XRAY_NEVER_INSTRUMENT { return true; }
97+
98+
ALWAYS_INLINE uint64_t readTSC(uint8_t &CPU) XRAY_NEVER_INSTRUMENT {
99+
return __builtin_readcyclecounter();
100+
}
101+
102+
inline uint64_t getTSCFrequency() XRAY_NEVER_INSTRUMENT {
103+
return NanosecondsPerSecond;
104+
}
105+
106+
} // namespace __xray
107+
86108
#else
87109
#error Target architecture is not supported.
88110
#endif // CPU architecture

0 commit comments

Comments
 (0)