@samitouri / QOSamiQemu / commits / c07bff60b8

target/ppc: Move wait instruction to decodetree

Implement wait instruction using decodetree with proper handling of WC and PL fields across different ISA versions. Since the opcode changed between ISA 2.x and 3.x we have defined 2 different decodetree instructions that are handled by the same helper. The changes have been tested by comparing the tcg generated before and after the change for wait instruction. The test was repeated for 2 types of machines: Power10 - which should use the newer wait implementation e500mc - which should use older PPC_WAIT implementation Both generated the same tcg ops with and without the change. Further, with the changes we were able to boot into Fedora distro as well. Signed-off-by: Ojaswin Mujoo <ojaswin@linux.ibm.com> Reviewed-by: Glenn Miles <milesg@linux.ibm.com> Reviewed-by: Amit Machhiwal <amachhiw@linux.ibm.com> Signed-off-by: Chinmay Rath <rathc@linux.ibm.com> Tested-by: Aniket Sahu <asahu1x@linux.ibm.com> Link: https://lore.kernel.org/qemu-devel/20260827133010.278889-18-rathc@linux.ibm.com Signed-off-by: Harsh Prateek Bora <harshpb@linux.ibm.com>

Ojaswin Mujoo committed Aug 27, 2026 at 18:59 UTC c07bff60b8fcae5e305c912591732e1b13f5c274
3 files changed +114 -91
target/ppc/insn32.decode
+15
@@ -1478,6 +1478,21 @@ ISYNC 010011 ----- ----- ----- 0010010110 -
1478 @XL_bfa ...... bf:3 .. bfa:3 .. ..... ..... ..... .
1479 MCRF 010011 ... -- ... -- ----- 00000 00000 - @XL_bfa
1480
1481 +# Wait Instructions
1482 +
1483 +# We can use the same X_wait argument set for both WAIT and older ISA2.x
1484 +# compliant WAIT_2_x. Depending on the version, we may or may not use the
1485 +# arguments. For more information, check do_wait() helper.
1486 +
1487 +&X_wait wc pl
1488 +@X_wait ...... ..- wc:2 --- pl:2 ----- .......... - &X_wait
1489 +
1490 +# According to ISA v3.1, bit 6 and 7 are implementation dependent and "unless
1491 +# the intention is to use the implementation-dependent field, these bits must be
1492 +# coded zero". Hence, we code them to 0.
1493 +WAIT 011111 00-.. ---.. ----- 0000011110 - @X_wait
1494 +WAIT_ISA_2_X 011111 ---.. ---.. ----- 0000111110 - @X_wait
1495 +
1496 # Branch History Rolling Buffer (BHRB) Instructions
1497
1498 &XFX_bhrbe rt bhrbe
target/ppc/translate.c
-91
@@ -2727,95 +2727,6 @@ static inline void gen_check_tlb_flush(DisasContext *ctx, bool global)
2727 static inline void gen_check_tlb_flush(DisasContext *ctx, bool global) { }
2728 #endif
2729
2730 -/* wait */
2731 -static void gen_wait(DisasContext *ctx)
2732 -{
2733 - uint32_t wc;
2734 -
2735 - if (ctx->insns_flags & PPC_WAIT) {
2736 - /* v2.03-v2.07 define an older incompatible 'wait' encoding. */
2737 -
2738 - if (ctx->insns_flags2 & PPC2_PM_ISA206) {
2739 - /* v2.06 introduced the WC field. WC > 0 may be treated as no-op. */
2740 - wc = WC(ctx->opcode);
2741 - } else {
2742 - wc = 0;
2743 - }
2744 -
2745 - } else if (ctx->insns_flags2 & PPC2_ISA300) {
2746 - /* v3.0 defines a new 'wait' encoding. */
2747 - wc = WC(ctx->opcode);
2748 - if (ctx->insns_flags2 & PPC2_ISA310) {
2749 - uint32_t pl = PL(ctx->opcode);
2750 -
2751 - /* WC 1,2 may be treated as no-op. WC 3 is reserved. */
2752 - if (wc == 3) {
2753 - gen_invalid(ctx);
2754 - return;
2755 - }
2756 -
2757 - /* PL 1-3 are reserved. If WC=2 then the insn is treated as noop. */
2758 - if (pl > 0 && wc != 2) {
2759 - gen_invalid(ctx);
2760 - return;
2761 - }
2762 -
2763 - } else { /* ISA300 */
2764 - /* WC 1-3 are reserved */
2765 - if (wc > 0) {
2766 - gen_invalid(ctx);
2767 - return;
2768 - }
2769 - }
2770 -
2771 - } else {
2772 - warn_report("wait instruction decoded with wrong ISA flags.");
2773 - gen_invalid(ctx);
2774 - return;
2775 - }
2776 -
2777 - /*
2778 - * wait without WC field or with WC=0 waits for an exception / interrupt
2779 - * to occur.
2780 - */
2781 - if (wc == 0) {
2782 - TCGv_i32 t0 = tcg_constant_i32(1);
2783 - tcg_gen_st_i32(t0, tcg_env,
2784 - -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
2785 - /* Stop translation, as the CPU is supposed to sleep from now */
2786 - gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
2787 - }
2788 -
2789 - /*
2790 - * Other wait types must not just wait until an exception occurs because
2791 - * ignoring their other wake-up conditions could cause a hang.
2792 - *
2793 - * For v2.06 and 2.07, wc=1,2,3 are architected but may be implemented as
2794 - * no-ops.
2795 - *
2796 - * wc=1 and wc=3 explicitly allow the instruction to be treated as a no-op.
2797 - *
2798 - * wc=2 waits for an implementation-specific condition, such could be
2799 - * always true, so it can be implemented as a no-op.
2800 - *
2801 - * For v3.1, wc=1,2 are architected but may be implemented as no-ops.
2802 - *
2803 - * wc=1 (waitrsv) waits for an exception or a reservation to be lost.
2804 - * Reservation-loss may have implementation-specific conditions, so it
2805 - * can be implemented as a no-op.
2806 - *
2807 - * wc=2 waits for an exception or an amount of time to pass. This
2808 - * amount is implementation-specific so it can be implemented as a
2809 - * no-op.
2810 - *
2811 - * ISA v3.1 allows for execution to resume "in the rare case of
2812 - * an implementation-dependent event", so in any case software must
2813 - * not depend on the architected resumption condition to become
2814 - * true, so no-op implementations should be architecturally correct
2815 - * (if suboptimal).
2816 - */
2817 -}
2818 -
2730 #if defined(TARGET_PPC64)
2731 static void gen_doze(DisasContext *ctx)
2732 {
@@ -5184,8 +5095,6 @@ GEN_HANDLER(lswx, 0x1F, 0x15, 0x10, 0x00000001, PPC_STRING),
5095 GEN_HANDLER(stswi, 0x1F, 0x15, 0x16, 0x00000001, PPC_STRING),
5096 GEN_HANDLER(stswx, 0x1F, 0x15, 0x14, 0x00000001, PPC_STRING),
5097 /* ISA v3.0 changed the extended opcode from 62 to 30 */
5187 -GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x039FF801, PPC_WAIT),
5188 -GEN_HANDLER_E(wait, 0x1F, 0x1E, 0x00, 0x039CF801, PPC_NONE, PPC2_ISA300),
5098 GEN_HANDLER(rfi, 0x13, 0x12, 0x01, 0x03FF8001, PPC_FLOW),
5099 #if defined(TARGET_PPC64)
5100 GEN_HANDLER(rfid, 0x13, 0x12, 0x00, 0x03FF8001, PPC_64B),
target/ppc/translate/storage-ctrl-impl.c.inc
+99
@@ -270,3 +270,102 @@ static bool do_tlbie(DisasContext *ctx, arg_X_tlbie *a, bool local)
270
271 TRANS_FLAGS(MEM_TLBIE, TLBIE, do_tlbie, false)
272 TRANS_FLAGS(MEM_TLBIE, TLBIEL, do_tlbie, true)
273 +
274 +/*
275 + * Decodetree populates a->wc and a->pl based on ISA v3.1, however they may
276 + * or may not be used based on the ISA:
277 + * For ISA < 2.06 - both wc and pl are ignored
278 + * For ISA == 2.06, 2.07, 3.0 - wc is used and pl is ignored
279 + * For ISA 3.1 - both wc and pl are used
280 + */
281 +static bool do_wait(DisasContext *ctx, arg_X_wait *a)
282 +{
283 + uint32_t wc;
284 +
285 + if (ctx->insns_flags & PPC_WAIT) {
286 + /* v2.03-v2.07 define an older incompatible 'wait' encoding. */
287 +
288 + if (ctx->insns_flags2 & PPC2_PM_ISA206) {
289 + /* v2.06 introduced the WC field. WC > 0 may be treated as no-op. */
290 + wc = a->wc;
291 + } else {
292 + wc = 0;
293 + }
294 +
295 + } else if (ctx->insns_flags2 & PPC2_ISA300) {
296 + /* v3.0 defines a new 'wait' encoding. */
297 + wc = a->wc;
298 + if (ctx->insns_flags2 & PPC2_ISA310) {
299 + uint32_t pl = a->pl;
300 +
301 + /* WC 1,2 may be treated as no-op. WC 3 is reserved. */
302 + if (wc == 3) {
303 + gen_invalid(ctx);
304 + return true;
305 + }
306 +
307 + /* PL 1-3 are reserved. If WC=2 then the insn is treated as noop. */
308 + if (pl > 0 && wc != 2) {
309 + gen_invalid(ctx);
310 + return true;
311 + }
312 +
313 + } else { /* ISA300 */
314 + /* WC 1-3 are reserved */
315 + if (wc > 0) {
316 + gen_invalid(ctx);
317 + return true;
318 + }
319 + }
320 +
321 + } else {
322 + warn_report("wait instruction decoded with wrong ISA flags.");
323 + gen_invalid(ctx);
324 + return true;
325 + }
326 +
327 + /*
328 + * wait without WC field or with WC=0 waits for an exception / interrupt
329 + * to occur.
330 + */
331 + if (wc == 0) {
332 + TCGv_i32 t0 = tcg_constant_i32(1);
333 + tcg_gen_st_i32(t0, tcg_env,
334 + -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
335 + /* Stop translation, as the CPU is supposed to sleep from now */
336 + gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
337 + }
338 +
339 + /*
340 + * Other wait types must not just wait until an exception occurs because
341 + * ignoring their other wake-up conditions could cause a hang.
342 + *
343 + * For v2.06 and 2.07, wc=1,2,3 are architected but may be implemented as
344 + * no-ops.
345 + *
346 + * wc=1 and wc=3 explicitly allow the instruction to be treated as a no-op.
347 + *
348 + * wc=2 waits for an implementation-specific condition, such could be
349 + * always true, so it can be implemented as a no-op.
350 + *
351 + * For v3.1, wc=1,2 are architected but may be implemented as no-ops.
352 + *
353 + * wc=1 (waitrsv) waits for an exception or a reservation to be lost.
354 + * Reservation-loss may have implementation-specific conditions, so it
355 + * can be implemented as a no-op.
356 + *
357 + * wc=2 waits for an exception or an amount of time to pass. This
358 + * amount is implementation-specific so it can be implemented as a
359 + * no-op.
360 + *
361 + * ISA v3.1 allows for execution to resume "in the rare case of
362 + * an implementation-dependent event", so in any case software must
363 + * not depend on the architected resumption condition to become
364 + * true, so no-op implementations should be architecturally correct
365 + * (if suboptimal).
366 + */
367 + return true;
368 +}
369 +
370 +TRANS_FLAGS(WAIT, WAIT_ISA_2_X, do_wait)
371 +TRANS_FLAGS2(ISA300, WAIT, do_wait)