Description
openedon Apr 10, 2021
- I have tried with the latest version of Docker Desktop
- I have tried disabling enabled experimental features
- I have uploaded Diagnostics
Expected behavior
I can run modern software that uses Intel instructions like pshufb
in Docker for Mac (on M1 Macs) because the qemu-x86_64 that's installed using the binfmt_misc
support can emulate it.
Actual behavior
I can't run modern software that makes use of newer Intel instructions because the qemu-x86_64 that gets run using binfmt_misc
doesn't get passed a -cpu core2duo
(or newer such as -cpu Skylake-Client
/-cpu max
) argument.
Information
The problem is that the qemu-x86_64
doesn't get passed a -cpu core2duo
(or even better something like -cpu Skylake-Client
or maybe -cpu max
("Enables all features supported by the accelerator in the current host")) argument. Really, I would recommend to just pass the newest CPU that qemu can emulate (probably -cpu max
).
I got the Swift compiler to work just fine by compiling my own qemu with this patch applied:
sed -i 's/cpu_model = NULL/cpu_model = "core2duo"/g' linux-user/main.c
which just sets the default CPU model to core2duo
. I then installed as the Docker for Mac default binfmt_misc
handler for x86_64
using
/containers/services/binfmt/rootfs/usr/bin/binfmt -uninstall qemu-x86_64
echo ":qemu-x86_64:M::\x7fELF\x02\x01\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x02\x00\x3e\x00:\xff\xff\xff\xff\xff\xfe\xfe\x00\xff\xff\xff\xff\xff\xff\xff\xff\xfe\xff\xff\xff:/var/lib/docker/overlay2/80s11o66od7msjkcmt4hal5ui/diff/amd64/usr/bin/qemu-x86_64-static-c2d:OCF" > /proc/sys/fs/binfmt_misc/register
in the actual VM which I entered using justincormack/nsenter
.
Steps to reproduce the behavior
The quickest way to reproduce the problem is:
- Get an M1 Mac and install Docker for Mac for M1 Macs
- Run
docker run -it --rm --platform linux/amd64 swift:5.3 bash -c 'echo "print(\"hello world\")" > /tmp/test.swift && cd /tmp && swiftc test.swift && ./test'
Expected: prints "hello world"
Actual: Output something similar to
Please submit a bug report (https://swift.org/contributing/#reporting-bugs) and include the project and the crash backtrace.
Stack dump:
0. Program arguments: /swift-DEVELOPMENT-SNAPSHOT-2021-02-09-a-ubuntu18.04/usr/bin/swift-frontend -frontend -c -primary-file /tmp//test.swift -target x86_64-unknown-linux-gnu -disable-objc-interop -color-diagnostics -module-name test -o /tmp/test-d8e021.o
1. Swift version 5.4-dev (LLVM 1e4181b99f530d2, Swift 842cc9c88f5463b)
#0 0x0000000005cb5c13 llvm::sys::PrintStackTrace(llvm::raw_ostream&, int) (/swift-DEVELOPMENT-SNAPSHOT-2021-02-09-a-ubuntu18.04/usr/bin/swift-frontend+0x5cb5c13)
#1 0x0000000005cb396e llvm::sys::RunSignalHandlers() (/swift-DEVELOPMENT-SNAPSHOT-2021-02-09-a-ubuntu18.04/usr/bin/swift-frontend+0x5cb396e)
#2 0x0000000005cb5f9c SignalHandler(int) (/swift-DEVELOPMENT-SNAPSHOT-2021-02-09-a-ubuntu18.04/usr/bin/swift-frontend+0x5cb5f9c)
#3 0x0000004000a48980 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x12980)
#4 0x00000000018a7f63 std::vector<swift::DiagnosticState::Behavior, std::allocator<swift::DiagnosticState::Behavior> >::_M_fill_insert(__gnu_cxx::__normal_iterator<swift::DiagnosticState::Behavior*, std::vector<swift::DiagnosticState::Behavior, std::allocator<swift::DiagnosticState::Behavior> > >, unsigned long, swift::DiagnosticState::Behavior const&) (/swift-DEVELOPMENT-SNAPSHOT-2021-02-09-a-ubuntu18.04/usr/bin/swift-frontend+0x18a7f63)
#5 0x00000000018a237f swift::DiagnosticState::DiagnosticState() (/swift-DEVELOPMENT-SNAPSHOT-2021-02-09-a-ubuntu18.04/usr/bin/swift-frontend+0x18a237f)
#6 0x00000000006ae240 swift::CompilerInstance::CompilerInstance() (/swift-DEVELOPMENT-SNAPSHOT-2021-02-09-a-ubuntu18.04/usr/bin/swift-frontend+0x6ae240)
#7 0x0000000000513165 swift::performFrontend(llvm::ArrayRef<char const*>, char const*, void*, swift::FrontendObserver*) (/swift-DEVELOPMENT-SNAPSHOT-2021-02-09-a-ubuntu18.04/usr/bin/swift-frontend+0x513165)
#8 0x00000000004ad906 main (/swift-DEVELOPMENT-SNAPSHOT-2021-02-09-a-ubuntu18.04/usr/bin/swift-frontend+0x4ad906)
#9 0x0000004002013bf7 __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21bf7)
#10 0x00000000004ad57a _start (/swift-DEVELOPMENT-SNAPSHOT-2021-02-09-a-ubuntu18.04/usr/bin/swift-frontend+0x4ad57a)
qemu: uncaught target signal 4 (Illegal instruction) - core dumped
<unknown>:0: error: unable to execute command: Illegal instruction
<unknown>:0: error: compile command failed due to signal 4 (use -v to see invocation)
Please note the qemu: uncaught target signal 4 (Illegal instruction) - core dumped
which qemu prints when it encounters the pshufb
Intel instruction (which needs the Intel SSE3 feature which qemu (correctly) only emulates if you tell it to emulate a new-enough CPU using -cpu core2duo
or better).
The problem here is that the Swift compiler runs a pshufb
instruction which isn't available in the ancient CPU that qemu emulates if you don't pass -cpu core2duo
or newer. See Swift compiler bug SR-14186 for all the details.
For a somewhat more complete test, it'd be probably good to run
docker run -it --rm --platform linux/amd64 swift:5.3 bash -c 'git clone https://github.com/apple/swift-nio.git && cd swift-nio && swift test'
which clones SwiftNIO, compiles it and runs its test suite.