* [PATCH v2 0/2] target/s390x: Make PRNO TRNG interruptible
@ 2026-07-14 19:17 Ilya Leoshkevich
2026-07-14 19:17 ` [PATCH v2 1/2] " Ilya Leoshkevich
2026-07-14 19:17 ` [PATCH v2 2/2] tests/tcg/s390x: Test PRNO TRNG interruptibility Ilya Leoshkevich
0 siblings, 2 replies; 5+ messages in thread
From: Ilya Leoshkevich @ 2026-07-14 19:17 UTC (permalink / raw)
To: Richard Henderson, Cornelia Huck, Eric Farman, Matthew Rosato
Cc: David Hildenbrand, qemu-s390x, qemu-devel, Harald Freudenberger,
Ilya Leoshkevich
v1: https://lore.kernel.org/qemu-devel/20260714113946.275122-1-iii@linux.ibm.com/
v1 -> v2: Use cpu_loop_exit_requested() (Richard).
Apply R-b, since the change is trivial enough.
Hi,
Christian has reported that one can make a TCG guest stuck by running
PRNO TRNG with a huge buffer. This series fixes this by making PRNO
TRNG end on cpu_loop_exit_requested().
Patch 1 is the fix, patch 2 is the test.
Cc: Harald, because this may conflict with the CPACF series.
Best regards,
Ilya
Ilya Leoshkevich (2):
target/s390x: Make PRNO TRNG interruptible
tests/tcg/s390x: Test PRNO TRNG interruptibility
target/s390x/tcg/crypto_helper.c | 22 ++++++++---
tests/tcg/s390x/Makefile.target | 1 +
tests/tcg/s390x/prno-trng.c | 67 ++++++++++++++++++++++++++++++++
3 files changed, 85 insertions(+), 5 deletions(-)
create mode 100644 tests/tcg/s390x/prno-trng.c
--
2.55.0
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH v2 1/2] target/s390x: Make PRNO TRNG interruptible 2026-07-14 19:17 [PATCH v2 0/2] target/s390x: Make PRNO TRNG interruptible Ilya Leoshkevich @ 2026-07-14 19:17 ` Ilya Leoshkevich 2026-07-22 9:30 ` Harald Freudenberger 2026-07-14 19:17 ` [PATCH v2 2/2] tests/tcg/s390x: Test PRNO TRNG interruptibility Ilya Leoshkevich 1 sibling, 1 reply; 5+ messages in thread From: Ilya Leoshkevich @ 2026-07-14 19:17 UTC (permalink / raw) To: Richard Henderson, Cornelia Huck, Eric Farman, Matthew Rosato Cc: David Hildenbrand, qemu-s390x, qemu-devel, Harald Freudenberger, Ilya Leoshkevich, Christian Borntraeger, qemu-stable fill_buf_random() writes the entire guest-requested amount of random bytes in one go. Since the length is a full 64-bit value, a guest can request several gigabytes and keep the vCPU spinning inside the helper, without a chance to react to interrupts. Do the same thing as HELPER(mvcl): check cpu_loop_exit_requested() at the bottom of the loop, and when a return to the main loop is pending, stop and report partial completion with condition code 3. Reported-by: Christian Borntraeger <borntraeger@linux.ibm.com> Fixes: 3dbc5fdacb5a ("target/s390x: support PRNO_TRNG instruction") Cc: qemu-stable@nongnu.org Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> --- target/s390x/tcg/crypto_helper.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/target/s390x/tcg/crypto_helper.c b/target/s390x/tcg/crypto_helper.c index 8fe0a222198..6a5dbe1cafa 100644 --- a/target/s390x/tcg/crypto_helper.c +++ b/target/s390x/tcg/crypto_helper.c @@ -16,6 +16,7 @@ #include "qemu/guest-random.h" #include "s390x-internal.h" #include "tcg_s390x.h" +#include "exec/cpu-common.h" #include "exec/helper-proto.h" #include "accel/tcg/cpu-ldst-common.h" #include "accel/tcg/cpu-mmu-index.h" @@ -242,8 +243,8 @@ static int cpacf_sha512(CPUS390XState *env, const int mmu_idx, uintptr_t ra, return !len ? 0 : 3; } -static void fill_buf_random(CPUS390XState *env, const int mmu_idx, uintptr_t ra, - uint64_t *buf_reg, uint64_t *len_reg) +static int fill_buf_random(CPUS390XState *env, const int mmu_idx, uintptr_t ra, + uint64_t *buf_reg, uint64_t *len_reg) { const MemOpIdx oi = make_memop_idx(MO_8, mmu_idx); uint8_t tmp[256]; @@ -265,7 +266,13 @@ static void fill_buf_random(CPUS390XState *env, const int mmu_idx, uintptr_t ra, --*len_reg; } len -= block; + + if (cpu_loop_exit_requested(env_cpu(env))) { + break; + } } + + return len == 0 ? 0 : 3; } uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3, @@ -278,6 +285,7 @@ uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3, uint8_t subfunc[16] = { 0 }; uint64_t param_addr; MemOpIdx oi; + int cc; switch (type) { case S390_FEAT_TYPE_KMAC: @@ -308,9 +316,13 @@ uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3, return cpacf_sha512(env, mmu_idx, ra, env->regs[1], &env->regs[r2], &env->regs[r2 + 1], type); case 114: /* CPACF_PRNO_TRNG */ - fill_buf_random(env, mmu_idx, ra, &env->regs[r1], &env->regs[r1 + 1]); - fill_buf_random(env, mmu_idx, ra, &env->regs[r2], &env->regs[r2 + 1]); - break; + cc = fill_buf_random(env, mmu_idx, ra, + &env->regs[r1], &env->regs[r1 + 1]); + if (cc == 0) { + cc = fill_buf_random(env, mmu_idx, ra, + &env->regs[r2], &env->regs[r2 + 1]); + } + return cc; default: /* we don't implement any other subfunction yet */ g_assert_not_reached(); -- 2.55.0 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 1/2] target/s390x: Make PRNO TRNG interruptible 2026-07-14 19:17 ` [PATCH v2 1/2] " Ilya Leoshkevich @ 2026-07-22 9:30 ` Harald Freudenberger 0 siblings, 0 replies; 5+ messages in thread From: Harald Freudenberger @ 2026-07-22 9:30 UTC (permalink / raw) To: Ilya Leoshkevich Cc: Richard Henderson, Cornelia Huck, Eric Farman, Matthew Rosato, David Hildenbrand, qemu-s390x, qemu-devel, Christian Borntraeger, qemu-stable On 2026-07-14 21:17, Ilya Leoshkevich wrote: > fill_buf_random() writes the entire guest-requested amount of random > bytes in one go. Since the length is a full 64-bit value, a guest can > request several gigabytes and keep the vCPU spinning inside the helper, > without a chance to react to interrupts. > > Do the same thing as HELPER(mvcl): check cpu_loop_exit_requested() at > the > bottom of the loop, and when a return to the main loop is pending, stop > and report partial completion with condition code 3. > > Reported-by: Christian Borntraeger <borntraeger@linux.ibm.com> > Fixes: 3dbc5fdacb5a ("target/s390x: support PRNO_TRNG instruction") > Cc: qemu-stable@nongnu.org > Reviewed-by: Richard Henderson <richard.henderson@linaro.org> > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> > --- > target/s390x/tcg/crypto_helper.c | 22 +++++++++++++++++----- > 1 file changed, 17 insertions(+), 5 deletions(-) > > diff --git a/target/s390x/tcg/crypto_helper.c > b/target/s390x/tcg/crypto_helper.c > index 8fe0a222198..6a5dbe1cafa 100644 > --- a/target/s390x/tcg/crypto_helper.c > +++ b/target/s390x/tcg/crypto_helper.c > @@ -16,6 +16,7 @@ > #include "qemu/guest-random.h" > #include "s390x-internal.h" > #include "tcg_s390x.h" > +#include "exec/cpu-common.h" > #include "exec/helper-proto.h" > #include "accel/tcg/cpu-ldst-common.h" > #include "accel/tcg/cpu-mmu-index.h" > @@ -242,8 +243,8 @@ static int cpacf_sha512(CPUS390XState *env, const > int mmu_idx, uintptr_t ra, > return !len ? 0 : 3; > } > > -static void fill_buf_random(CPUS390XState *env, const int mmu_idx, > uintptr_t ra, > - uint64_t *buf_reg, uint64_t *len_reg) > +static int fill_buf_random(CPUS390XState *env, const int mmu_idx, > uintptr_t ra, > + uint64_t *buf_reg, uint64_t *len_reg) > { > const MemOpIdx oi = make_memop_idx(MO_8, mmu_idx); > uint8_t tmp[256]; > @@ -265,7 +266,13 @@ static void fill_buf_random(CPUS390XState *env, > const int mmu_idx, uintptr_t ra, > --*len_reg; > } > len -= block; > + > + if (cpu_loop_exit_requested(env_cpu(env))) { > + break; > + } > } > + > + return len == 0 ? 0 : 3; > } > > uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, > uint32_t r3, > @@ -278,6 +285,7 @@ uint32_t HELPER(msa)(CPUS390XState *env, uint32_t > r1, uint32_t r2, uint32_t r3, > uint8_t subfunc[16] = { 0 }; > uint64_t param_addr; > MemOpIdx oi; > + int cc; > > switch (type) { > case S390_FEAT_TYPE_KMAC: > @@ -308,9 +316,13 @@ uint32_t HELPER(msa)(CPUS390XState *env, uint32_t > r1, uint32_t r2, uint32_t r3, > return cpacf_sha512(env, mmu_idx, ra, env->regs[1], > &env->regs[r2], > &env->regs[r2 + 1], type); > case 114: /* CPACF_PRNO_TRNG */ > - fill_buf_random(env, mmu_idx, ra, &env->regs[r1], > &env->regs[r1 + 1]); > - fill_buf_random(env, mmu_idx, ra, &env->regs[r2], > &env->regs[r2 + 1]); > - break; > + cc = fill_buf_random(env, mmu_idx, ra, > + &env->regs[r1], &env->regs[r1 + 1]); > + if (cc == 0) { > + cc = fill_buf_random(env, mmu_idx, ra, > + &env->regs[r2], &env->regs[r2 + 1]); > + } > + return cc; > default: > /* we don't implement any other subfunction yet */ > g_assert_not_reached(); Reviewed-by: Harald Freudenberger <freude@linux.ibm.com> ^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v2 2/2] tests/tcg/s390x: Test PRNO TRNG interruptibility 2026-07-14 19:17 [PATCH v2 0/2] target/s390x: Make PRNO TRNG interruptible Ilya Leoshkevich 2026-07-14 19:17 ` [PATCH v2 1/2] " Ilya Leoshkevich @ 2026-07-14 19:17 ` Ilya Leoshkevich 2026-07-22 9:31 ` Harald Freudenberger 1 sibling, 1 reply; 5+ messages in thread From: Ilya Leoshkevich @ 2026-07-14 19:17 UTC (permalink / raw) To: Richard Henderson, Cornelia Huck, Eric Farman, Matthew Rosato Cc: David Hildenbrand, qemu-s390x, qemu-devel, Harald Freudenberger, Ilya Leoshkevich Add a small test that issues a large PRNO TRNG request while a timer is running, and checks that the timer interrupts it several times. Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> --- tests/tcg/s390x/Makefile.target | 1 + tests/tcg/s390x/prno-trng.c | 67 +++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) create mode 100644 tests/tcg/s390x/prno-trng.c diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target index 0ca030ded01..48cba4cdfa4 100644 --- a/tests/tcg/s390x/Makefile.target +++ b/tests/tcg/s390x/Makefile.target @@ -75,6 +75,7 @@ Z13_TESTS+=vcksm Z13_TESTS+=vstl Z13_TESTS+=vrep Z13_TESTS+=precise-smc-user +Z13_TESTS+=prno-trng $(Z13_TESTS): CFLAGS+=-march=z13 -O2 TESTS+=$(Z13_TESTS) diff --git a/tests/tcg/s390x/prno-trng.c b/tests/tcg/s390x/prno-trng.c new file mode 100644 index 00000000000..43eea5db1dc --- /dev/null +++ b/tests/tcg/s390x/prno-trng.c @@ -0,0 +1,67 @@ +/* + * Test that PERFORM RANDOM NUMBER OPERATION TRNG is interruptible. + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ +#include <assert.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/time.h> +#include <asm/ucontext.h> + +static unsigned char buf1[16 * 1024 * 1024]; +static unsigned char buf2[16 * 1024 * 1024]; + +static volatile sig_atomic_t interrupted; + +static void sigprof_handler(int sig, siginfo_t *info, void *ucontext) +{ + struct ucontext *uc = ucontext; + unsigned long addr = uc->uc_mcontext.regs.psw.addr; + + if (*(unsigned short *)(addr - 4) == 0xb93c) { + interrupted++; + } +} + +static void prno_trng(void *b1, unsigned long l1, void *b2, unsigned long l2) +{ + register unsigned long r0 asm("r0") = 114; /* TRNG */ + register unsigned long r2 asm("r2") = (unsigned long)b1; + register unsigned long r3 asm("r3") = l1; + register unsigned long r4 asm("r4") = (unsigned long)b2; + register unsigned long r5 asm("r5") = l2; + + asm volatile("0: ppno %[r2],%[r4]\n" /* prno alias for old toolchains */ + " jo 0b" + : [r2] "+r" (r2), [r3] "+r" (r3) + , [r4] "+r" (r4), [r5] "+r" (r5) + : "r" (r0) + : "cc", "memory"); +} + +int main(void) +{ + struct itimerval it = { + .it_interval = { .tv_usec = 10000 }, /* 0.01s */ + .it_value = { .tv_usec = 10000 }, + }; + struct sigaction act = { + .sa_sigaction = sigprof_handler, + .sa_flags = SA_SIGINFO, + }; + int err; + + err = sigaction(SIGPROF, &act, NULL); + assert(err == 0); + err = setitimer(ITIMER_PROF, &it, NULL); + assert(err == 0); + + prno_trng(buf1, sizeof(buf1), buf2, sizeof(buf2)); + printf("interrupted %d times\n", interrupted); + assert(interrupted >= 3); + + return EXIT_SUCCESS; +} -- 2.55.0 ^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v2 2/2] tests/tcg/s390x: Test PRNO TRNG interruptibility 2026-07-14 19:17 ` [PATCH v2 2/2] tests/tcg/s390x: Test PRNO TRNG interruptibility Ilya Leoshkevich @ 2026-07-22 9:31 ` Harald Freudenberger 0 siblings, 0 replies; 5+ messages in thread From: Harald Freudenberger @ 2026-07-22 9:31 UTC (permalink / raw) To: Ilya Leoshkevich Cc: Richard Henderson, Cornelia Huck, Eric Farman, Matthew Rosato, David Hildenbrand, qemu-s390x, qemu-devel On 2026-07-14 21:17, Ilya Leoshkevich wrote: > Add a small test that issues a large PRNO TRNG request while a timer is > running, and checks that the timer interrupts it several times. > > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com> > --- > tests/tcg/s390x/Makefile.target | 1 + > tests/tcg/s390x/prno-trng.c | 67 +++++++++++++++++++++++++++++++++ > 2 files changed, 68 insertions(+) > create mode 100644 tests/tcg/s390x/prno-trng.c > > diff --git a/tests/tcg/s390x/Makefile.target > b/tests/tcg/s390x/Makefile.target > index 0ca030ded01..48cba4cdfa4 100644 > --- a/tests/tcg/s390x/Makefile.target > +++ b/tests/tcg/s390x/Makefile.target > @@ -75,6 +75,7 @@ Z13_TESTS+=vcksm > Z13_TESTS+=vstl > Z13_TESTS+=vrep > Z13_TESTS+=precise-smc-user > +Z13_TESTS+=prno-trng > $(Z13_TESTS): CFLAGS+=-march=z13 -O2 > TESTS+=$(Z13_TESTS) > > diff --git a/tests/tcg/s390x/prno-trng.c b/tests/tcg/s390x/prno-trng.c > new file mode 100644 > index 00000000000..43eea5db1dc > --- /dev/null > +++ b/tests/tcg/s390x/prno-trng.c > @@ -0,0 +1,67 @@ > +/* > + * Test that PERFORM RANDOM NUMBER OPERATION TRNG is interruptible. > + * > + * SPDX-License-Identifier: GPL-2.0-or-later > + */ > +#include <assert.h> > +#include <signal.h> > +#include <stdio.h> > +#include <stdlib.h> > +#include <string.h> > +#include <sys/time.h> > +#include <asm/ucontext.h> > + > +static unsigned char buf1[16 * 1024 * 1024]; > +static unsigned char buf2[16 * 1024 * 1024]; > + > +static volatile sig_atomic_t interrupted; > + > +static void sigprof_handler(int sig, siginfo_t *info, void *ucontext) > +{ > + struct ucontext *uc = ucontext; > + unsigned long addr = uc->uc_mcontext.regs.psw.addr; > + > + if (*(unsigned short *)(addr - 4) == 0xb93c) { > + interrupted++; > + } > +} > + > +static void prno_trng(void *b1, unsigned long l1, void *b2, unsigned > long l2) > +{ > + register unsigned long r0 asm("r0") = 114; /* TRNG */ > + register unsigned long r2 asm("r2") = (unsigned long)b1; > + register unsigned long r3 asm("r3") = l1; > + register unsigned long r4 asm("r4") = (unsigned long)b2; > + register unsigned long r5 asm("r5") = l2; > + > + asm volatile("0: ppno %[r2],%[r4]\n" /* prno alias for old > toolchains */ > + " jo 0b" > + : [r2] "+r" (r2), [r3] "+r" (r3) > + , [r4] "+r" (r4), [r5] "+r" (r5) > + : "r" (r0) > + : "cc", "memory"); > +} > + > +int main(void) > +{ > + struct itimerval it = { > + .it_interval = { .tv_usec = 10000 }, /* 0.01s */ > + .it_value = { .tv_usec = 10000 }, > + }; > + struct sigaction act = { > + .sa_sigaction = sigprof_handler, > + .sa_flags = SA_SIGINFO, > + }; > + int err; > + > + err = sigaction(SIGPROF, &act, NULL); > + assert(err == 0); > + err = setitimer(ITIMER_PROF, &it, NULL); > + assert(err == 0); > + > + prno_trng(buf1, sizeof(buf1), buf2, sizeof(buf2)); > + printf("interrupted %d times\n", interrupted); > + assert(interrupted >= 3); > + > + return EXIT_SUCCESS; > +} Reviewed-by: Harald Freudenberger <freude@linux.ibm.com> ^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-07-22 9:31 UTC | newest] Thread overview: 5+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-07-14 19:17 [PATCH v2 0/2] target/s390x: Make PRNO TRNG interruptible Ilya Leoshkevich 2026-07-14 19:17 ` [PATCH v2 1/2] " Ilya Leoshkevich 2026-07-22 9:30 ` Harald Freudenberger 2026-07-14 19:17 ` [PATCH v2 2/2] tests/tcg/s390x: Test PRNO TRNG interruptibility Ilya Leoshkevich 2026-07-22 9:31 ` Harald Freudenberger
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.