Skip to content

Commit d2c2074

Browse files
frobtechCQ Bot
authored andcommitted
[kernel][arm64] Use FEAT_MOPS memcpy, memset when available
Use code-patching to switch between the current (cortex-strings) assembly versions of memcpy and memset, and new versions taking advantage of the FEAT_MOPS instructions. Change-Id: I09bbdd877316976769183fafdcc7f651f2710ccd Reviewed-on: https://fuchsia-review.googlesource.com/c/fuchsia/+/1069632 Reviewed-by: Travis Geiselbrecht <[email protected]> Fuchsia-Auto-Submit: Roland McGrath <[email protected]> Commit-Queue: Auto-Submit <[email protected]>
1 parent 4520d38 commit d2c2074

File tree

7 files changed

+138
-10
lines changed

7 files changed

+138
-10
lines changed

zircon/kernel/arch/arm64/code-patches/BUILD.gn

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ import("//build/toolchain/toolchain_environment.gni")
99

1010
if (toolchain_environment == "kernel.phys") {
1111
source_set("code-patches") {
12+
public_deps = [ ":headers" ]
1213
sources = [ "code-patches.cc" ]
1314
deps = [
1415
"//zircon/kernel/arch/arm64/phys:arch-phys-info",
16+
"//zircon/kernel/lib/arch",
1517
"//zircon/kernel/lib/code-patching",
1618
"//zircon/kernel/phys:handoff",
1719
"//zircon/kernel/phys:symbolize",
1820
]
19-
public_deps = [ ":headers" ]
2021
}
2122
}
2223

zircon/kernel/arch/arm64/code-patches/code-patches.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
// license that can be found in the LICENSE file or at
55
// https://opensource.org/licenses/MIT
66

7+
#include <lib/arch/arm64/feature.h>
78
#include <lib/code-patching/code-patches.h>
89
#include <zircon/assert.h>
910

@@ -20,6 +21,20 @@
2021
bool ArchPatchCode(code_patching::Patcher& patcher, const ArchPatchInfo& info,
2122
ktl::span<ktl::byte> insns, CodePatchId case_id,
2223
fit::inline_function<void(ktl::initializer_list<ktl::string_view>)> print) {
24+
constexpr auto if_mops = [](ktl::string_view mops,
25+
ktl::string_view not_mops) -> ktl::string_view {
26+
auto isar2 = arch::ArmIdAa64IsaR2El1::Read();
27+
bool feat_mops = isar2.mops() != arch::ArmIdAa64IsaR2El1::Mops::kNone;
28+
return feat_mops ? mops : not_mops;
29+
};
30+
31+
auto do_alternative = [&patcher, insns, &print](ktl::string_view name,
32+
ktl::string_view alternative) -> bool {
33+
patcher.MandatoryPatchWithAlternative(insns, alternative);
34+
print({"using ", name, " alternative \"", alternative, "\""});
35+
return true;
36+
};
37+
2338
switch (case_id) {
2439
case CodePatchId::kSelfTest:
2540
patcher.NopFill(insns);
@@ -79,6 +94,13 @@ bool ArchPatchCode(code_patching::Patcher& patcher, const ArchPatchInfo& info,
7994
print({"CPU workaround SMCCC function is "sv, choice});
8095
return true;
8196
}
97+
98+
case CodePatchId::k__UnsanitizedMemcpy:
99+
return do_alternative("memcpy", if_mops("memcpy-mops", "memcpy-cortex"));
100+
101+
case CodePatchId::k__UnsanitizedMemset:
102+
return do_alternative("memset", if_mops("memset-mops", "memset-cortex"));
82103
}
104+
83105
return false;
84106
}

zircon/kernel/arch/arm64/code-patches/include/arch/code-patches/case-id.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,13 @@ enum class CodePatchId : uint32_t {
2424
// The patched area is a single `mov w0, #...` instruction. It gets patched
2525
// with the SMCCC function number used for SMCCC_ARCH_WORKAROUND_3.
2626
kSmcccWorkaroundFunction,
27+
28+
// Relates to the optimizations available for C string utilities.
29+
//
30+
// Note: the "__" is intentional as the function name has two leading
31+
// underscores.
32+
k__UnsanitizedMemcpy,
33+
k__UnsanitizedMemset,
2734
};
2835

2936
// The callback accepts an initializer-list of something constructible with
@@ -35,6 +42,8 @@ inline constexpr auto WithCodePatchNames = [](auto&& callback) {
3542
{CodePatchId::kSelfTest, "SELF_TEST"},
3643
{CodePatchId::kSmcccConduit, "SMCCC_CONDUIT"},
3744
{CodePatchId::kSmcccWorkaroundFunction, "SMCCC_WORKAROUND_FUNCTION"},
45+
{CodePatchId::k__UnsanitizedMemcpy, "__UNSANITIZED_MEMCPY"},
46+
{CodePatchId::k__UnsanitizedMemset, "__UNSANITIZED_MEMSET"},
3847
});
3948
};
4049

zircon/kernel/lib/code-patching/code-patching.gni

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,7 @@ template("code_patching_hermetic_alternative") {
158158
blob_entrypoint = target_name
159159
}
160160

