12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
211508074SAnshuman Khandual /*
311508074SAnshuman Khandual * Ptrace test for VMX/VSX registers in the TM context
411508074SAnshuman Khandual *
511508074SAnshuman Khandual * Copyright (C) 2015 Anshuman Khandual, IBM Corporation.
611508074SAnshuman Khandual */
711508074SAnshuman Khandual #include "ptrace.h"
811508074SAnshuman Khandual #include "tm.h"
911508074SAnshuman Khandual #include "ptrace-vsx.h"
1011508074SAnshuman Khandual
1111508074SAnshuman Khandual int shm_id;
1211508074SAnshuman Khandual unsigned long *cptr, *pptr;
1311508074SAnshuman Khandual
1411508074SAnshuman Khandual unsigned long fp_load[VEC_MAX];
1511508074SAnshuman Khandual unsigned long fp_store[VEC_MAX];
1611508074SAnshuman Khandual unsigned long fp_load_ckpt[VEC_MAX];
1711508074SAnshuman Khandual unsigned long fp_load_ckpt_new[VEC_MAX];
1811508074SAnshuman Khandual
load_vsx(void)1911508074SAnshuman Khandual __attribute__((used)) void load_vsx(void)
2011508074SAnshuman Khandual {
2111508074SAnshuman Khandual loadvsx(fp_load, 0);
2211508074SAnshuman Khandual }
2311508074SAnshuman Khandual
load_vsx_ckpt(void)2411508074SAnshuman Khandual __attribute__((used)) void load_vsx_ckpt(void)
2511508074SAnshuman Khandual {
2611508074SAnshuman Khandual loadvsx(fp_load_ckpt, 0);
2711508074SAnshuman Khandual }
2811508074SAnshuman Khandual
tm_vsx(void)2911508074SAnshuman Khandual void tm_vsx(void)
3011508074SAnshuman Khandual {
3111508074SAnshuman Khandual unsigned long result, texasr;
3211508074SAnshuman Khandual int ret;
3311508074SAnshuman Khandual
3411508074SAnshuman Khandual cptr = (unsigned long *)shmat(shm_id, NULL, 0);
3511508074SAnshuman Khandual
3611508074SAnshuman Khandual trans:
3711508074SAnshuman Khandual cptr[1] = 0;
3811508074SAnshuman Khandual asm __volatile__(
3911508074SAnshuman Khandual "bl load_vsx_ckpt;"
4011508074SAnshuman Khandual
4111508074SAnshuman Khandual "1: ;"
4211508074SAnshuman Khandual "tbegin.;"
4311508074SAnshuman Khandual "beq 2f;"
4411508074SAnshuman Khandual
4511508074SAnshuman Khandual "bl load_vsx;"
4611508074SAnshuman Khandual "tsuspend.;"
4711508074SAnshuman Khandual "li 7, 1;"
4811508074SAnshuman Khandual "stw 7, 0(%[cptr1]);"
4911508074SAnshuman Khandual "tresume.;"
5011508074SAnshuman Khandual "b .;"
5111508074SAnshuman Khandual
5211508074SAnshuman Khandual "tend.;"
5311508074SAnshuman Khandual "li 0, 0;"
5411508074SAnshuman Khandual "ori %[res], 0, 0;"
5511508074SAnshuman Khandual "b 3f;"
5611508074SAnshuman Khandual
5711508074SAnshuman Khandual "2: ;"
5811508074SAnshuman Khandual "li 0, 1;"
5911508074SAnshuman Khandual "ori %[res], 0, 0;"
6011508074SAnshuman Khandual "mfspr %[texasr], %[sprn_texasr];"
6111508074SAnshuman Khandual
6211508074SAnshuman Khandual "3: ;"
6311508074SAnshuman Khandual : [res] "=r" (result), [texasr] "=r" (texasr)
645249497aSBreno Leitao : [sprn_texasr] "i" (SPRN_TEXASR), [cptr1] "b" (&cptr[1])
65a02cbc7fSMichael Ellerman : "memory", "r0", "r3", "r4",
66a02cbc7fSMichael Ellerman "r7", "r8", "r9", "r10", "r11", "lr"
6711508074SAnshuman Khandual );
6811508074SAnshuman Khandual
6911508074SAnshuman Khandual if (result) {
7011508074SAnshuman Khandual if (!cptr[0])
7111508074SAnshuman Khandual goto trans;
7211508074SAnshuman Khandual
7311508074SAnshuman Khandual shmdt((void *)cptr);
7411508074SAnshuman Khandual storevsx(fp_store, 0);
7511508074SAnshuman Khandual ret = compare_vsx_vmx(fp_store, fp_load_ckpt_new);
7611508074SAnshuman Khandual if (ret)
7711508074SAnshuman Khandual exit(1);
7811508074SAnshuman Khandual exit(0);
7911508074SAnshuman Khandual }
8011508074SAnshuman Khandual shmdt((void *)cptr);
8111508074SAnshuman Khandual exit(1);
8211508074SAnshuman Khandual }
8311508074SAnshuman Khandual
trace_tm_vsx(pid_t child)8411508074SAnshuman Khandual int trace_tm_vsx(pid_t child)
8511508074SAnshuman Khandual {
8611508074SAnshuman Khandual unsigned long vsx[VSX_MAX];
8711508074SAnshuman Khandual unsigned long vmx[VMX_MAX + 2][2];
8811508074SAnshuman Khandual
8911508074SAnshuman Khandual FAIL_IF(start_trace(child));
9011508074SAnshuman Khandual FAIL_IF(show_vsx(child, vsx));
9111508074SAnshuman Khandual FAIL_IF(validate_vsx(vsx, fp_load));
9211508074SAnshuman Khandual FAIL_IF(show_vmx(child, vmx));
9311508074SAnshuman Khandual FAIL_IF(validate_vmx(vmx, fp_load));
9411508074SAnshuman Khandual FAIL_IF(show_vsx_ckpt(child, vsx));
9511508074SAnshuman Khandual FAIL_IF(validate_vsx(vsx, fp_load_ckpt));
9611508074SAnshuman Khandual FAIL_IF(show_vmx_ckpt(child, vmx));
9711508074SAnshuman Khandual FAIL_IF(validate_vmx(vmx, fp_load_ckpt));
9811508074SAnshuman Khandual memset(vsx, 0, sizeof(vsx));
9911508074SAnshuman Khandual memset(vmx, 0, sizeof(vmx));
10011508074SAnshuman Khandual
10111508074SAnshuman Khandual load_vsx_vmx(fp_load_ckpt_new, vsx, vmx);
10211508074SAnshuman Khandual
10311508074SAnshuman Khandual FAIL_IF(write_vsx_ckpt(child, vsx));
10411508074SAnshuman Khandual FAIL_IF(write_vmx_ckpt(child, vmx));
10511508074SAnshuman Khandual pptr[0] = 1;
10611508074SAnshuman Khandual FAIL_IF(stop_trace(child));
10711508074SAnshuman Khandual return TEST_PASS;
10811508074SAnshuman Khandual }
10911508074SAnshuman Khandual
ptrace_tm_vsx(void)11011508074SAnshuman Khandual int ptrace_tm_vsx(void)
11111508074SAnshuman Khandual {
11211508074SAnshuman Khandual pid_t pid;
11311508074SAnshuman Khandual int ret, status, i;
11411508074SAnshuman Khandual
115*68877ff2SBenjamin Gray SKIP_IF_MSG(!have_htm(), "Don't have transactional memory");
116*68877ff2SBenjamin Gray SKIP_IF_MSG(htm_is_synthetic(), "Transactional memory is synthetic");
11711508074SAnshuman Khandual shm_id = shmget(IPC_PRIVATE, sizeof(int) * 2, 0777|IPC_CREAT);
11811508074SAnshuman Khandual
11911508074SAnshuman Khandual for (i = 0; i < 128; i++) {
12011508074SAnshuman Khandual fp_load[i] = 1 + rand();
12111508074SAnshuman Khandual fp_load_ckpt[i] = 1 + 2 * rand();
12211508074SAnshuman Khandual fp_load_ckpt_new[i] = 1 + 3 * rand();
12311508074SAnshuman Khandual }
12411508074SAnshuman Khandual
12511508074SAnshuman Khandual pid = fork();
12611508074SAnshuman Khandual if (pid < 0) {
12711508074SAnshuman Khandual perror("fork() failed");
12811508074SAnshuman Khandual return TEST_FAIL;
12911508074SAnshuman Khandual }
13011508074SAnshuman Khandual
13111508074SAnshuman Khandual if (pid == 0)
13211508074SAnshuman Khandual tm_vsx();
13311508074SAnshuman Khandual
13411508074SAnshuman Khandual if (pid) {
13511508074SAnshuman Khandual pptr = (unsigned long *)shmat(shm_id, NULL, 0);
13611508074SAnshuman Khandual while (!pptr[1])
13711508074SAnshuman Khandual asm volatile("" : : : "memory");
13811508074SAnshuman Khandual
13911508074SAnshuman Khandual ret = trace_tm_vsx(pid);
14011508074SAnshuman Khandual if (ret) {
14111508074SAnshuman Khandual kill(pid, SIGKILL);
14211508074SAnshuman Khandual shmdt((void *)pptr);
14311508074SAnshuman Khandual shmctl(shm_id, IPC_RMID, NULL);
14411508074SAnshuman Khandual return TEST_FAIL;
14511508074SAnshuman Khandual }
14611508074SAnshuman Khandual
14711508074SAnshuman Khandual shmdt((void *)pptr);
14811508074SAnshuman Khandual ret = wait(&status);
14911508074SAnshuman Khandual shmctl(shm_id, IPC_RMID, NULL);
15011508074SAnshuman Khandual if (ret != pid) {
15111508074SAnshuman Khandual printf("Child's exit status not captured\n");
15211508074SAnshuman Khandual return TEST_FAIL;
15311508074SAnshuman Khandual }
15411508074SAnshuman Khandual
15511508074SAnshuman Khandual return (WIFEXITED(status) && WEXITSTATUS(status)) ? TEST_FAIL :
15611508074SAnshuman Khandual TEST_PASS;
15711508074SAnshuman Khandual }
15811508074SAnshuman Khandual return TEST_PASS;
15911508074SAnshuman Khandual }
16011508074SAnshuman Khandual
main(int argc,char * argv[])16111508074SAnshuman Khandual int main(int argc, char *argv[])
16211508074SAnshuman Khandual {
16311508074SAnshuman Khandual return test_harness(ptrace_tm_vsx, "ptrace_tm_vsx");
16411508074SAnshuman Khandual }
165