[PATCH v6 2/3] aarch64: clear ZA state of SME before clone and clone3 syscalls
Adhemerval Zanella Netto
adhemerval.zanella@linaro.org
Wed Oct 8 11:18:51 GMT 2025
On 08/10/25 06:08, Yury Khrustalev wrote:
> On Tue, Oct 07, 2025 at 11:05:59AM -0300, Adhemerval Zanella Netto wrote:
>>
>> On 06/10/25 08:53, Yury Khrustalev wrote:
>>> This change adds a call to the __arm_za_disable() function immediately
>>> before the SVC instruction inside clone() and clone3() wrappers. It also
>>> adds a macro for inline clone() used in fork() and adds the same call to
>>> the vfork implementation. This sets the ZA state of SME to "off" on return
>>> from these functions (for both the child and the parent).
>>>
>>> ...
>>>
>>> However, in certain cases, the kernel may ensure that a "child" doesn't
>>> start in an incorrect state. This is what is done by the recent change
>>> included in 6.16 kernel [5]. This is not enough to ensure that code that
>>> uses clone() and clone3() function conforms to [1] when it runs on a
>>> system that provides SME, hence this change.
>>
>> This makes old glibc without this fix non-compliant with the lazy saving scheme.
>> I assume you will backport this from 2.39 (the first release with SME support)
>> and forward,
>
> Yes, this is the plan: to backport this patch to 2.39 and above as well
> as the a7f6fd976c17b82dc198290b4ab7087f35855a0e change.
>
>> but it does not help on older releases where HWCAP2_SME will still
>> be advertised by the kernel.
>
> HWCAP2_SME will only be advertised by 6.16 and above. If it happens to
> be advertised for an earlier kernel version, it means it was forcibly
> enabled during kernel build or the version of kernel is not up-to-date.
>
> I don't think we can do anything with either of those cases.
>
>> I am not sure if this would be a real problem; users of SME should rarely call
>> clone/clone3/setjmp during a za operation (maybe some might hit this while running
>> containers with old glibc on newer kernels). Rich has suggested masking off the
>> hwcap SME bits in such a case [1], but it would require updating old release
>> branches, which is also not optimal.
>
> I agree, doing so would be optimising for a rare and unlikely case at
> the expense of most users.
>
>> I assume this would not be a problem for Android, as they typically sync their
>> libc support with the kernel version.
>>
>> And I think this should not be a blocker for this change.
>
> Agreed.
>
>>> +/* Clear ZA state of SME (C version). */
>>> +/* The __libc_arm_za_disable function has special calling convention
>>> + that allows to call it without stack manipulation and preserving
>>> + most of the registers. */
>>> +#define CALL_LIBC_ARM_ZA_DISABLE() \
>>> +({ \
>>> + asm volatile ( \
>>> + " mov x13, x30\n" \
>>> + " .cfi_register x30, x13\n" \
>>> + " bl __libc_arm_za_disable\n" \
>>> + " mov x30, x13\n" \
>>> + " .cfi_register x13, x30\n" \
>>> + : : : "x13", "x14", "x15", "x16", "x17", "x18", "memory" ); \
>>> +})
>>
>> I think there is no need to constrait the temporary to x13, we can let
>> compiler pick it instead:
>>
>> #define CALL_LIBC_ARM_ZA_DISABLE() \
>> ({ \
>> unsigned long int __tmp; \
>> asm volatile ( \
>> " mov %0, x30\n" \
>> " .cfi_register x30, %0\n" \
>> " bl __libc_arm_za_disable\n" \
>> " mov x30, %0\n" \
>> " .cfi_register %0, x30\n" \
>> : "=r" (__tmp) \
>> : \
>> : "x14", "x15", "x16", "x17", "x18", "memory" ); \
>> })
>
> Compiler might not know the calling convention of__libc_arm_za_disable().
> It's a private Glibc function and a compiler might treat it as such
> applying common rules. I think it's safer to force use of x13 that we
> know will stay unchanged.
But x13 is temporary register to save the stack pointer, afaiu there is no
need to be x13 in C code.
More information about the Libc-alpha
mailing list