161-
blob_path =
162-
rebase_path("$target_out_dir/$blob_entrypoint.bin", root_build_dir)
161+
blob_path = rebase_path("$target_out_dir/$target_name.bin", root_build_dir)
163162

164163
hermetic_code_blob(target_name) {
165164
forward_variables_from(invoker,
@@ -182,7 +181,7 @@ template("code_patching_hermetic_alternative") {
182181
code_patching_hermetic_alternatives += [
183182
{
184183
label = target_label
185-
name = blob_entrypoint
184+
name = target_name
186185
path = blob_path
187186
},
188187
]
@@ -192,7 +191,7 @@ template("code_patching_hermetic_alternative") {
192191
distribution_entries += [
193192
{
194193
source = blob_path
195-
destination = "code-patches/$entrypoint"
194+
destination = "code-patches/$target_name"
196195
label = target_label
197196
},
198197
]

zircon/kernel/lib/libc/string/arch/arm64/BUILD.gn

Lines changed: 46 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,12 @@
44
# license that can be found in the LICENSE file or at
55
# https://opensource.org/licenses/MIT
66

7+
import("//build/toolchain/toolchain_environment.gni")
8+
import("//zircon/kernel/lib/code-patching/code-patching.gni")
9+
10+
cortex_strings_dir = "//zircon/third_party/lib/cortex-strings"
11+
not_needed([ "cortex_strings_dir" ])
12+
713
source_set("arm64") {
814
if (current_os == "win" || toolchain_variant.tags + [ "strict-align" ] -
915
[ "strict-align" ] != toolchain_variant.tags) {
@@ -14,13 +20,48 @@ source_set("arm64") {
1420
"//zircon/kernel/lib/libc/string/memset.c",
1521
]
1622
deps = [ "//zircon/kernel/lib/libc:headers" ]
23+
} else if (toolchain_environment == "kernel") {
24+
# In the kernel proper, code-patching chooses the implementation.
25+
deps = [
26+
":__unsanitized_memcpy",
27+
":__unsanitized_memset",
28+
]
1729
} else {
18-
# These use '#include "third_party/lib/cortex-strings/src/aarch64/..."'.
19-
# and '#include "third_party/lib/cortex-strings/no-neon/src/aarch64/..."'.
20-
include_dirs = [ "//zircon/" ]
2130
sources = [
22-
"memcpy.S",
23-
"memset.S",
31+
"$cortex_strings_dir/no-neon/src/aarch64/memset.S",
32+
"$cortex_strings_dir/src/aarch64/memcpy.S",
2433
]
2534
}
2635
}
36+
37+
if (toolchain_environment == "kernel") {
38+
foreach(function,
39+
[
40+
"memcpy",
41+
"memset",
42+
]) {
43+
code_patching_hermetic_stub("__unsanitized_${function}") {
44+
aliases = [ function ]
45+
deps = [
46+
":${function}-cortex",
47+
":${function}-mops",
48+
]
49+
}
50+
51+
code_patching_hermetic_alternative("${function}-mops") {
52+
entrypoint = function
53+
sources = [ "${function}-mops.S" ]
54+
deps = [ "//zircon/kernel/lib/arch:headers" ]
55+
}
56+
}
57+
58+
code_patching_hermetic_alternative("memcpy-cortex") {
59+
entrypoint = "memcpy"
60+
sources = [ "$cortex_strings_dir/src/aarch64/memcpy.S" ]
61+
}
62+
63+
code_patching_hermetic_alternative("memset-cortex") {
64+
entrypoint = "memset"
65+
sources = [ "$cortex_strings_dir/no-neon/src/aarch64/memset.S" ]
66+
}
67+
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2025 The Fuchsia Authors
2+
//
3+
// Use of this source code is governed by a MIT-style
4+
// license that can be found in the LICENSE file or at
5+
// https://opensource.org/licenses/MIT
6+
7+
#include <lib/arch/asm.h>
8+
9+
.arch_extension mops
10+
11+
.function memcpy, global
12+
13+
// The return value is always just the first argument and they both go in x0.
14+
// So use a different register for the destination pointer that gets updated.
15+
retval .req x0
16+
dst .req x3
17+
src .req x1
18+
count .req x2
19+
20+
mov dst, retval
21+
22+
cpyfp [dst]!, [src]!, count!
23+
cpyfm [dst]!, [src]!, count!
24+
cpyfe [dst]!, [src]!, count!
25+
26+
ret
27+
28+
.end_function
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// Copyright 2025 The Fuchsia Authors
2+
//
3+
// Use of this source code is governed by a MIT-style
4+
// license that can be found in the LICENSE file or at
5+
// https://opensource.org/licenses/MIT
6+
7+
#include <lib/arch/asm.h>
8+
9+
.arch_extension mops
10+
11+
.function memset, global
12+
13+
// The return value is always just the first argument and they both go in x0.
14+
// So use a different register for the destination pointer that gets updated.
15+
retval .req x0
16+
dst .req x3
17+
byte .req x1
18+
count .req x2
19+
20+
mov dst, retval
21+
22+
setp [dst]!, count!, byte
23+
setm [dst]!, count!, byte
24+
sete [dst]!, count!, byte
25+
26+
ret
27+
28+
.end_function

0 commit comments

Comments
 (0)