@samitouri / QOSamiQemu / commits / aae77f5ddd

target/s390x: Make PRNO TRNG interruptible

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> Reviewed-by: Harald Freudenberger <freude@linux.ibm.com> Link: https://lore.kernel.org/qemu-devel/20260714191948.342204-2-iii@linux.ibm.com Signed-off-by: Eric Farman <farman@linux.ibm.com>

Ilya Leoshkevich committed Jul 14, 2026 at 21:17 UTC aae77f5dddef62da7e1479c257d99d2ab574df56
1 file changed +17 -5
target/s390x/tcg/crypto_helper.c
+17 -5
@@ -16,6 +16,7 @@
16 #include "qemu/guest-random.h"
17 #include "s390x-internal.h"
18 #include "tcg_s390x.h"
19 +#include "exec/cpu-common.h"
20 #include "exec/helper-proto.h"
21 #include "accel/tcg/cpu-ldst-common.h"
22 #include "accel/tcg/cpu-mmu-index.h"
@@ -242,8 +243,8 @@ static int cpacf_sha512(CPUS390XState *env, const int mmu_idx, uintptr_t ra,
243 return !len ? 0 : 3;
244 }
245
245 -static void fill_buf_random(CPUS390XState *env, const int mmu_idx, uintptr_t ra,
246 - uint64_t *buf_reg, uint64_t *len_reg)
246 +static int fill_buf_random(CPUS390XState *env, const int mmu_idx, uintptr_t ra,
247 + uint64_t *buf_reg, uint64_t *len_reg)
248 {
249 const MemOpIdx oi = make_memop_idx(MO_8, mmu_idx);
250 uint8_t tmp[256];
@@ -265,7 +266,13 @@ static void fill_buf_random(CPUS390XState *env, const int mmu_idx, uintptr_t ra,
266 --*len_reg;
267 }
268 len -= block;
269 +
270 + if (cpu_loop_exit_requested(env_cpu(env))) {
271 + break;
272 + }
273 }
274 +
275 + return len == 0 ? 0 : 3;
276 }
277
278 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,
285 uint8_t subfunc[16] = { 0 };
286 uint64_t param_addr;
287 MemOpIdx oi;
288 + int cc;
289
290 switch (type) {
291 case S390_FEAT_TYPE_KMAC:
@@ -308,9 +316,13 @@ uint32_t HELPER(msa)(CPUS390XState *env, uint32_t r1, uint32_t r2, uint32_t r3,
316 return cpacf_sha512(env, mmu_idx, ra, env->regs[1], &env->regs[r2],
317 &env->regs[r2 + 1], type);
318 case 114: /* CPACF_PRNO_TRNG */
311 - fill_buf_random(env, mmu_idx, ra, &env->regs[r1], &env->regs[r1 + 1]);
312 - fill_buf_random(env, mmu_idx, ra, &env->regs[r2], &env->regs[r2 + 1]);
313 - break;
319 + cc = fill_buf_random(env, mmu_idx, ra,
320 + &env->regs[r1], &env->regs[r1 + 1]);
321 + if (cc == 0) {
322 + cc = fill_buf_random(env, mmu_idx, ra,
323 + &env->regs[r2], &env->regs[r2 + 1]);
324 + }
325 + return cc;
326 default:
327 /* we don't implement any other subfunction yet */
328 g_assert_not_reached();