mirror of
https://github.com/edk2-porting/linux-next.git
synced 2024-12-26 14:14:01 +08:00
9d535e200f
Currently TM signal context tests for GPR, FPR, VMX, and VSX registers print wrong register numbers (wrongly starting from register 0 instead of the first register in the non-volatile subset). Besides it the output when a mismatch happens is poor giving not much information about which context and which register mismatches, because it prints both contexts at the same time and not a comparison between the value that mismatches and the value expected and, moreover, it stops printing on the first mismatch, but it's important to know if there are other mismatches happening beyond the first one. For instance, this is the current output when a mismatch happens: test: tm_signal_context_chk_gpr tags: git_version:v5.2-8249-g02e970fae465-dirty Failed on 0 GPR 1 or 18446744073709551615 failure: tm_signal_context_chk_gpr test: tm_signal_context_chk_fpu tags: git_version:v5.2-8248-g09c289e3ef80 Failed on 0 FP -1 or -1 failure: tm_signal_context_chk_fpu test: tm_signal_context_chk_vmx tags: git_version:v5.2-8248-g09c289e3ef80 Failed on 0 vmx 0xfffffffffffffffefffffffdfffffffc vs 0xfffffffffffffffefffffffdfffffffc failure: tm_signal_context_chk_vmx test: tm_signal_context_chk_vsx tags: git_version:v5.2-8248-g09c289e3ef80 Failed on 0 vsx 0xfffffffffefffffffdfffffffcffffff vs 0xfffffffffefffffffdfffffffcffffff failure: tm_signal_context_chk_vsx This commit fixes the register numbers printed and enhances the error output by providing a full list of mismatching registers separated by the context (non-speculative or speculative context), for example: test: tm_signal_context_chk_gpr tags: git_version:v5.2-8249-g02e970fae465-dirty GPR14 (1st context) == 1 instead of -1 (expected) GPR15 (1st context) == 2 instead of -2 (expected) GPR14 (2nd context) == 0 instead of 18446744073709551615 (expected) GPR15 (2nd context) == 0 instead of 18446744073709551614 (expected) failure: tm_signal_context_chk_gpr test: tm_signal_context_chk_fpu tags: git_version:v5.2-8249-g02e970fae465-dirty FPR14 (1st context) == -1 instead of 1 (expected) FPR15 (1st context) == -2 instead of 2 (expected) failure: tm_signal_context_chk_fpu test: tm_signal_context_chk_vmx tags: git_version:v5.2-8249-g02e970fae465-dirty VMX20 (1st context) == 0xfffffffffffffffefffffffdfffffffc instead of 0x00000001000000020000000300000004 (expected) VMX21 (1st context) == 0xfffffffbfffffffafffffff9fffffff8 instead of 0x00000005000000060000000700000008 (expected) failure: tm_signal_context_chk_vmx test: tm_signal_context_chk_vsx tags: git_version:v5.2-8249-g02e970fae465-dirty VSX20 (1st context) == 0xfffffffffefffffffdfffffffcffffff instead of 0x00000001000000020000000300000004 (expected) VSX21 (1st context) == 0xfbfffffffafffffff9fffffff8ffffff instead of 0x00000005000000060000000700000008 (expected) failure: tm_signal_context_chk_vsx Finally, this commit adds comments to the tests in the hope that it will help people not so familiar with TM understand the tests. Signed-off-by: Gustavo Romero <gromero@linux.ibm.com> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au> Link: https://lore.kernel.org/r/20190814205211.24840-1-gromero@linux.ibm.com
113 lines
3.2 KiB
C
113 lines
3.2 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
* Copyright 2016, Cyril Bur, IBM Corp.
|
|
*
|
|
* Test the kernel's signal frame code.
|
|
*
|
|
* The kernel sets up two sets of ucontexts if the signal was to be
|
|
* delivered while the thread was in a transaction (referred too as
|
|
* first and second contexts).
|
|
* Expected behaviour is that the checkpointed state is in the user
|
|
* context passed to the signal handler (first context). The speculated
|
|
* state can be accessed with the uc_link pointer (second context).
|
|
*
|
|
* The rationale for this is that if TM unaware code (which linked
|
|
* against TM libs) installs a signal handler it will not know of the
|
|
* speculative nature of the 'live' registers and may infer the wrong
|
|
* thing.
|
|
*/
|
|
|
|
#include <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <signal.h>
|
|
#include <unistd.h>
|
|
|
|
#include <altivec.h>
|
|
|
|
#include "utils.h"
|
|
#include "tm.h"
|
|
|
|
#define MAX_ATTEMPT 500000
|
|
|
|
#define NV_GPR_REGS 18 /* Number of non-volatile GPR registers */
|
|
#define R14 14 /* First non-volatile register to check in r14-r31 subset */
|
|
|
|
long tm_signal_self_context_load(pid_t pid, long *gprs, double *fps, vector int *vms, vector int *vss);
|
|
|
|
static sig_atomic_t fail, broken;
|
|
|
|
/* Test only non-volatile general purpose registers, i.e. r14-r31 */
|
|
static long gprs[] = {
|
|
/* First context will be set with these values, i.e. non-speculative */
|
|
/* R14, R15, ... */
|
|
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
|
|
/* Second context will be set with these values, i.e. speculative */
|
|
/* R14, R15, ... */
|
|
-1,-2,-3,-4,-5,-6,-7,-8,-9,-10,-11,-12,-13,-14,-15,-16,-17,-18
|
|
};
|
|
|
|
static void signal_usr1(int signum, siginfo_t *info, void *uc)
|
|
{
|
|
int i;
|
|
ucontext_t *ucp = uc;
|
|
ucontext_t *tm_ucp = ucp->uc_link;
|
|
|
|
/* Check first context. Print all mismatches. */
|
|
for (i = 0; i < NV_GPR_REGS; i++) {
|
|
fail = (ucp->uc_mcontext.gp_regs[R14 + i] != gprs[i]);
|
|
if (fail) {
|
|
broken = 1;
|
|
printf("GPR%d (1st context) == %lu instead of %lu (expected)\n",
|
|
R14 + i, ucp->uc_mcontext.gp_regs[R14 + i], gprs[i]);
|
|
}
|
|
}
|
|
|
|
/* Check second context. Print all mismatches. */
|
|
for (i = 0; i < NV_GPR_REGS; i++) {
|
|
fail = (tm_ucp->uc_mcontext.gp_regs[R14 + i] != gprs[NV_GPR_REGS + i]);
|
|
if (fail) {
|
|
broken = 1;
|
|
printf("GPR%d (2nd context) == %lu instead of %lu (expected)\n",
|
|
R14 + i, tm_ucp->uc_mcontext.gp_regs[R14 + i], gprs[NV_GPR_REGS + i]);
|
|
}
|
|
}
|
|
}
|
|
|
|
static int tm_signal_context_chk_gpr()
|
|
{
|
|
struct sigaction act;
|
|
int i;
|
|
long rc;
|
|
pid_t pid = getpid();
|
|
|
|
SKIP_IF(!have_htm());
|
|
|
|
act.sa_sigaction = signal_usr1;
|
|
sigemptyset(&act.sa_mask);
|
|
act.sa_flags = SA_SIGINFO;
|
|
if (sigaction(SIGUSR1, &act, NULL) < 0) {
|
|
perror("sigaction sigusr1");
|
|
exit(1);
|
|
}
|
|
|
|
i = 0;
|
|
while (i < MAX_ATTEMPT && !broken) {
|
|
/*
|
|
* tm_signal_self_context_load will set both first and second
|
|
* contexts accordingly to the values passed through non-NULL
|
|
* array pointers to it, in that case 'gprs', and invoke the
|
|
* signal handler installed for SIGUSR1.
|
|
*/
|
|
rc = tm_signal_self_context_load(pid, gprs, NULL, NULL, NULL);
|
|
FAIL_IF(rc != pid);
|
|
i++;
|
|
}
|
|
|
|
return broken;
|
|
}
|
|
|
|
int main(void)
|
|
{
|
|
return test_harness(tm_signal_context_chk_gpr, "tm_signal_context_chk_gpr");
|
|
}
|