ValveSoftware / steam-for-linux

Issue tracking for the Steam for Linux beta client
4.22k stars 174 forks source link

64-bit steamclient.so causes games to crash due to cmpxchg16b instruction #4196

Open joaormatos opened 8 years ago

joaormatos commented 8 years ago

The 64 bit version of steamclient.so uses the instruction cmpxchg16b, which is not supported by some early AMD64 CPUs. On such CPUs, 64 bit games crash on startup with a SIGILL.

One example of such a game is Super Meat Boy.

~/.steam/steam/SteamApps/common/Super Meat Boy$ gdb ./amd64/SuperMeatBoy 
GNU gdb (Debian 7.7.1+dfsg-5) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./amd64/SuperMeatBoy...(no debugging symbols found)...done.
(gdb) run
Starting program: /home/steam/steamdir/steam/SteamApps/common/Super Meat Boy/amd64/SuperMeatBoy 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGILL, Illegal instruction.
0x00007fffec1bdcbf in ?? () from /home/steam/steamdir/linux64/steamclient.so
(gdb) x/i $pc
=> 0x7fffec1bdcbf:      lock cmpxchg16b 0x0(%rbp)
(gdb) 

For the purpose of reproducing this bug: if a CPU supports the cmpxchg16b instruction, the "cx16" flag will be found in /proc/cpuinfo. grep cx16 /proc/cpuinfo

Plagman commented 8 years ago

Thanks for the report. We have a pending change to disable 64-bit support on these CPUs, but it hasn't yet been finalized.

joaormatos commented 8 years ago

I'm not sure what you mean by disabling 64-bit support. What will it mean for users with those CPUs?

Plagman commented 8 years ago

Steam will run the 32-bit version of these games instead. If the game is 64-bit only, it won't be supported on these CPUs.

joaormatos commented 8 years ago

I'm curious as to how you intend to do that. Most dual-arch games I examined decide which binary they're going to run by themselves, in a launch script.

Plagman commented 8 years ago

This is technically a bug with these games and you're right that the Steam-side fix won't do much for those; the right way for developers to put their multi-arch games up is to set two different launch configurations in their application data, one for Linux i386 and one for Linux x86_64.

amonakov commented 8 years ago

Steam can run them under PER_LINUX32 personality (akin to the linux32 utility), and then as long as the wrapper/launch script uses "uname" to discover which version to run, it'll go for the 32-bit version.

joaormatos commented 8 years ago

@amonakov Thank you, I didn't know about setarch. Most launch scripts I've seen check the arch via uname -m, so this should be a satisfactory workaround for the time being. Super Meat Boy now works on the affected system if Steam was launched with linux32.

I could put linux32 %command% in the game's launch options instead of launching Steam with it, but since all 64 bit games are affected, launching Steam with linux32 seems to be the best option for now. It might even make Steam launch the 32 bit version of games that handle multi-arch correctly, but I don't know if I have any of those in my library.

Still, I was expecting the solution to this problem to be a simple change to the options used to build steamclient.so. I assumed the cmpxchg16b instruction was being added by a compiler optimization or a statically linked library built with optimizations enabled, but it might be deliberate after all.

Plagman commented 8 years ago

Correct, that instruction is used by design the Steamworks low-level locking primitives for 64-bit architectures and we have no fallback for these, meaning our support for 64-bit processors is limited to those that support it.

kisak-valve commented 7 years ago

As noted in #4880, the steam client is now affected by this issue due to use of 64 bit libcef for the browser component.

austinksmith commented 4 years ago

I am following up on this one as well, I am running a similar setup to #4880 using Lubuntu 18.04 and I built this computer as a bit of a thought experiment to see how well an older cpu can run if you max it out.

This is the hardware setup.

AMD Opteron 185 2.6ghz socket 939 dual core
12GB ECC Registered ddr400mhz dual channel ram
4x60GB solid state drives in raid0
AMD RX560 4GB PCI-E video card
Lubuntu Linux 18.04 LTS

I am experiencing the same issue with the actual steam webviews themselves, this wasn't a problem in the past. Disabling hardware acceleration or enabling low performance mode does not resolve the issue, ironically the only way I can interact with steam now is using big picture mode but functionality is limited. Can't uninstall games, can't view friends list etc. Using small mode will let me view my library however it won't stay in small mode and I can't view the store page etc.

I was able to install using big picture mode Killing Floor and play that with reasonable performance on high settings, however I am struggling to get other things to install simply because I can't change the install location.

Doing some research it appears it should be possible to implement a fallback mode that will still allow the steam webview to render albeit with lower performance. Possibly using a different instruction to handle for older devices. Many people still use older systems to play legacy games and this bug is now affecting the actual steam client itself and ironically this doesn't happen if you run windows 7 64-bit on the same system though I prefer the lighter weight lubuntu.

Early AMD64 processors (typically on Socket 939 and 940) lacked the CMPXCHG16B instruction, which is an extension of the CMPXCHG8B instruction present on most post-80486 processors. Similar to CMPXCHG8B, CMPXCHG16B allows for atomic operations on octa-words (128-bit values). This is useful for parallel algorithms that use compare and swap on data larger than the size of a pointer, common in lock-free and wait-free algorithms. Without CMPXCHG16B one must use workarounds, such as a critical section or alternative lock-free approaches.[43] Its absence also prevents 64-bit Windows prior to Windows 8.1 from having a user-mode address space larger than 8 terabytes.[44] The 64-bit version of Windows 8.1 requires the instruction

Here are the supported extensions, SSE2 is supported on this cpu.

cat  /proc/cpuinfo
processor   : 0
vendor_id   : AuthenticAMD
cpu family  : 15
model       : 35
model name  : Dual Core AMD Opteron(tm) Processor 185
stepping    : 2
microcode   : 0x4d
cpu MHz     : 2607.902
cache size  : 1024 KB
physical id : 0
siblings    : 2
core id     : 0
cpu cores   : 2
apicid      : 0
initial apicid  : 0
fpu     : yes
fpu_exception   : yes
cpuid level : 1
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt lm 3dnowext 3dnow rep_good nopl cpuid extd_apicid pni lahf_lm cmp_legacy 3dnowprefetch vmmcall
bugs        : fxsave_leak sysret_ss_attrs null_seg swapgs_fence spectre_v1 spectre_v2
bogomips    : 5215.80
TLB size    : 1024 4K pages
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: ts fid vid ttp

processor   : 1
vendor_id   : AuthenticAMD
cpu family  : 15
model       : 35
model name  : Dual Core AMD Opteron(tm) Processor 185
stepping    : 2
microcode   : 0x4d
cpu MHz     : 2607.902
cache size  : 1024 KB
physical id : 0
siblings    : 2
core id     : 1
cpu cores   : 2
apicid      : 1
initial apicid  : 1
fpu     : yes
fpu_exception   : yes
cpuid level : 1
wp      : yes
flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt lm 3dnowext 3dnow rep_good nopl cpuid extd_apicid pni lahf_lm cmp_legacy 3dnowprefetch vmmcall
bugs        : fxsave_leak sysret_ss_attrs null_seg swapgs_fence spectre_v1 spectre_v2
bogomips    : 5215.78
TLB size    : 1024 4K pages
clflush size    : 64
cache_alignment : 64
address sizes   : 40 bits physical, 48 bits virtual
power management: ts fid vid ttp