qemu-ppc
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] target/ppc: Implement new wait variants


From: Nicholas Piggin
Subject: Re: [PATCH] target/ppc: Implement new wait variants
Date: Wed, 20 Jul 2022 20:08:10 +1000

Excerpts from Víctor Colombo's message of July 20, 2022 12:20 am:
> Hello Nicholas,
> 
> On 19/07/2022 08:38, Nicholas Piggin wrote:
>> ISA v2.06 adds new variations of wait, specified by the WC field. These
>> are not compatible with the wait 0 implementation, because they add
>> additional conditions that cause the processor to resume, which can
>> cause software to hang or run very slowly.
>> 
>> ISA v3.0 changed the wait opcode.
>> 
>> ISA v3.1 added new WC values to the new wait opcode, and added a PL
>> field.
>> 
>> This implements the new wait encoding and supports WC variants with
>> no-op implementations, which is provides basic correctness as explained.
>> 
>> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
>> ---
>>   target/ppc/translate.c | 84 ++++++++++++++++++++++++++++++++++++++----
>>   1 file changed, 76 insertions(+), 8 deletions(-)
>> 
>> diff --git a/target/ppc/translate.c b/target/ppc/translate.c
>> index 1d6daa4608..ce4aa84f1d 100644
>> --- a/target/ppc/translate.c
>> +++ b/target/ppc/translate.c
>> @@ -4066,12 +4066,79 @@ static void gen_sync(DisasContext *ctx)
>>   /* wait */
>>   static void gen_wait(DisasContext *ctx)
>>   {
>> -    TCGv_i32 t0 = tcg_const_i32(1);
>> -    tcg_gen_st_i32(t0, cpu_env,
>> -                   -offsetof(PowerPCCPU, env) + offsetof(CPUState, halted));
>> -    tcg_temp_free_i32(t0);
>> -    /* Stop translation, as the CPU is supposed to sleep from now */
>> -    gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
>> +    uint32_t wc = (ctx->opcode >> 21) & 3;
>> +    uint32_t pl = (ctx->opcode >> 16) & 3;
> 
> I think the best here would be to move this instruction to decodetree.
> However, this can be a bit of extra work and out of the scope you though
> for this patch.

Yeah you're probably right. I haven't looked into decodetree yet sorry,
if we could get this in first would be convenient.

> What do you think about adding a EXTRACT_HELPER to
> target/ppc/internal.h?

Just to avoid open coded extraction here? Probably a good idea, I'll try
it.

>> +
>> +    /* v3.0 and later use the ISA flag for wait rather than a PM flag */
>> +    if (!(ctx->insns_flags2 & PPC2_PM_ISA206) &&
>> +        !(ctx->insns_flags2 & PPC2_ISA300)) {
>> +        /* wc field was introduced in ISA v2.06 */
>> +        if (wc) {
>> +            gen_invalid(ctx);
>> +            return;
>> +        }
>> +    }
>> +
>> +    if (!(ctx->insns_flags2 & PPC2_ISA310)) {
>> +        /* pl field was introduced in ISA v3.1 */
>> +        if (pl) {
>> +            gen_invalid(ctx);
>> +            return;
>> +        }
> 
> IIUC the ISA says that "Reserved fields in instructions are ignored by
> the processor". So this check is incorrect, I guess, as we should allow
> the instruction to continue.

Hmm, I think you're right.

>> +
>> +        if (ctx->insns_flags2 & PPC2_ISA300) {
>> +            /* wc > 0 is reserved in v3.0 */
>> +            if (wc > 0) {
> 
> This however is correct
> 
>> +                gen_invalid(ctx);
>> +                return;
>> +            }
>> +        }
>> +    }
>> +
>> +    /* wc=3 is reserved and pl=1-3 are reserved in v3.1. */
>> +    if (wc == 3 || pl > 0) {
> 
> This can cause a situation where the field is reserve in a previous ISA
> and should be ignored. I think the best option is to put these checks
> inside a conditional for each different ISA. Otherwise it's getting a
> bit hard to follow what should happen in each situation.

Good idea.

> 
>> +        gen_invalid(ctx);
>> +        return;
>> +    }
>> +
>> +    /* wait 0 waits for an exception to occur. */
>> +    if (wc == 0) {
>> +        TCGv_i32 t0 = tcg_const_i32(1);
>> +        tcg_gen_st_i32(t0, cpu_env,
>> +                       -offsetof(PowerPCCPU, env) + offsetof(CPUState, 
>> halted));
>> +        tcg_temp_free_i32(t0);
>> +        /* Stop translation, as the CPU is supposed to sleep from now */
>> +        gen_exception_nip(ctx, EXCP_HLT, ctx->base.pc_next);
>> +    }
>> +
>> +    /*
>> +     * Other wait types must not just wait until an exception occurs because
>> +     * ignoring their other wake-up conditions could cause a hang.
>> +     *
>> +     * For v2.06 and 2.07, wc=1,2 are architected but may be implemented as
>> +     * no-ops.
>> +     *
>> +     * wc=1 (waitrsv) waits for an exception or a reservation to be lost.
>> +     * Reservation-loss may have implementation-specific conditions, so it
>> +     * can be implemented as a no-op.
>> +     *
>> +     * wc=2 waits for an implementation-specific condition which could be
>> +     * always true, so it can be implemented as a no-op.
>> +     *
>> +     * For v3.1, wc=1,2 are architected but may be implemented as no-ops.
>> +     *
>> +     * wc=1 similarly to v2.06 and v2.07.
>> +     *
>> +     * wc=2 waits for an exception or an amount of time to pass. This
>> +     * amount is implementation-specific so it can be implemented as a
>> +     * no-op.
>> +     *
>> +     * ISA v3.1 does allow for execution to resume "in the rare case of
>> +     * an implementation-dependent event", so in any case software must
>> +     * not depend on the architected resumption condition to become
>> +     * true, so no-op implementations should be architecturally correct
>> +     * (if suboptimal).
>> +     */
>>   }
>> 
>>   #if defined(TARGET_PPC64)
>> @@ -6852,8 +6919,9 @@ GEN_HANDLER2(stdcx_, "stdcx.", 0x1F, 0x16, 0x06, 
>> 0x00000000, PPC_64B),
>>   GEN_HANDLER_E(stqcx_, 0x1F, 0x16, 0x05, 0, PPC_NONE, PPC2_LSQ_ISA207),
>>   #endif
>>   GEN_HANDLER(sync, 0x1F, 0x16, 0x12, 0x039FF801, PPC_MEM_SYNC),
>> -GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x03FFF801, PPC_WAIT),
>> -GEN_HANDLER_E(wait, 0x1F, 0x1E, 0x00, 0x039FF801, PPC_NONE, PPC2_ISA300),
>> +/* ISA v3.0 changed the extended opcode from 62 to 30 */
>> +GEN_HANDLER(wait, 0x1F, 0x1E, 0x01, 0x039FF801, PPC_WAIT),
>> +GEN_HANDLER_E(wait, 0x1F, 0x1E, 0x00, 0x039CF801, PPC_NONE, PPC2_ISA300),
> 
> Does this continue to work for the previous ISAs? I'm having a hard time
> testing this instruction for previous cpus, even without this patch

I don't think I tested that actually. I will.

Thanks for the review, I'll make updates and post a new vesion.

Thanks,
Nick



reply via email to

[Prev in Thread] Current Thread [Next in Thread]