Skip to content

Commit 910f54f

Browse files
authored
i#7779: Store Aarch64 SVE registers in arrays of dr_simd_t and dr_svp_t. (#7780)
SVE registers (Z0-Z31) and predicate registers (P0-P15) are encapsulated within arrays of dr_simd_t and dr_sve_t types, respectively. When the SVE registers are written to the dstack using insert_save_or_restore_sve_registers(), create_base_disp_for_save_restore() is used to compute the offset of the SVE registers, i.e. ``` case SVE_ZREG_TYPE: opsz = opnd_size_from_bytes(proc_get_vector_length_bytes()); offset = num_saved * proc_get_vector_length_bytes(); break; case SVE_PREG_TYPE: opsz = opnd_size_from_bytes(proc_get_vector_length_bytes() / 8); offset = num_saved * (proc_get_vector_length_bytes() / 8); break; ``` The offset calculation considers the size of the register supported on the platform based on roc_get_vector_length_bytes(), but not arrays of dr_simd_t and dr_sve_t. In effect, all the registers are packed together without considering the size of dr_simd_t and dr_svep_t. When other functions retrieve the register values based on the arrays, they get incorrect values (except for z0). This PR changes the code to use the size of the array element to compute the offset, so that register values are stored in the corresponding elements. Add a test to verify SVE registers are saved and restored properly using dr_redirect_ececution(). Fixes: #7779
1 parent b54c434 commit 910f54f

File tree

5 files changed

+413
-3
lines changed

5 files changed

+413
-3
lines changed

core/arch/aarchxx/mangle.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,11 +99,17 @@ create_base_disp_for_save_restore(uint base_reg, bool is_single_reg, reg_type_t
9999
break;
100100
case SVE_ZREG_TYPE:
101101
opsz = opnd_size_from_bytes(proc_get_vector_length_bytes());
102-
offset = num_saved * proc_get_vector_length_bytes();
102+
// SVE registers (Z0-Z31) are mapped to a contiguous array of dr_simd_t.
103+
// Each Z-register occupies a distinct element in the array, indexed by its
104+
// architectural register number.
105+
offset = num_saved * sizeof(dr_simd_t);
103106
break;
104107
case SVE_PREG_TYPE:
105108
opsz = opnd_size_from_bytes(proc_get_vector_length_bytes() / 8);
106-
offset = num_saved * (proc_get_vector_length_bytes() / 8);
109+
// SVE predicate registers (P0-P15) are mapped to a contiguous array of dr_svep_t.
110+
// Each P-register occupies a distinct element in the array, indexed by its
111+
// architectural register number.
112+
offset = num_saved * sizeof(dr_svep_t);
107113
break;
108114
default: ASSERT_NOT_REACHED();
109115
}

