The System V ABI for amd64 allows functions to use space in a 128
byte redzone below the stack pointer for scratch space and requires
interrupt and signal frames to avoid overwriting it. However, EFI
uses the Windows ABI which does not support this. As a result,
interrupt handlers in EFI push their interrupt frames directly on
top of the stack pointer. If the compiler used the red zone in a
function in the EFI loader, then a device interrupt that occurred
while that function was running could trash its local variables.
In practice this happens fairly reliable when using gzipfs as an
interrupt during decompression can trash the local variables in
the inflate_table() function resulting in corrupted output or hangs.
Fix this by disabling the redzone for amd64 EFI binaries. This
requires building not only the loader but any libraries used by the
loader without redzone support.
Thanks to Jilles for pointing me at the redzone once I found the
stack corruption.
Sponsored by: Cisco Systems, Inc.
I did think about building dedicated versions of libstand and libficl
for EFI in sys/amd64/efi. However, I think if the EFI loader is the
only consumer of the 64-bit libficl/libstand on amd64 then this is
simpler and results in less work in the future (we are already stuck
with having to keep libstand32/Makefile in sync with libstand/Makefile
going forward and this would add to that burden).