Re: [PATCH v2 07/11] um: add infrastructure to build files using nolibc

Berg, Benjamin
2025-09-22T07:11:05Z

Hi,

On Sun, 2025-09-21 at 10:13 +0200, Willy Tarreau wrote:
> Hi Benjamin,
>
> On Fri, Sep 19, 2025 at 05:34:16PM +0200, Benjamin Berg wrote:
> > From: Benjamin Berg <benjamin.berg@intel.com>
> >
> > Add NOLIBC_CFLAGS and NOLIBC_OBJS to build files against nolibc rather
> > than libc. With this it is possible to move to nolibc in smaller steps.
> >
> > Set NOLIBC_IGNORE_ERRNO, as the nolibc errno implementation is overly
> > simple and cannot handle threading. nolibc provides sys_* functions that
> > do not emulate the libc errno behaviour and can be used instead.
>
> Just for my understanding, in case we can improve portability, why is it
> needed to disable errno processing here ? Even if it's limited, it
> shouldn't cause trouble. I mean that if a program works with it defined,
> logically it should also work without since the only difference is that
> the errno global variable will not be defined nor assigned on syscall
> returns.
>
> > Guard the syscall definition as it is a macro in nolibc.
>
> This one is interesting:
>
>   --- a/arch/um/include/shared/os.h
>   +++ b/arch/um/include/shared/os.h
>   @@ -327,7 +327,9 @@ extern int __ignore_sigio_fd(int fd);
>    /* tty.c */
>    extern int get_pty(void);
>
>   +#ifndef NOLIBC
>    long syscall(long number, ...);
>   +#endif
>
> In nolibc, the syscall() definition indeed looks like this now:
>
>   #define __syscall_narg(_0, _1, _2, _3, _4, _5, _6, N, ...) N
>   #define _syscall_narg(...) __syscall_narg(__VA_ARGS__, 6, 5, 4, 3, 2, 1, 0)
>   #define _syscall(N, ...) __sysret(my_syscall##N(__VA_ARGS__))
>   #define _syscall_n(N, ...) _syscall(N, __VA_ARGS__)
>   #define syscall(...) _syscall_n(_syscall_narg(__VA_ARGS__), ##__VA_ARGS__)
>
> Except by mapping all syscalls to _syscall(6, ...) and always passing
> 6 args, I'm not seeing any easy way to dynamically adapt to the number
> of arguments if we wanted to move it to a function. Also, a static
> function would still conflict with the definition above. I'm wondering
> about what extent the documented "long syscall(number, ...)" is valid in
> fact, as I doubt it's really implemented anywhere as a generic function
> taking the maximum amount of args.
>
> Thus I think that the guard is indeed the only option to reconciliate these
> two incompatible approaches. By the way I think it could be more future-
> proof to do the guard on the syscall macro definition itself (which would
> thus also resist it being passed by "-Dsyscall(x)=(...)" or any other form:
>
>   +#ifndef syscall
>    long syscall(long number, ...);
>   +#endif

I had that, but then Thomas suggested the NOLIBC check :-)

Overall, it probably does not really matter. The declaration is used
when this file is included from kernel code to be able to do host
syscalls. That can be useful, but in that case we will not be able to
use nolibc includes and macros anyway. If UML stops linking against
libc we'll need an alternative solution, likely by adding a simple
os_syscall wrapper and using that instead.

Considering that, I think I'll change it to "#ifdef __KERNEL__".

Benjamin
Intel Deutschland GmbH
Registered Address: Am Campeon 10, 85579 Neubiberg, Germany
Tel: +49 89 99 8853-0, www.intel.de
Managing Directors: Sean Fennelly, Jeffrey Schneiderman, Tiffany Doon Silva
Chairperson of the Supervisory Board: Nicole Lau
Registered Office: Munich
Commercial Register: Amtsgericht Muenchen HRB 186928