suite/tests/CMakeLists.txt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,8 @@ set(sve_tests
525525
client.drbbdup-drwrap-test client.drbbdup-emul-test client.process-id
526526
client.drreg-test client.low_on_memory client.tls client.drwrap-test
527527
client.drwrap-drreg-test drstatecmp-fuzz-app client.drutil-test client.stolen-reg
528-
client.ldstex client.drsyms-test client.drwrap-test-detach api.dis-a64
528+
client.ldstex client.drsyms-test client.drwrap-test-detach
529+
client.save-restore-sve-registers api.dis-a64
529530
api.reenc-a64 api.opnd api.detach api.detach_state api.detach_signal
530531
api.detach_spawn api.detach_spawn_stress_FLAKY api.detach_spawn_quick_exit
531532
api.ibl-stress api.ibl-stress-aarch64-far-link_LONG api.static_startstop
@@ -6111,6 +6112,17 @@ if (UNIX)
61116112
torunonly(linux.steal-switch linux.thread linux/thread.c
61126113
"-enable_reset -reset_at_fragment_count 100 -steal_reg_at_reset ${new_reg}" "")
61136114
endif ()
6115+
if (AARCH64 AND LINUX)
6116+
if (proc_supports_sve OR proc_supports_sve2)
6117+
set(client.save-restore-sve-registers_client_source
6118+
"client-interface/redirect_execution.dll.c")
6119+
tobuild_ci(client.save-restore-sve-registers common/aarch64_sve.asm "" "" "")
6120+
set_target_properties(
6121+
client.save-restore-sve-registers PROPERTIES LINKER_LANGUAGE C)
6122+
append_link_flags(client.save-restore-sve-registers
6123+
"-nostartfiles -nodefaultlibs -static")
6124+
endif()
6125+
endif()
61146126
tobuild(pthreads.pthreads pthreads/pthreads.c)
61156127
tobuild(pthreads.pthreads_exit pthreads/pthreads_exit.c)
61166128
tobuild(pthreads.ptsig pthreads/ptsig.c)
Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/* **********************************************************
2+
* Copyright (c) 2026 Google, Inc. All rights reserved.
3+
* **********************************************************/
4+
5+
/*
6+
* Redistribution and use in source and binary forms, with or without
7+
* modification, are permitted provided that the following conditions are met:
8+
*
9+
* * Redistributions of source code must retain the above copyright notice,
10+
* this list of conditions and the following disclaimer.
11+
*
12+
* * Redistributions in binary form must reproduce the above copyright notice,
13+
* this list of conditions and the following disclaimer in the documentation
14+
* and/or other materials provided with the distribution.
15+
*
16+
* * Neither the name of VMware, Inc. nor the names of its contributors may be
17+
* used to endorse or promote products derived from this software without
18+
* specific prior written permission.
19+
*
20+
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21+
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22+
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23+
* ARE DISCLAIMED. IN NO EVENT SHALL VMWARE, INC. OR CONTRIBUTORS BE LIABLE
24+
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25+
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26+
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27+
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28+
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29+
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
30+
* DAMAGE.
31+
*/
32+
33+
#include "dr_api.h"
34+
#include "client_tools.h"
35+
36+
static bool redirect_execution = false;
37+
38+
static void
39+
bb_event(void *pc)
40+
{
41+
void *drcontext = dr_get_current_drcontext();
42+
dr_mcontext_t mcontext;
43+
mcontext.size = sizeof(mcontext);
44+
mcontext.flags = DR_MC_ALL;
45+
ASSERT(dr_get_mcontext(drcontext, &mcontext) == true);
46+
mcontext.pc = dr_app_pc_as_jump_target(dr_get_isa_mode(drcontext), pc);
47+
dr_redirect_execution(&mcontext);
48+
}
49+
50+
static dr_emit_flags_t
51+
instrument_bb(void *drcontext, void *tag, instrlist_t *bb, bool for_trace,
52+
bool translating)
53+
{
54+
instr_t *instr, *next_instr;
55+
for (instr = instrlist_first(bb); instr != NULL; instr = next_instr) {
56+
next_instr = instr_get_next(instr);
57+
if (next_instr == NULL) {
58+
return DR_EMIT_DEFAULT;
59+
}
60+
// Insert a clean call after the two-consecutive NOP sentinel sequence.
61+
// The clean call invokes dr_redirect_execution() to restore the saved application
62+
// context and resume execution with the original register state.
63+
if (instr_is_nop(instr) && instr_is_nop(next_instr)) {
64+
dr_insert_clean_call_ex(
65+
drcontext, bb, next_instr, (void *)bb_event,
66+
DR_CLEANCALL_READS_APP_CONTEXT, 1,
67+
OPND_CREATE_INTPTR((ptr_uint_t)instr_get_app_pc(next_instr)));
68+
}
69+
}
70+
return DR_EMIT_DEFAULT;
71+
}
72+
73+
DR_EXPORT void
74+
dr_init(client_id_t id)
75+
{
76+
dr_register_bb_event(instrument_bb);
77+
}

0 commit comments

Comments
 (0)