diff options
author | Matheus Ferst <matheus.ferst@eldorado.org.br> | 2021-10-14 19:32:31 -0300 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2021-10-21 11:42:47 +1100 |
commit | 66c6b40aba13807506f20c7522f4930c9ffc76ce (patch) | |
tree | d1658e09ad6da6d61eebcbe4c2a323bf4fcf2c68 /tests | |
parent | 252fcf36bba483493365e91c2f98569de29a43fd (diff) | |
download | qemu-66c6b40aba13807506f20c7522f4930c9ffc76ce.zip qemu-66c6b40aba13807506f20c7522f4930c9ffc76ce.tar.gz qemu-66c6b40aba13807506f20c7522f4930c9ffc76ce.tar.bz2 |
linux-user/ppc: Fix XER access in save/restore_user_regs
We should use cpu_read_xer/cpu_write_xer to save/restore the complete
register since some of its bits are in other fields of CPUPPCState. A
test is added to prevent future regressions.
Fixes: da91a00f191f ("target-ppc: Split out SO, OV, CA fields from XER")
Signed-off-by: Matheus Ferst <matheus.ferst@eldorado.org.br>
Message-Id: <20211014223234.127012-2-matheus.ferst@eldorado.org.br>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'tests')
-rw-r--r-- | tests/tcg/ppc64/Makefile.target | 2 | ||||
-rw-r--r-- | tests/tcg/ppc64le/Makefile.target | 2 | ||||
-rw-r--r-- | tests/tcg/ppc64le/signal_save_restore_xer.c | 42 |
3 files changed, 46 insertions, 0 deletions
diff --git a/tests/tcg/ppc64/Makefile.target b/tests/tcg/ppc64/Makefile.target index a6a4dda..6ab7934 100644 --- a/tests/tcg/ppc64/Makefile.target +++ b/tests/tcg/ppc64/Makefile.target @@ -23,4 +23,6 @@ run-plugin-byte_reverse-with-%: $(call skip-test, "RUN of byte_reverse ($*)", "not built") endif +PPC64_TESTS += signal_save_restore_xer + TESTS += $(PPC64_TESTS) diff --git a/tests/tcg/ppc64le/Makefile.target b/tests/tcg/ppc64le/Makefile.target index c0c14ff..5e65b15 100644 --- a/tests/tcg/ppc64le/Makefile.target +++ b/tests/tcg/ppc64le/Makefile.target @@ -22,4 +22,6 @@ run-plugin-byte_reverse-with-%: $(call skip-test, "RUN of byte_reverse ($*)", "not built") endif +PPC64LE_TESTS += signal_save_restore_xer + TESTS += $(PPC64LE_TESTS) diff --git a/tests/tcg/ppc64le/signal_save_restore_xer.c b/tests/tcg/ppc64le/signal_save_restore_xer.c new file mode 100644 index 0000000..e4f8a07 --- /dev/null +++ b/tests/tcg/ppc64le/signal_save_restore_xer.c @@ -0,0 +1,42 @@ +#include <assert.h> +#include <stdint.h> +#include <signal.h> +#include <sys/user.h> + +#define XER_SO (1 << 31) +#define XER_OV (1 << 30) +#define XER_CA (1 << 29) +#define XER_OV32 (1 << 19) +#define XER_CA32 (1 << 18) + +uint64_t saved; + +void sigill_handler(int sig, siginfo_t *si, void *ucontext) +{ + ucontext_t *uc = ucontext; + uc->uc_mcontext.regs->nip += 4; + saved = uc->uc_mcontext.regs->xer; + uc->uc_mcontext.regs->xer |= XER_OV | XER_OV32; +} + +int main(void) +{ + uint64_t initial = XER_CA | XER_CA32, restored; + struct sigaction sa = { + .sa_sigaction = sigill_handler, + .sa_flags = SA_SIGINFO + }; + + sigaction(SIGILL, &sa, NULL); + + asm("mtspr 1, %1\n\t" + ".long 0x0\n\t" + "mfspr %0, 1\n\t" + : "=r" (restored) + : "r" (initial)); + + assert(saved == initial); + assert(restored == (XER_OV | XER_OV32 | XER_CA | XER_CA32)); + + return 0; +} |