[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:25:01 GMT 2025



On 08/10/25 08:18, Adhemerval Zanella Netto wrote:
> 
> 
> 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.

I mean, the inline asm already define the clobbered registers so compiler
should pick one that is no suppose to pick.


More information about the Libc-alpha mailing list