Skip to content

Commit f445be9

Browse files
committed
Reland "[compiler-rt][aarch64] Add SME ABI support routines." (#68875)
Resolved issue with green dragon build by fixing relocations for MachO/Darwin which doesn't compile without @page/@pageoff directives. Also silenced a warning about constructor(90) priority being < 101, which is reserved for the implementation. In this case, we're compiling the implementation so we should be able to use 90. This reverts commit 072713a.
1 parent d093aee commit f445be9

File tree

5 files changed

+262
-0
lines changed

5 files changed

+262
-0
lines changed

compiler-rt/cmake/Modules/AddCompilerRT.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,10 @@ function(add_compiler_rt_runtime name type)
312312
set(COMPONENT_OPTION COMPONENT ${libname})
313313
endif()
314314

315+
if(type STREQUAL "SHARED")
316+
list(APPEND LIB_DEFS COMPILER_RT_SHARED_LIB)
317+
endif()
318+
315319
if(type STREQUAL "OBJECT")
316320
if(CMAKE_C_COMPILER_ID MATCHES Clang AND CMAKE_C_COMPILER_TARGET)
317321
list(APPEND extra_cflags_${libname} "--target=${CMAKE_C_COMPILER_TARGET}")

compiler-rt/cmake/builtin-config-ix.cmake

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ asm(\".arch armv8-a+lse\");
3333
asm(\"cas w0, w1, [x2]\");
3434
")
3535

36+
builtin_check_c_compiler_source(COMPILER_RT_HAS_ASM_SME
37+
"
38+
asm(\".arch armv9-a+sme\");
39+
asm(\"smstart\");
40+
")
41+
3642
if(ANDROID)
3743
set(OS_NAME "Android")
3844
else()

compiler-rt/lib/builtins/CMakeLists.txt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,8 @@ set(aarch64_SOURCES
551551
${GENERIC_SOURCES}
552552
cpu_model.c
553553
aarch64/fp_mode.c
554+
aarch64/sme-abi.S
555+
aarch64/sme-abi-init.c
554556
)
555557

556558
# Generate outline atomics helpers from lse.S base
@@ -780,6 +782,7 @@ else ()
780782
endif()
781783

782784
append_list_if(COMPILER_RT_HAS_ASM_LSE HAS_ASM_LSE BUILTIN_DEFS)
785+
append_list_if(COMPILER_RT_HAS_ASM_SME HAS_ASM_SME BUILTIN_DEFS)
783786

784787
foreach (arch ${BUILTIN_SUPPORTED_ARCH})
785788
if (CAN_TARGET_${arch})
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2+
// See https://llvm.org/LICENSE.txt for license information.
3+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
5+
__attribute__((visibility("hidden"), nocommon))
6+
_Bool __aarch64_has_sme_and_tpidr2_el0;
7+
8+
// We have multiple ways to check that the function has SME, depending on our
9+
// target.
10+
// * For Linux we can use __getauxval().
11+
// * For newlib we can use __aarch64_sme_accessible().
12+
13+
#if defined(__linux__)
14+
15+
#ifndef AT_HWCAP2
16+
#define AT_HWCAP2 26
17+
#endif
18+
19+
#ifndef HWCAP2_SME
20+
#define HWCAP2_SME (1 << 23)
21+
#endif
22+
23+
extern unsigned long int __getauxval (unsigned long int);
24+
25+
static _Bool has_sme(void) {
26+
return __getauxval(AT_HWCAP2) & HWCAP2_SME;
27+
}
28+
29+
#else // defined(__linux__)
30+
31+
#if defined(COMPILER_RT_SHARED_LIB)
32+
__attribute__((weak))
33+
#endif
34+
extern _Bool __aarch64_sme_accessible(void);
35+
36+
static _Bool has_sme(void) {
37+
#if defined(COMPILER_RT_SHARED_LIB)
38+
if (!__aarch64_sme_accessible)
39+
return 0;
40+
#endif
41+
return __aarch64_sme_accessible();
42+
}
43+
44+
#endif // defined(__linux__)
45+
46+
#if __GNUC__ >= 9
47+
#pragma GCC diagnostic ignored "-Wprio-ctor-dtor"
48+
#endif
49+
__attribute__((constructor(90)))
50+
static void init_aarch64_has_sme(void) {
51+
__aarch64_has_sme_and_tpidr2_el0 = has_sme();
52+
}
Lines changed: 197 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,197 @@
1+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2+
// See https://llvm.org/LICENSE.txt for license information.
3+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
4+
5+
// This patch implements the support routines for the SME ABI,
6+
// described here:
7+
// https://github.com/ARM-software/abi-aa/blob/main/aapcs64/aapcs64.rst#sme-support-routines
8+
9+
#include "../assembly.h"
10+
11+
#ifdef HAS_ASM_SME
12+
#define ARCH armv9-a+sme
13+
#define SMSTOP_SM smstop sm
14+
#define SMSTOP_ZA smstop za
15+
#define REG_TPIDR2_EL0 TPIDR2_EL0
16+
#define REG_SVCR SVCR
17+
#define ADDSVL_X16_X16_1 addsvl x16, x16, #1
18+
#define LDR_ZA_W15_0_X16 ldr za[w15,0], [x16]
19+
#define STR_ZA_W15_0_X16 str za[w15,0], [x16]
20+
#define CNTD_X0 cntd x0
21+
#define CFI_OFFSET_VG_MINUS_16 .cfi_offset vg, -16
22+
#else
23+
#define ARCH armv8-a
24+
#define SMSTOP_SM .inst 0xd503427f
25+
#define SMSTOP_ZA .inst 0xd503447f
26+
#define REG_TPIDR2_EL0 S3_3_C13_C0_5
27+
#define REG_SVCR S3_3_C4_C2_2
28+
#define ADDSVL_X16_X16_1 .inst 0x04305830
29+
#define LDR_ZA_W15_0_X16 .inst 0xe1006200
30+
#define STR_ZA_W15_0_X16 .inst 0xe1206200
31+
#define CNTD_X0 .inst 0x04e0e3e0
32+
#define CFI_OFFSET_VG_MINUS_16 .cfi_escape 0x10, 0x2e, 0x03, 0x11, 0x70, 0x22 // $vg @ cfa - 16
33+
#endif
34+
35+
#if !defined(__APPLE__)
36+
#define TPIDR2_SYMBOL SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)
37+
#define TPIDR2_SYMBOL_OFFSET :lo12:SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)
38+
#else
39+
// MachO requires @page/@pageoff directives because the global is defined
40+
// in a different file. Otherwise this file may fail to build.
41+
#define TPIDR2_SYMBOL SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)@page
42+
#define TPIDR2_SYMBOL_OFFSET SYMBOL_NAME(__aarch64_has_sme_and_tpidr2_el0)@pageoff
43+
#endif
44+
45+
.arch ARCH
46+
47+
// Utility function which calls a system's abort() routine. Because the function
48+
// is streaming-compatible it should disable streaming-SVE mode before calling
49+
// abort(). Note that there is no need to preserve any state before the call,
50+
// because the function does not return.
51+
DEFINE_COMPILERRT_PRIVATE_FUNCTION(do_abort)
52+
.cfi_startproc
53+
.variant_pcs SYMBOL_NAME(do_abort)
54+
stp x29, x30, [sp, #-32]!
55+
CNTD_X0
56+
// Store VG to a stack location that we describe with .cfi_offset
57+
str x0, [sp, #16]
58+
.cfi_def_cfa_offset 32
59+
.cfi_offset w30, -24
60+
.cfi_offset w29, -32
61+
CFI_OFFSET_VG_MINUS_16
62+
bl __arm_sme_state
63+
tbz x0, #0, 2f
64+
1:
65+
SMSTOP_SM
66+
2:
67+
// We can't make this into a tail-call because the unwinder would
68+
// need to restore the value of VG.
69+
bl SYMBOL_NAME(abort)
70+
.cfi_endproc
71+
END_COMPILERRT_FUNCTION(do_abort)
72+
73+
// __arm_sme_state fills the result registers based on a local
74+
// that is set as part of the compiler-rt startup code.
75+
// __aarch64_has_sme_and_tpidr2_el0
76+
DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_sme_state)
77+
.variant_pcs __arm_sme_state
78+
mov x0, xzr
79+
mov x1, xzr
80+
81+
adrp x16, TPIDR2_SYMBOL
82+
ldrb w16, [x16, TPIDR2_SYMBOL_OFFSET]
83+
cbz w16, 1f
84+
0:
85+
orr x0, x0, #0xC000000000000000
86+
mrs x16, REG_SVCR
87+
bfxil x0, x16, #0, #2
88+
mrs x1, REG_TPIDR2_EL0
89+
1:
90+
ret
91+
END_COMPILERRT_OUTLINE_FUNCTION(__arm_sme_state)
92+
93+
DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_tpidr2_restore)
94+
.variant_pcs __arm_tpidr2_restore
95+
// If TPIDR2_EL0 is nonnull, the subroutine aborts in some platform-specific
96+
// manner.
97+
mrs x14, REG_TPIDR2_EL0
98+
cbnz x14, 2f
99+
100+
// If any of the reserved bytes in the first 16 bytes of BLK are nonzero,
101+
// the subroutine [..] aborts in some platform-defined manner.
102+
ldrh w14, [x0, #10]
103+
cbnz w14, 2f
104+
ldr w14, [x0, #12]
105+
cbnz w14, 2f
106+
107+
// If BLK.za_save_buffer is NULL, the subroutine does nothing.
108+
ldr x16, [x0]
109+
cbz x16, 1f
110+
111+
// If BLK.num_za_save_slices is zero, the subroutine does nothing.
112+
ldrh w14, [x0, #8]
113+
cbz x14, 1f
114+
115+
mov x15, xzr
116+
0:
117+
LDR_ZA_W15_0_X16
118+
ADDSVL_X16_X16_1
119+
add x15, x15, #1
120+
cmp x14, x15
121+
b.ne 0b
122+
1:
123+
ret
124+
2:
125+
b SYMBOL_NAME(do_abort)
126+
END_COMPILERRT_OUTLINE_FUNCTION(__arm_tpidr2_restore)
127+
128+
DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_tpidr2_save)
129+
// If the current thread does not have access to TPIDR2_EL0, the subroutine
130+
// does nothing.
131+
adrp x14, TPIDR2_SYMBOL
132+
ldrb w14, [x14, TPIDR2_SYMBOL_OFFSET]
133+
cbz w14, 1f
134+
135+
// If TPIDR2_EL0 is null, the subroutine does nothing.
136+
mrs x16, REG_TPIDR2_EL0
137+
cbz x16, 1f
138+
139+
// If any of the reserved bytes in the first 16 bytes of the TPIDR2 block are
140+
// nonzero, the subroutine [..] aborts in some platform-defined manner.
141+
ldrh w14, [x16, #10]
142+
cbnz w14, 2f
143+
ldr w14, [x16, #12]
144+
cbnz w14, 2f
145+
146+
// If num_za_save_slices is zero, the subroutine does nothing.
147+
ldrh w14, [x16, #8]
148+
cbz x14, 1f
149+
150+
// If za_save_buffer is NULL, the subroutine does nothing.
151+
ldr x16, [x16]
152+
cbz x16, 1f
153+
154+
mov x15, xzr
155+
0:
156+
STR_ZA_W15_0_X16
157+
ADDSVL_X16_X16_1
158+
add x15, x15, #1
159+
cmp x14, x15
160+
b.ne 0b
161+
1:
162+
ret
163+
2:
164+
b SYMBOL_NAME(do_abort)
165+
END_COMPILERRT_OUTLINE_FUNCTION(__arm_tpidr2_save)
166+
167+
DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(__arm_za_disable)
168+
// If the current thread does not have access to SME, the subroutine does
169+
// nothing.
170+
adrp x14, TPIDR2_SYMBOL
171+
ldrb w14, [x14, TPIDR2_SYMBOL_OFFSET]
172+
cbz w14, 0f
173+
174+
// Otherwise, the subroutine behaves as if it did the following:
175+
// * Call __arm_tpidr2_save.
176+
stp x29, x30, [sp, #-16]!
177+
.cfi_def_cfa_offset 16
178+
mov x29, sp
179+
.cfi_def_cfa w29, 16
180+
.cfi_offset w30, -8
181+
.cfi_offset w29, -16
182+
bl __arm_tpidr2_save
183+
184+
// * Set TPIDR2_EL0 to null.
185+
msr REG_TPIDR2_EL0, xzr
186+
187+
// * Set PSTATE.ZA to 0.
188+
SMSTOP_ZA
189+
190+
.cfi_def_cfa wsp, 16
191+
ldp x29, x30, [sp], #16
192+
.cfi_def_cfa_offset 0
193+
.cfi_restore w30
194+
.cfi_restore w29
195+
0:
196+
ret
197+
END_COMPILERRT_OUTLINE_FUNCTION(__arm_za_disable)

0 commit comments

Comments
 (0)