mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2025-01-23 06:14:42 +08:00
selftests/powerpc/ptrace: Do more of ptrace-gpr in asm
The ptrace-gpr test includes some inline asm to load GPR and FPR registers. It then goes back to C to wait for the parent to trace it and then checks register contents. The split between inline asm and C is fragile, it relies on the compiler not using any non-volatile GPRs after the inline asm block. It also requires a very large and unwieldy inline asm block. So convert the logic to set registers, wait, and store registers to a single asm function, meaning there's no window for the compiler to intervene. Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20220627140239.2464900-10-mpe@ellerman.id.au
This commit is contained in:
parent
149a497d5f
commit
611e385087
@ -94,4 +94,12 @@
|
||||
PPC_LL r0, STACK_FRAME_LR_POS(%r1); \
|
||||
mtlr r0;
|
||||
|
||||
.macro OP_REGS op, reg_width, start_reg, end_reg, base_reg, base_reg_offset=0, skip=0
|
||||
.set i, \start_reg
|
||||
.rept (\end_reg - \start_reg + 1)
|
||||
\op i, (\reg_width * (i - \skip) + \base_reg_offset)(\base_reg)
|
||||
.set i, i + 1
|
||||
.endr
|
||||
.endm
|
||||
|
||||
#endif /* _SELFTESTS_POWERPC_BASIC_ASM_H */
|
||||
|
@ -35,6 +35,7 @@ $(TM_TESTS): CFLAGS += -I../tm -mhtm
|
||||
|
||||
CFLAGS += -I../../../../../usr/include -fno-pie
|
||||
|
||||
$(OUTPUT)/ptrace-gpr: ptrace-gpr.S
|
||||
$(OUTPUT)/ptrace-pkey $(OUTPUT)/core-pkey: LDLIBS += -pthread
|
||||
|
||||
$(TEST_GEN_PROGS): ../harness.c ../utils.c ../lib/reg.S
|
||||
|
52
tools/testing/selftests/powerpc/ptrace/ptrace-gpr.S
Normal file
52
tools/testing/selftests/powerpc/ptrace/ptrace-gpr.S
Normal file
@ -0,0 +1,52 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
/*
|
||||
* test helper assembly functions
|
||||
*
|
||||
* Copyright (C) 2016 Simon Guo, IBM Corporation.
|
||||
* Copyright 2022 Michael Ellerman, IBM Corporation.
|
||||
*/
|
||||
#include "basic_asm.h"
|
||||
|
||||
#define GPR_SIZE __SIZEOF_LONG__
|
||||
#define FIRST_GPR 14
|
||||
#define NUM_GPRS (32 - FIRST_GPR)
|
||||
#define STACK_SIZE (NUM_GPRS * GPR_SIZE)
|
||||
|
||||
// gpr_child_loop(int *read_flag, int *write_flag,
|
||||
// unsigned long *gpr_buf, double *fpr_buf);
|
||||
FUNC_START(gpr_child_loop)
|
||||
// r3 = read_flag
|
||||
// r4 = write_flag
|
||||
// r5 = gpr_buf
|
||||
// r6 = fpr_buf
|
||||
PUSH_BASIC_STACK(STACK_SIZE)
|
||||
|
||||
// Save non-volatile GPRs
|
||||
OP_REGS PPC_STL, GPR_SIZE, FIRST_GPR, 31, %r1, STACK_FRAME_LOCAL(0, 0), FIRST_GPR
|
||||
|
||||
// Load GPRs with expected values
|
||||
OP_REGS PPC_LL, GPR_SIZE, FIRST_GPR, 31, r5, 0, FIRST_GPR
|
||||
|
||||
// Load FPRs with expected values
|
||||
OP_REGS lfd, 8, 0, 31, r6
|
||||
|
||||
// Signal to parent that we're ready
|
||||
li r0, 1
|
||||
stw r0, 0(r4)
|
||||
|
||||
// Wait for parent to finish
|
||||
1: lwz r0, 0(r3)
|
||||
cmpwi r0, 0
|
||||
beq 1b // Loop while flag is zero
|
||||
|
||||
// Save GPRs back to caller buffer
|
||||
OP_REGS PPC_STL, GPR_SIZE, FIRST_GPR, 31, r5, 0, FIRST_GPR
|
||||
|
||||
// Save FPRs
|
||||
OP_REGS stfd, 8, 0, 31, r6
|
||||
|
||||
// Reload non-volatile GPRs
|
||||
OP_REGS PPC_LL, GPR_SIZE, FIRST_GPR, 31, %r1, STACK_FRAME_LOCAL(0, 0), FIRST_GPR
|
||||
|
||||
POP_BASIC_STACK(STACK_SIZE)
|
||||
blr
|
@ -16,32 +16,27 @@ double a = FPR_1;
|
||||
double b = FPR_2;
|
||||
double c = FPR_3;
|
||||
|
||||
extern void gpr_child_loop(int *read_flag, int *write_flag,
|
||||
unsigned long *gpr_buf, double *fpr_buf);
|
||||
|
||||
void gpr(void)
|
||||
{
|
||||
unsigned long gpr_buf[18];
|
||||
unsigned long gpr_buf[32];
|
||||
double fpr_buf[32];
|
||||
int i;
|
||||
|
||||
cptr = (int *)shmat(shm_id, NULL, 0);
|
||||
memset(gpr_buf, 0, sizeof(gpr_buf));
|
||||
memset(fpr_buf, 0, sizeof(fpr_buf));
|
||||
|
||||
asm __volatile__(
|
||||
ASM_LOAD_GPR_IMMED(gpr_1)
|
||||
ASM_LOAD_FPR(flt_1)
|
||||
:
|
||||
: [gpr_1]"i"(GPR_1), [flt_1] "b" (&a)
|
||||
: "memory", "r6", "r7", "r8", "r9", "r10",
|
||||
"r11", "r12", "r13", "r14", "r15", "r16", "r17",
|
||||
"r18", "r19", "r20", "r21", "r22", "r23", "r24",
|
||||
"r25", "r26", "r27", "r28", "r29", "r30", "r31"
|
||||
);
|
||||
for (i = 0; i < 32; i++) {
|
||||
gpr_buf[i] = GPR_1;
|
||||
fpr_buf[i] = a;
|
||||
}
|
||||
|
||||
cptr[1] = 1;
|
||||
|
||||
while (!cptr[0])
|
||||
asm volatile("" : : : "memory");
|
||||
gpr_child_loop(&cptr[0], &cptr[1], gpr_buf, fpr_buf);
|
||||
|
||||
shmdt((void *)cptr);
|
||||
store_gpr(gpr_buf);
|
||||
store_fpr(fpr_buf);
|
||||
|
||||
if (validate_gpr(gpr_buf, GPR_3))
|
||||
exit(1);
|
||||
|
Loading…
Reference in New Issue
Block a user