Re: [PATCH v3 1/5] powerpc/rtas: Handle ibm,open-errinjct return format

Narayana Murty N <[email protected]>
Newsgroups gmane.linux.ports.ppc.embedded
Message-ID <410a3225-3ec8-408d-af93-15f7cc6f1629__36984.9755241134$1788187656$gmane$org@linux.ibm.com>
Hi Sourabh,

Thanks for the review.

On 04/08/26 11:22 AM, Sourabh Jain wrote:
> 
> 
> On 21/07/26 09:08, Narayana Murty N wrote:
>> PAPR specifies that ibm,open-errinjct has a unique return-cell layout:
>>
>>    rets[0] = injection session token (output parameter)
>>    rets[1] = status code
>>
>> This differs from every other RTAS call, where:
>>
>>    rets[0] = status code
>>    rets[1..] = output parameters
>>
>> As a result, the existing rtas_call() convention — return value is the
>> RTAS status, outputs[] receives the non-status output values — must be
>> preserved while correctly extracting status from rets[1] for this one
>> call.
>>
>> Add rtas_token_is_open_errinjct() and rtas_status_from_args() helpers.
>> rtas_status_from_args() selects the correct status cell based on the
>> token, and the output-copy loop in rtas_call() is updated so that for
>> ibm,open-errinjct:
>>
>>    rtas_call() return = rets[1]   (RTAS status)
>>    outputs[0]        = rets[0]   (session token)
>>
>> For all other calls the behaviour is unchanged: return value is rets[0]
>> and outputs[] receives rets[1..nret-1].
>>
>> The sys_rtas userspace path is not modified: copy_to_user() still
>> copies raw RTAS return cells (rets[0..nret-1]) to userspace.
>>
>> Callers passing a single output int (nret == 2) are safe because we
>> write at most nret-1 values into outputs[], never all nret cells.
>>
>> Also move the '/* A -1 return code...*/' comment to immediately precede
>> the if (ret == -1) check it describes, and remove the redundant stale
>> else branch that re-assigned ret.
>>
>> Reference: OpenPOWER PAPR documentation
>>             https://files.openpower.foundation/s/XFgfMaqLMD5Bcm8
>>
>> Signed-off-by: Narayana Murty N <[email protected]>
>> ---
>>   arch/powerpc/kernel/rtas.c | 51 ++++++++++++++++++++++++++++++++------
>>   1 file changed, 44 insertions(+), 7 deletions(-)
>>
>> diff --git a/arch/powerpc/kernel/rtas.c b/arch/powerpc/kernel/rtas.c
>> index 8d81c1e7a8db..27d53f34494d 100644
>> --- a/arch/powerpc/kernel/rtas.c
>> +++ b/arch/powerpc/kernel/rtas.c
>> @@ -1117,6 +1117,29 @@ static bool token_is_restricted_errinjct(s32 
>> token)
>>              token == rtas_function_token(RTAS_FN_IBM_ERRINJCT);
>>   }
>> +/**
>> + * rtas_token_is_open_errinjct() - Test whether @token identifies 
>> ibm,open-errinjct.
>> + */
>> +static bool rtas_token_is_open_errinjct(int token)
>> +{
>> +    return token == rtas_function_token(RTAS_FN_IBM_OPEN_ERRINJCT);
>> +}
> 
> The above function is a god candidate for an inline function.

Agreed. I updated this in v4 and made the helper static inline.

>> +
>> +/**
>> + * rtas_status_from_args() - Extract the RTAS status code from a 
>> completed
>> + *                           call's return-cell array.
>> + *
>> + * For ibm,open-errinjct the status lives in rets[1]; for every other
>> + * RTAS function it lives in rets[0].
>> + */
>> +static int rtas_status_from_args(int token, struct rtas_args *args, 
>> int nret)
>> +{
>> +    if (rtas_token_is_open_errinjct(token) && nret > 1)
> 
> Do we know what RTAS returns when nret is less than 2 for the ibm,open- 
> errinjct RTAS call?
> 
> I assume RTAS treats this as a parameter error. However, since there is 
> no rets buffer available
> to store the status code, I'm not sure how RTAS would convey the 
> parameter error back to the kernel.
> 
> The way the RTAS status code is extracted when nret is less than 2 for 
> the ibm,open-errinjct RTAS
> call seems problematic me, especially when nret == 1. When nret == 1, 
> this function returns args->rets[0],
> which is supposed to contain the session token.
> 
> Are we sure that RTAS places the call status in rets[0] when nret == 1 
> for the ibm,open-errinjct RTAS call?
> 
The rets[0] contains a status for
ibm,open-errinjct when fewer than two return cells are provided. For this
RTAS call, rets[0] is the session token and rets[1] is the status. So if
nret < 2, the kernel cannot reliably extract the status.

I fixed this in v4 by treating ibm,open-errinjct with nret < 2 as an
invalid rtas_call() usage instead of falling back to rets[0]. That avoids
mistaking a session token for a status code.

For normal callers using nret == 2, the behavior remains:

rtas_call() return value = rets[1] status
outputs[0] = rets[0] session token

The sys_rtas() path remains unchanged and continues to expose the raw RTAS
return cells to userspace.

> - Sourabh Jain
> 
>> +        return be32_to_cpu(args->rets[1]);
>> +
>> +    return nret > 0 ? be32_to_cpu(args->rets[0]) : 0;
>> +}
>> +
>>   /**
>>    * rtas_call() - Invoke an RTAS firmware function.
>>    * @token: Identifies the function being invoked.
>> @@ -1213,15 +1236,29 @@ int rtas_call(int token, int nargs, int nret, 
>> int *outputs, ...)
>>       va_rtas_call_unlocked(args, token, nargs, nret, list);
>>       va_end(list);
>> -    /* A -1 return code indicates that the last command couldn't
>> -       be completed due to a hardware error. */
>> -    if (be32_to_cpu(args->rets[0]) == -1)
>> +    ret = rtas_status_from_args(token, args, nret);
>> +
>> +    /*
>> +     * A -1 return code indicates that the last command couldn't
>> +     * be completed due to a hardware error.
>> +     */
>> +    if (ret == -1)
>>           buff_copy = __fetch_rtas_last_error(NULL);
>> -    if (nret > 1 && outputs != NULL)
>> -        for (i = 0; i < nret-1; ++i)
>> -            outputs[i] = be32_to_cpu(args->rets[i + 1]);
>> -    ret = (nret > 0) ? be32_to_cpu(args->rets[0]) : 0;
>> +    if (nret > 1 && outputs != NULL) {
>> +        if (rtas_token_is_open_errinjct(token)) {
>> +            /*
>> +             * ibm,open-errinjct: rets[0]=session token, rets[1]=status.
>> +             * Expose session token in outputs[0]; skip rets[1] 
>> (status).
>> +             */
>> +            outputs[0] = be32_to_cpu(args->rets[0]);
>> +            for (i = 1; i < nret - 1; ++i)
>> +                outputs[i] = be32_to_cpu(args->rets[i + 1]);
>> +        } else {
>> +            for (i = 0; i < nret - 1; ++i)
>> +                outputs[i] = be32_to_cpu(args->rets[i + 1]);
>> +        }
>> +    }
>>       lockdep_unpin_lock(&rtas_lock, cookie);
>>       raw_spin_unlock_irqrestore(&rtas_lock, flags);
> 


Thanks,
Narayana
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.