[PATCH v2 1/1] aarch64: clear ZA state of SME before clone and clone3 syscalls
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Thu Jun 12 14:08:20 GMT 2025
On 12/06/25 09:53, Richard Sandiford wrote:
> Adhemerval Zanella Netto <adhemerval.zanella@linaro.org> writes:
>> On 11/06/25 12:36, Yury Khrustalev wrote:
>>> Hi everyone,
>>>
>>> There are several sub-threads, so I'll reply here to provide some summary.
>>>
>>> 1. Changes in the kernel address most common scenarios wrt ZA state of SME.
>>>
>>> 2. Since clone() is part of API available to userspace via libc wrapper,
>>> it is possible that some corner cases are still not covered, which is why
>>> this Glibc patch series is still useful. Ideally, we also want all libc-s
>>> to be aligned on this so that userspace programs could expect the same
>>> behaviour.
>>
>> For thread discussion my understanding was that SME status between v5.19 and
>> v6.12 is broken due multiple issues (and disabled on stable releases), and
>> from 6.12 to 6.16 was marked BROKEN.
>>
>> And starting from 6.16 there should be no need to no extra care by userland
>> to clear ZA state of SME before fork, as indicated by kernel commit
>> cde5c32db55740659fca6d56c09b88800d88fd29:
>>
>> Ideally we'd require that userspace ensures that a task is in the "ZA
>> off" state (with PSTATE.ZA==0 and TPIDR2_EL0==NULL) prior to issuing a
>> clone syscall, and have the kernel force this state for new threads.
>> Unfortunately, contemporary C libraries do not do this, and simply
>> forcing this state within the implementation of clone would break
>> fork().
>>
>> I do not think it would be worth to handle the old broken kernels (v5.19 to
>> v6.12) and adding this patch to fix potentially corner cases adds some doubt
>> whether the kernel does have SME in an workable condition; nor it is clear
>> what exactly are the corner cases is trying to prevent.
>
> I think that's putting the burden of proof in the wrong place.
>
> In principle, the lazy save scheme allows any normal ("private-ZA")
> function to call __arm_za_disable for any reason. Calling __arm_za_disable
> is a conservatively correct thing to do. The question then is more:
> can we prove that not calling __arm_za_disable is behaviourally
> equivalent to calling __arm_za_disable as far as the lazy save
> scheme is concerned?
It is not conservative if there is no description of what exactly is
trying to achieve here. And the question does not really makes sense
without defining in which usercases libc (or any runtime, because it
essentially boils down to the kABI and SME interop) should act upon.
If __arm_za_disable is strictly required, I think it should be proper
documented in kABI or aarch64 ABI that it should be called in
clone-like interfaces.
>
> From a QoI perspective, functions are discouraged from calling
> __arm_za_disable if (a) the function could plausibly be used in the
> middle of an SME operation, (b) it's easy to prove that not calling
> __arm_za_disable is behaviourally equivalent to calling __arm_za_disable,
> and (c) the function does not tend to force the kernel to save ZA state.
>
> I think clone fails on at least (a) and (b). Calling clone in the middle of
> an SME operation seems significantly outside the normal expected use of SME.
> And clone is a complex syscall with many options, so it's difficult to
> prove that not calling __arm_za_disable is behaviourally equivalent to
> calling __arm_za_disable.
That's why libc provides wrapper over clone() and if users wants
to mess up with clone flags they can not resort that libc runtime will
always behave as expected.
>
> So IMO, if there's doubt about whether all uses of clone are correct
> without __arm_za_disable (or glibc's local equivalent), the choice
> should be to call __arm_za_disable.
So it all boils down on whether if some clone arguments might trigger
some undefined behavior with SME. The glibc does minimal sanitization
of clone arguments (just check whether the function and the stack
are not null), and bionic seems to follow glibc here.
musl tries to filter out invalid flags that might produce an invalid
thread/TLS state, so I wonder if should do the same in this case.
>
> In particular, it shouldn't be up to code higher up the stack to become
> SME aware if they are using the correct libc functions (rather than
> trying to use asm to do syscalls directly).
That's I agree.
PS: CC Rich Felker, because he might eventually need to handle this on
musl as well.
More information about the Libc-alpha
mailing list