Skip to content

Commit db17d2c

Browse files
iii-irth7680
authored andcommitted
accel/tcg/user-exec: Fix read-modify-write of code on s390 hosts
x86_64 dotnet/runtime uses cmpxchg for code patching. When running it under s390x qemu-linux user, cpu_signal_handler() does not recognize this as a write and does not restore PAGE_WRITE cleared by tb_page_add(), incorrectly forwarding the signal to the guest code. Signed-off-by: Ilya Leoshkevich <[email protected]> Reviewed-by: Richard Henderson <[email protected]> Message-Id: <[email protected]> Signed-off-by: Richard Henderson <[email protected]>
1 parent 76d0042 commit db17d2c

File tree

1 file changed

+41
-7
lines changed

1 file changed

+41
-7
lines changed

accel/tcg/user-exec.c

Lines changed: 41 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -680,18 +680,26 @@ int cpu_signal_handler(int host_signum, void *pinfo,
680680

681681
pc = uc->uc_mcontext.psw.addr;
682682

683-
/* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
684-
of the normal 2 arguments. The 3rd argument contains the "int_code"
685-
from the hardware which does in fact contain the is_write value.
686-
The rt signal handler, as far as I can tell, does not give this value
687-
at all. Not that we could get to it from here even if it were. */
688-
/* ??? This is not even close to complete, since it ignores all
689-
of the read-modify-write instructions. */
683+
/*
684+
* ??? On linux, the non-rt signal handler has 4 (!) arguments instead
685+
* of the normal 2 arguments. The 4th argument contains the "Translation-
686+
* Exception Identification for DAT Exceptions" from the hardware (aka
687+
* "int_parm_long"), which does in fact contain the is_write value.
688+
* The rt signal handler, as far as I can tell, does not give this value
689+
* at all. Not that we could get to it from here even if it were.
690+
* So fall back to parsing instructions. Treat read-modify-write ones as
691+
* writes, which is not fully correct, but for tracking self-modifying code
692+
* this is better than treating them as reads. Checking si_addr page flags
693+
* might be a viable improvement, albeit a racy one.
694+
*/
695+
/* ??? This is not even close to complete. */
690696
pinsn = (uint16_t *)pc;
691697
switch (pinsn[0] >> 8) {
692698
case 0x50: /* ST */
693699
case 0x42: /* STC */
694700
case 0x40: /* STH */
701+
case 0xba: /* CS */
702+
case 0xbb: /* CDS */
695703
is_write = 1;
696704
break;
697705
case 0xc4: /* RIL format insns */
@@ -702,6 +710,12 @@ int cpu_signal_handler(int host_signum, void *pinfo,
702710
is_write = 1;
703711
}
704712
break;
713+
case 0xc8: /* SSF format insns */
714+
switch (pinsn[0] & 0xf) {
715+
case 0x2: /* CSST */
716+
is_write = 1;
717+
}
718+
break;
705719
case 0xe3: /* RXY format insns */
706720
switch (pinsn[2] & 0xff) {
707721
case 0x50: /* STY */
@@ -715,7 +729,27 @@ int cpu_signal_handler(int host_signum, void *pinfo,
715729
is_write = 1;
716730
}
717731
break;
732+
case 0xeb: /* RSY format insns */
733+
switch (pinsn[2] & 0xff) {
734+
case 0x14: /* CSY */
735+
case 0x30: /* CSG */
736+
case 0x31: /* CDSY */
737+
case 0x3e: /* CDSG */
738+
case 0xe4: /* LANG */
739+
case 0xe6: /* LAOG */
740+
case 0xe7: /* LAXG */
741+
case 0xe8: /* LAAG */
742+
case 0xea: /* LAALG */
743+
case 0xf4: /* LAN */
744+
case 0xf6: /* LAO */
745+
case 0xf7: /* LAX */
746+
case 0xfa: /* LAAL */
747+
case 0xf8: /* LAA */
748+
is_write = 1;
749+
}
750+
break;
718751
}
752+
719753
return handle_cpu_signal(pc, info, is_write, &uc->uc_sigmask);
720754
}
721755

0 commit comments

Comments
 (0)