@@ -211,4 +211,127 @@ TEST(ptrace_v_early_debug)
211211 }
212212}
213213
214+ TEST (ptrace_v_syscall_clobbering )
215+ {
216+ pid_t pid ;
217+
218+ if (!is_vector_supported () && !is_xtheadvector_supported ())
219+ SKIP (return , "Vector not supported" );
220+
221+ chld_lock = 1 ;
222+ pid = fork ();
223+ ASSERT_LE (0 , pid )
224+ TH_LOG ("fork: %m" );
225+
226+ if (pid == 0 ) {
227+ unsigned long vl ;
228+
229+ while (chld_lock == 1 )
230+ asm volatile ("" : : "g" (chld_lock ) : "memory" );
231+
232+ if (is_xtheadvector_supported ()) {
233+ asm volatile (
234+ // 0 | zimm[10:0] | rs1 | 1 1 1 | rd |1010111| vsetvli
235+ // vsetvli t4, x0, e16, m2, d1
236+ ".4byte 0b00000000010100000111111011010111\n"
237+ "mv %[new_vl], t4\n"
238+ : [new_vl ] "=r" (vl ) : : "t4" );
239+ } else {
240+ asm volatile (
241+ ".option push\n"
242+ ".option arch, +zve32x\n"
243+ "vsetvli %[new_vl], x0, e16, m2, tu, mu\n"
244+ ".option pop\n"
245+ : [new_vl ] "=r" (vl ) : : );
246+ }
247+
248+ while (1 ) {
249+ asm volatile (
250+ ".option push\n"
251+ ".option norvc\n"
252+ "ebreak\n"
253+ ".option pop\n" );
254+
255+ sleep (0 );
256+ }
257+ } else {
258+ struct __riscv_v_regset_state * regset_data ;
259+ unsigned long vlenb = get_vr_len ();
260+ struct user_regs_struct regs ;
261+ size_t regset_size ;
262+ struct iovec iov ;
263+ int status ;
264+
265+ /* attach */
266+
267+ ASSERT_EQ (0 , ptrace (PTRACE_ATTACH , pid , NULL , NULL ));
268+ ASSERT_EQ (pid , waitpid (pid , & status , 0 ));
269+ ASSERT_TRUE (WIFSTOPPED (status ));
270+
271+ /* unlock */
272+
273+ ASSERT_EQ (0 , ptrace (PTRACE_POKEDATA , pid , & chld_lock , 0 ));
274+
275+ /* resume and wait for the 1st ebreak */
276+
277+ ASSERT_EQ (0 , ptrace (PTRACE_CONT , pid , NULL , NULL ));
278+ ASSERT_EQ (pid , waitpid (pid , & status , 0 ));
279+ ASSERT_TRUE (WIFSTOPPED (status ));
280+
281+ /* read tracee vector csr regs using ptrace GETREGSET */
282+
283+ regset_size = sizeof (* regset_data ) + vlenb * 32 ;
284+ regset_data = calloc (1 , regset_size );
285+
286+ iov .iov_base = regset_data ;
287+ iov .iov_len = regset_size ;
288+
289+ ASSERT_EQ (0 , ptrace (PTRACE_GETREGSET , pid , NT_RISCV_VECTOR , & iov ));
290+
291+ /* verify initial vsetvli settings */
292+
293+ if (is_xtheadvector_supported ())
294+ EXPECT_EQ (5UL , regset_data -> vtype );
295+ else
296+ EXPECT_EQ (9UL , regset_data -> vtype );
297+
298+ EXPECT_EQ (regset_data -> vlenb , regset_data -> vl );
299+ EXPECT_EQ (vlenb , regset_data -> vlenb );
300+ EXPECT_EQ (0UL , regset_data -> vstart );
301+ EXPECT_EQ (0UL , regset_data -> vcsr );
302+
303+ /* skip 1st ebreak, then resume and wait for the 2nd ebreak */
304+
305+ iov .iov_base = & regs ;
306+ iov .iov_len = sizeof (regs );
307+
308+ ASSERT_EQ (0 , ptrace (PTRACE_GETREGSET , pid , NT_PRSTATUS , & iov ));
309+ regs .pc += 4 ;
310+ ASSERT_EQ (0 , ptrace (PTRACE_SETREGSET , pid , NT_PRSTATUS , & iov ));
311+
312+ ASSERT_EQ (0 , ptrace (PTRACE_CONT , pid , NULL , NULL ));
313+ ASSERT_EQ (pid , waitpid (pid , & status , 0 ));
314+ ASSERT_TRUE (WIFSTOPPED (status ));
315+
316+ /* read tracee vtype using ptrace GETREGSET */
317+
318+ iov .iov_base = regset_data ;
319+ iov .iov_len = regset_size ;
320+
321+ ASSERT_EQ (0 , ptrace (PTRACE_GETREGSET , pid , NT_RISCV_VECTOR , & iov ));
322+
323+ /* verify that V state is illegal after syscall */
324+
325+ EXPECT_EQ ((1UL << (__riscv_xlen - 1 )), regset_data -> vtype );
326+ EXPECT_EQ (vlenb , regset_data -> vlenb );
327+ EXPECT_EQ (0UL , regset_data -> vstart );
328+ EXPECT_EQ (0UL , regset_data -> vcsr );
329+ EXPECT_EQ (0UL , regset_data -> vl );
330+
331+ /* cleanup */
332+
333+ ASSERT_EQ (0 , kill (pid , SIGKILL ));
334+ }
335+ }
336+
214337TEST_HARNESS_MAIN
0 commit comments