Open xen0n opened 7 months ago
Confirmed this is the root cause. By re-building systemd with -mno-lsx -mno-lasx
, I successfully produced working UKIs.
We need to teach sd-boot's build system to just use the LP64S ABI for the UEFI bits.
@xry111: Do you think something like -mgeneral-regs-only
useful for LoongArch too? I fear -msoft-float
alone may not be able to cancel other fancy additions from future -march
additions, while filtering -march
is arguably not appropriate either.
-mabi=lp64s
isn't directly usable, because the sd-boot UEFI code didn't make the effort to avoid inclusion of libc headers:
In file included from /usr/include/features.h:527,
from /usr/include/bits/libc-header-start.h:33,
from /usr/include/limits.h:26,
from /usr/lib/gcc/loongarch64-unknown-linux-gnu/14/include/limits.h:210,
from /usr/lib/gcc/loongarch64-unknown-linux-gnu/14/include/syslimits.h:7,
from /usr/lib/gcc/loongarch64-unknown-linux-gnu/14/include/limits.h:34,
from ../systemd-stable-254.6/src/fundamental/macro-fundamental.h:8,
from ../systemd-stable-254.6/src/boot/efi/efi.h:9,
from ../systemd-stable-254.6/src/fundamental/string-util-fundamental.h:5,
from ../systemd-stable-254.6/src/fundamental/bootspec-fundamental.h:4,
from ../systemd-stable-254.6/src/fundamental/bootspec-fundamental.c:3:
/usr/include/gnu/stubs.h:8:11: fatal error: gnu/stubs-lp64s.h: No such file or directory
8 | # include <gnu/stubs-lp64s.h>
| ^~~~~~~~~~~~~~~~~~~
compilation terminated.
EDIT: apparently -msoft-float
also fails in exactly the same way. I really don't want to pretend compiling for LP64D while doing -mno-lsx -mno-lasx
, because we can't disable FP the same way, hence it's only papering over the problem,
According to the UEFI spec, it's okay for UEFI apps to self-enable FPU with CSR.EUEN
if they're willing to self-manage the context afterwards. But I don't think it's a good idea for every single UEFI app to do so either.
Hmm, what's the expected difference between -mgeneral-regs-only and -msoft-float or -mabi=lp64s?
Hmm, what's the expected difference between -mgeneral-regs-only and -msoft-float or -mabi=lp64s?
See:
It seems it doesn't change the ABI, but it's likely because aarch64 and x86_64 don't have multiple commonly used ABIs.
Maybe fixing the libc header dep of the UEFI code is the most elegant way to go... The UEFI code cannot and shouldn't get into contact with the Linux libc after all.
Maybe fixing the libc header dep of the UEFI code is the most elegant way to go... The UEFI code cannot and shouldn't get into contact with the Linux libc after all.
I'm wondering if -ffreestanding should prevent the inclusion of Glibc limits.h (like stdint.h).
Maybe fixing the libc header dep of the UEFI code is the most elegant way to go... The UEFI code cannot and shouldn't get into contact with the Linux libc after all.
I'm wondering if -ffreestanding should prevent the inclusion of Glibc limits.h (like stdint.h).
Is that possible or appropriate to do? IIUC -f*
flags are meant for the optimizer, but to implement what you suggested we seem to need to poke into the include search path. Otherwise all header files look identical and there's no magical mark/pragma that distinguishes libc headers from ordinary user-supplied headers.
Maybe fixing the libc header dep of the UEFI code is the most elegant way to go... The UEFI code cannot and shouldn't get into contact with the Linux libc after all.
I'm wondering if -ffreestanding should prevent the inclusion of Glibc limits.h (like stdint.h).
Is that possible or appropriate to do? IIUC
-f*
flags are meant for the optimizer, but to implement what you suggested we seem to need to poke into the include search path. Otherwise all header files look identical and there's no magical mark/pragma that distinguishes libc headers from ordinary user-supplied headers.
-ffreestanding already prevents the inclusion of libc stdint.h as at now. When we include stdint.h in a freestanding C program, GCC will use its own minimized version of stdint.h.
-ffreestanding
Assert that compilation targets a freestanding environment. This
implies -fno-builtin. A freestanding environment is one in which
the standard library may not exist, and program startup may not
necessarily be at "main". The most obvious example is an OS
kernel. This is equivalent to -fno-hosted.
It seems reasonable for a bootloader.
Ah, that's nice, but the problem is that -ffreestanding
is already present...
Ah, that's nice, but the problem is that
-ffreestanding
is already present...
Yes, I mean I'm wondering if GCC limits.h should be self-contained if !__STDC_HOSTED__
, like stdint.h.
GCC stdint.h now reads:
#ifndef _GCC_WRAP_STDINT_H
#if __STDC_HOSTED__
# if defined __cplusplus && __cplusplus >= 201103L
# undef __STDC_LIMIT_MACROS
# define __STDC_LIMIT_MACROS
# undef __STDC_CONSTANT_MACROS
# define __STDC_CONSTANT_MACROS
# endif
# include_next <stdint.h>
#else
# include "stdint-gcc.h"
#endif
#define _GCC_WRAP_STDINT_H
#endif
So it does not refer to Glibc stdint.h if !__STDC_HOSTED__
. Maybe it should be done for limits.h too.
i.e. in GCC limits.h now we have (line 32):
#ifndef _LIBC_LIMITS_H_
/* Use "..." so that we find syslimits.h only in this same directory. */
#include "syslimits.h"
#endif
Maybe it should be
#ifndef _LIBC_LIMITS_H_ && __STDC_HOSTED__
/* Use "..." so that we find syslimits.h only in this same directory. */
#include "syslimits.h"
#endif
?
Ah, so GCC's -ffreestanding
adaptation of <stdint.h>
is some local trick... Then extending that to <limits.h>
seems reasonable to me!
I also found out that the libgcc.a
contains vectorized __popcountdi2
so even if I disabled SIMD codegen for systemd, this code still found its way into the UKI stub...
000000000000001c <__popcountdi2>:
1c: 73e18000 vldi $vr0, 3072
20: 72ebf080 vinsgr2vr.d $vr0, $a0, 0x0
24: 729c2c00 vpcnt.d $vr0, $vr0
28: 72f3f004 vpickve2gr.du $a0, $vr0, 0x0
Phew. Now to me systemd-boot just requires a multilib...
Anyway to me depending on libgcc.a is wrong even on x86_64: what will happen if libgcc.a uses a SSE2 instruction?
I'm having a debate with Segher Boessenkool on the topic.
got hit by this. using sd-boot on loongarchlinux & AOSC OS. Now I can't boot to any of them even using EFI Shell command to boot.
With GCC 14 snapshot and
-march=la464
or-march=la664
in CFLAGS, UKIs produced by systemd'sukify
tool fail to print anything when brought up by sd-boot.Likely due to LSX/LASX being emitted by GCC for block moves, but because the SIMD unit is disabled at the UEFI stage, the execution simply halts with an
SXD
orASXD
exception.