18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright 2015, Michael Neuling, IBM Corp. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Test the kernel's signal return code to ensure that it doesn't 68c2ecf20Sopenharmony_ci * crash when both the transactional and suspend MSR bits are set in 78c2ecf20Sopenharmony_ci * the signal context. 88c2ecf20Sopenharmony_ci * 98c2ecf20Sopenharmony_ci * For this test, we send ourselves a SIGUSR1. In the SIGUSR1 handler 108c2ecf20Sopenharmony_ci * we modify the signal context to set both MSR TM S and T bits (which 118c2ecf20Sopenharmony_ci * is "reserved" by the PowerISA). When we return from the signal 128c2ecf20Sopenharmony_ci * handler (implicit sigreturn), the kernel should detect reserved MSR 138c2ecf20Sopenharmony_ci * value and send us with a SIGSEGV. 148c2ecf20Sopenharmony_ci */ 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#include <stdlib.h> 178c2ecf20Sopenharmony_ci#include <stdio.h> 188c2ecf20Sopenharmony_ci#include <signal.h> 198c2ecf20Sopenharmony_ci#include <unistd.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include "utils.h" 228c2ecf20Sopenharmony_ci#include "tm.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ciint segv_expected = 0; 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_civoid signal_segv(int signum) 278c2ecf20Sopenharmony_ci{ 288c2ecf20Sopenharmony_ci if (segv_expected && (signum == SIGSEGV)) 298c2ecf20Sopenharmony_ci _exit(0); 308c2ecf20Sopenharmony_ci _exit(1); 318c2ecf20Sopenharmony_ci} 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_civoid signal_usr1(int signum, siginfo_t *info, void *uc) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci ucontext_t *ucp = uc; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci /* Link tm checkpointed context to normal context */ 388c2ecf20Sopenharmony_ci ucp->uc_link = ucp; 398c2ecf20Sopenharmony_ci /* Set all TM bits so that the context is now invalid */ 408c2ecf20Sopenharmony_ci#ifdef __powerpc64__ 418c2ecf20Sopenharmony_ci ucp->uc_mcontext.gp_regs[PT_MSR] |= (7ULL << 32); 428c2ecf20Sopenharmony_ci#else 438c2ecf20Sopenharmony_ci ucp->uc_mcontext.uc_regs->gregs[PT_MSR] |= (7ULL); 448c2ecf20Sopenharmony_ci#endif 458c2ecf20Sopenharmony_ci /* Should segv on return becuase of invalid context */ 468c2ecf20Sopenharmony_ci segv_expected = 1; 478c2ecf20Sopenharmony_ci} 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ciint tm_signal_msr_resv() 508c2ecf20Sopenharmony_ci{ 518c2ecf20Sopenharmony_ci struct sigaction act; 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci SKIP_IF(!have_htm()); 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci act.sa_sigaction = signal_usr1; 568c2ecf20Sopenharmony_ci sigemptyset(&act.sa_mask); 578c2ecf20Sopenharmony_ci act.sa_flags = SA_SIGINFO; 588c2ecf20Sopenharmony_ci if (sigaction(SIGUSR1, &act, NULL) < 0) { 598c2ecf20Sopenharmony_ci perror("sigaction sigusr1"); 608c2ecf20Sopenharmony_ci exit(1); 618c2ecf20Sopenharmony_ci } 628c2ecf20Sopenharmony_ci if (signal(SIGSEGV, signal_segv) == SIG_ERR) 638c2ecf20Sopenharmony_ci exit(1); 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci raise(SIGUSR1); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci /* We shouldn't get here as we exit in the segv handler */ 688c2ecf20Sopenharmony_ci return 1; 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ciint main(void) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci return test_harness(tm_signal_msr_resv, "tm_signal_msr_resv"); 748c2ecf20Sopenharmony_ci} 75