Fix a bunch of BUGs in the mem-helpers (including the MVC instruction),
especially, to make them behave correctly on faults. -----BEGIN PGP SIGNATURE----- iQJFBAABCAAvFiEEG9nKrXNcTDpGDfzKTd4Q9wD/g1oFAl2Ie9ERHGRhdmlkQHJl ZGhhdC5jb20ACgkQTd4Q9wD/g1qMNQ//an/e3uXES+LINt/L/UeMpTVxrKCjqz/0 xlzN3eZmCTKTWb+PD0BRA5tsLCynI731gZQZgHSkgnNz3bEMklJELdUNL40N1idn 9ey1ZDOGOtGKNYzoe6C53V0H7T2i1WIhoCNeuUSVjcnGL43RVYJB+gCOwCWKQhgR k7wJ7b5riJtNBFy9cx8egjP+Rw+eJ/9e+lDccVAOF4avvvI0gNMN9Fq8N6q2y4DM 1stzhwuBP4rsl6SwCyvEdaISwVpcnQWQTp0z46ighrqWV/hJnibVQtDGVSvb3+Dr Kn+oHaN1VYwgaAacVAzgW+HMak1BRWIf8OGGfZlihUMubUCOHANkj9eIqVAwF8qy 5hVJMfCA9HpCSy0Va9zmVZ9/2EVJfLacykULxveXKX9e9AU+awoQJIvnRIzpc5Q0 zvPK/871icXPx9UR46aOt8i8CBOun3HmsfCPyuOvzliCHuKyVqbBfdqOl7BHp5LL aMp/DB51DIfvQhSRDFdRR2f5o9KvYcafG72F7pWnLZ83TXVHhVqza03ArnjOa/Gi Yty+LMEVYWzfmFq8GpA/9bJvY7Bd/EfkO3xXnlJjEFRPk/XTnzsO5c3flcK9hgnY tSlqTj/4k+oyKiV7WTYzixTAu4tUhcKOEDkQ4j6kwUMJUTkueqDTAe1Ycxkzjqy5 QfGdmuKpE8U= =839a -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/davidhildenbrand/tags/s390x-tcg-2019-09-23' into staging Fix a bunch of BUGs in the mem-helpers (including the MVC instruction), especially, to make them behave correctly on faults. # gpg: Signature made Mon 23 Sep 2019 09:01:21 BST # gpg: using RSA key 1BD9CAAD735C4C3A460DFCCA4DDE10F700FF835A # gpg: issuer "david@redhat.com" # gpg: Good signature from "David Hildenbrand <david@redhat.com>" [unknown] # gpg: aka "David Hildenbrand <davidhildenbrand@gmail.com>" [full] # Primary key fingerprint: 1BD9 CAAD 735C 4C3A 460D FCCA 4DDE 10F7 00FF 835A * remotes/davidhildenbrand/tags/s390x-tcg-2019-09-23: (30 commits) tests/tcg: target/s390x: Test MVC tests/tcg: target/s390x: Test MVO s390x/tcg: MVO: Fault-safe handling s390x/tcg: MVST: Fault-safe handling s390x/tcg: MVZ: Fault-safe handling s390x/tcg: MVN: Fault-safe handling s390x/tcg: MVCIN: Fault-safe handling s390x/tcg: NC: Fault-safe handling s390x/tcg: XC: Fault-safe handling s390x/tcg: OC: Fault-safe handling s390x/tcg: MVCLU: Fault-safe handling s390x/tcg: MVC: Fault-safe handling on destructive overlaps s390x/tcg: MVCS/MVCP: Use access_memmove() s390x/tcg: Fault-safe memmove s390x/tcg: Fault-safe memset s390x/tcg: Always use MMU_USER_IDX for CONFIG_USER_ONLY s390x/tcg: MVST: Fix storing back the addresses to registers s390x/tcg: MVST: Check for specification exceptions s390x/tcg: MVCS/MVCP: Properly wrap the length s390x/tcg: MVCOS: Lengths are 32 bit in 24/31-bit mode ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
2f93a3ecdd
|
@ -328,6 +328,9 @@ extern const VMStateDescription vmstate_s390_cpu;
|
||||||
|
|
||||||
static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch)
|
static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
return MMU_USER_IDX;
|
||||||
|
#else
|
||||||
if (!(env->psw.mask & PSW_MASK_DAT)) {
|
if (!(env->psw.mask & PSW_MASK_DAT)) {
|
||||||
return MMU_REAL_IDX;
|
return MMU_REAL_IDX;
|
||||||
}
|
}
|
||||||
|
@ -351,6 +354,7 @@ static inline int cpu_mmu_index(CPUS390XState *env, bool ifetch)
|
||||||
default:
|
default:
|
||||||
abort();
|
abort();
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
|
static inline void cpu_get_tb_cpu_state(CPUS390XState* env, target_ulong *pc,
|
||||||
|
|
|
@ -20,7 +20,7 @@ DEF_HELPER_FLAGS_4(mvn, TCG_CALL_NO_WG, void, env, i32, i64, i64)
|
||||||
DEF_HELPER_FLAGS_4(mvo, TCG_CALL_NO_WG, void, env, i32, i64, i64)
|
DEF_HELPER_FLAGS_4(mvo, TCG_CALL_NO_WG, void, env, i32, i64, i64)
|
||||||
DEF_HELPER_FLAGS_4(mvpg, TCG_CALL_NO_WG, i32, env, i64, i64, i64)
|
DEF_HELPER_FLAGS_4(mvpg, TCG_CALL_NO_WG, i32, env, i64, i64, i64)
|
||||||
DEF_HELPER_FLAGS_4(mvz, TCG_CALL_NO_WG, void, env, i32, i64, i64)
|
DEF_HELPER_FLAGS_4(mvz, TCG_CALL_NO_WG, void, env, i32, i64, i64)
|
||||||
DEF_HELPER_4(mvst, i64, env, i64, i64, i64)
|
DEF_HELPER_3(mvst, i32, env, i32, i32)
|
||||||
DEF_HELPER_4(ex, void, env, i32, i64, i64)
|
DEF_HELPER_4(ex, void, env, i32, i64, i64)
|
||||||
DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32)
|
DEF_HELPER_FLAGS_4(stam, TCG_CALL_NO_WG, void, env, i32, i64, i32)
|
||||||
DEF_HELPER_FLAGS_4(lam, TCG_CALL_NO_WG, void, env, i32, i64, i32)
|
DEF_HELPER_FLAGS_4(lam, TCG_CALL_NO_WG, void, env, i32, i64, i32)
|
||||||
|
|
|
@ -637,7 +637,7 @@
|
||||||
/* MOVE PAGE */
|
/* MOVE PAGE */
|
||||||
C(0xb254, MVPG, RRE, Z, r1_o, r2_o, 0, 0, mvpg, 0)
|
C(0xb254, MVPG, RRE, Z, r1_o, r2_o, 0, 0, mvpg, 0)
|
||||||
/* MOVE STRING */
|
/* MOVE STRING */
|
||||||
C(0xb255, MVST, RRE, Z, r1_o, r2_o, 0, 0, mvst, 0)
|
C(0xb255, MVST, RRE, Z, 0, 0, 0, 0, mvst, 0)
|
||||||
/* MOVE WITH OPTIONAL SPECIFICATION */
|
/* MOVE WITH OPTIONAL SPECIFICATION */
|
||||||
C(0xc800, MVCOS, SSF, MVCOS, la1, a2, 0, 0, mvcos, 0)
|
C(0xc800, MVCOS, SSF, MVCOS, la1, a2, 0, 0, mvcos, 0)
|
||||||
/* MOVE WITH OFFSET */
|
/* MOVE WITH OFFSET */
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -318,6 +318,9 @@ static inline uint64_t ld_code4(CPUS390XState *env, uint64_t pc)
|
||||||
|
|
||||||
static int get_mem_index(DisasContext *s)
|
static int get_mem_index(DisasContext *s)
|
||||||
{
|
{
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
return MMU_USER_IDX;
|
||||||
|
#else
|
||||||
if (!(s->base.tb->flags & FLAG_MASK_DAT)) {
|
if (!(s->base.tb->flags & FLAG_MASK_DAT)) {
|
||||||
return MMU_REAL_IDX;
|
return MMU_REAL_IDX;
|
||||||
}
|
}
|
||||||
|
@ -333,6 +336,7 @@ static int get_mem_index(DisasContext *s)
|
||||||
tcg_abort();
|
tcg_abort();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gen_exception(int excp)
|
static void gen_exception(int excp)
|
||||||
|
@ -3488,9 +3492,13 @@ static DisasJumpType op_mvpg(DisasContext *s, DisasOps *o)
|
||||||
|
|
||||||
static DisasJumpType op_mvst(DisasContext *s, DisasOps *o)
|
static DisasJumpType op_mvst(DisasContext *s, DisasOps *o)
|
||||||
{
|
{
|
||||||
gen_helper_mvst(o->in1, cpu_env, regs[0], o->in1, o->in2);
|
TCGv_i32 t1 = tcg_const_i32(get_field(s->fields, r1));
|
||||||
|
TCGv_i32 t2 = tcg_const_i32(get_field(s->fields, r2));
|
||||||
|
|
||||||
|
gen_helper_mvst(cc_op, cpu_env, t1, t2);
|
||||||
|
tcg_temp_free_i32(t1);
|
||||||
|
tcg_temp_free_i32(t2);
|
||||||
set_cc_static(s);
|
set_cc_static(s);
|
||||||
return_low128(o->in2);
|
|
||||||
return DISAS_NEXT;
|
return DISAS_NEXT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,3 +6,5 @@ TESTS+=ipm
|
||||||
TESTS+=exrl-trt
|
TESTS+=exrl-trt
|
||||||
TESTS+=exrl-trtr
|
TESTS+=exrl-trtr
|
||||||
TESTS+=pack
|
TESTS+=pack
|
||||||
|
TESTS+=mvo
|
||||||
|
TESTS+=mvc
|
||||||
|
|
109
tests/tcg/s390x/mvc.c
Normal file
109
tests/tcg/s390x/mvc.c
Normal file
|
@ -0,0 +1,109 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <setjmp.h>
|
||||||
|
|
||||||
|
jmp_buf jmp_env;
|
||||||
|
|
||||||
|
static void handle_sigsegv(int sig)
|
||||||
|
{
|
||||||
|
siglongjmp(jmp_env, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ALLOC_SIZE (2 * 4096)
|
||||||
|
|
||||||
|
static inline void mvc_256(const char *dst, const char *src)
|
||||||
|
{
|
||||||
|
asm volatile (
|
||||||
|
" mvc 0(256,%[dst]),0(%[src])\n"
|
||||||
|
:
|
||||||
|
: [dst] "d" (dst),
|
||||||
|
[src] "d" (src)
|
||||||
|
: "memory");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
char *src, *dst;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* register the SIGSEGV handler */
|
||||||
|
if (signal(SIGSEGV, handle_sigsegv) == SIG_ERR) {
|
||||||
|
fprintf(stderr, "SIGSEGV not registered\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* prepare the buffers - two consecutive pages */
|
||||||
|
src = valloc(ALLOC_SIZE);
|
||||||
|
dst = valloc(ALLOC_SIZE);
|
||||||
|
memset(src, 0xff, ALLOC_SIZE);
|
||||||
|
memset(dst, 0x0, ALLOC_SIZE);
|
||||||
|
|
||||||
|
/* protect the second pages */
|
||||||
|
if (mprotect(src + 4096, 4096, PROT_NONE) ||
|
||||||
|
mprotect(dst + 4096, 4096, PROT_NONE)) {
|
||||||
|
fprintf(stderr, "mprotect failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fault on second destination page */
|
||||||
|
if (sigsetjmp(jmp_env, 1) == 0) {
|
||||||
|
mvc_256(dst + 4096 - 128, src);
|
||||||
|
fprintf(stderr, "fault not triggered\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fault on second source page */
|
||||||
|
if (sigsetjmp(jmp_env, 1) == 0) {
|
||||||
|
mvc_256(dst, src + 4096 - 128);
|
||||||
|
fprintf(stderr, "fault not triggered\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fault on second source and second destination page */
|
||||||
|
if (sigsetjmp(jmp_env, 1) == 0) {
|
||||||
|
mvc_256(dst + 4096 - 128, src + 4096 - 128);
|
||||||
|
fprintf(stderr, "fault not triggered\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* restore permissions */
|
||||||
|
if (mprotect(src + 4096, 4096, PROT_READ | PROT_WRITE) ||
|
||||||
|
mprotect(dst + 4096, 4096, PROT_READ | PROT_WRITE)) {
|
||||||
|
fprintf(stderr, "mprotect failed\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* no data must be touched during the faults */
|
||||||
|
for (i = 0; i < ALLOC_SIZE; i++) {
|
||||||
|
if (src[i] != 0xff || dst[i]) {
|
||||||
|
fprintf(stderr, "data modified during a fault\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test if MVC works now correctly accross page boundaries */
|
||||||
|
mvc_256(dst + 4096 - 128, src + 4096 - 128);
|
||||||
|
for (i = 0; i < ALLOC_SIZE; i++) {
|
||||||
|
if (src[i] != 0xff) {
|
||||||
|
fprintf(stderr, "src modified\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (i < 4096 - 128 || i >= 4096 + 128) {
|
||||||
|
if (dst[i]) {
|
||||||
|
fprintf(stderr, "wrong dst modified\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (dst[i] != 0xff) {
|
||||||
|
fprintf(stderr, "wrong data moved\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
25
tests/tcg/s390x/mvo.c
Normal file
25
tests/tcg/s390x/mvo.c
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
int main(void)
|
||||||
|
{
|
||||||
|
uint8_t dest[6] = {0xff, 0x77, 0x88, 0x99, 0x0c, 0xff};
|
||||||
|
uint8_t src[5] = {0xee, 0x12, 0x34, 0x56, 0xee};
|
||||||
|
uint8_t expected[6] = {0xff, 0x01, 0x23, 0x45, 0x6c, 0xff};
|
||||||
|
int i;
|
||||||
|
|
||||||
|
asm volatile (
|
||||||
|
" mvo 0(4,%[dest]),0(3,%[src])\n"
|
||||||
|
:
|
||||||
|
: [dest] "d" (dest + 1),
|
||||||
|
[src] "d" (src + 1)
|
||||||
|
: "memory");
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(expected); i++) {
|
||||||
|
if (dest[i] != expected[i]) {
|
||||||
|
fprintf(stderr, "bad data\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue