Browse Source

target/s390x/tcg: Fix and improve the SACF instruction

The SET ADDRESS SPACE CONTROL FAST instruction is not privileged, it can be
used from problem space, too. Just the switching to the home address space
is privileged and should still generate a privilege exception. This bug is
e.g. causing programs like Java that use the "getcpu" vdso kernel function
to crash (see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=990417#26 ).

While we're at it, also check if DAT is not enabled. In that case the
instruction is supposed to generate a special operation exception.

Resolves: https://gitlab.com/qemu-project/qemu/-/issues/655
Message-Id: <20221201184443.136355-1-thuth@redhat.com>
Reviewed-by: Ilya Leoshkevich <iii@linux.ibm.com>
Reviewed-by: David Hildenbrand <david@redhat.com>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Thomas Huth <thuth@redhat.com>
pull/228/head
Thomas Huth 3 years ago
parent
commit
21be74a9a5
  1. 7
      target/s390x/tcg/cc_helper.c
  2. 2
      target/s390x/tcg/insn-data.h.inc

7
target/s390x/tcg/cc_helper.c

@ -487,6 +487,10 @@ void HELPER(sacf)(CPUS390XState *env, uint64_t a1)
{
HELPER_LOG("%s: %16" PRIx64 "\n", __func__, a1);
if (!(env->psw.mask & PSW_MASK_DAT)) {
tcg_s390_program_interrupt(env, PGM_SPECIAL_OP, GETPC());
}
switch (a1 & 0xf00) {
case 0x000:
env->psw.mask &= ~PSW_MASK_ASC;
@ -497,6 +501,9 @@ void HELPER(sacf)(CPUS390XState *env, uint64_t a1)
env->psw.mask |= PSW_ASC_SECONDARY;
break;
case 0x300:
if ((env->psw.mask & PSW_MASK_PSTATE) != 0) {
tcg_s390_program_interrupt(env, PGM_PRIVILEGED, GETPC());
}
env->psw.mask &= ~PSW_MASK_ASC;
env->psw.mask |= PSW_ASC_HOME;
break;

2
target/s390x/tcg/insn-data.h.inc

@ -1365,7 +1365,7 @@
/* SERVICE CALL LOGICAL PROCESSOR (PV hypercall) */
F(0xb220, SERVC, RRE, Z, r1_o, r2_o, 0, 0, servc, 0, IF_PRIV | IF_IO)
/* SET ADDRESS SPACE CONTROL FAST */
F(0xb279, SACF, S, Z, 0, a2, 0, 0, sacf, 0, IF_PRIV)
C(0xb279, SACF, S, Z, 0, a2, 0, 0, sacf, 0)
/* SET CLOCK */
F(0xb204, SCK, S, Z, 0, m2_64a, 0, 0, sck, 0, IF_PRIV | IF_IO)
/* SET CLOCK COMPARATOR */

Loading…
Cancel
Save