http://bugs.winehq.org/show_bug.cgi?id=58755
--- Comment #9 from Zeb Figura z.figura12@gmail.com --- (In reply to Zeb Figura from comment #8)
I actually ended up partially debugging this. The problem is that Wine sometimes does WCB16_REGS calls with a zeroed context, so it sets zero %fs and %gs. Some CPUs crash when %gs is zero even in 64-bit mode, mine included.
Okay, it's more complicated than that. It turns out:
* the kernel lies to us: FS_sig and GS_sig are always zero in an exception, but that's not their real values. This threw me off.
* %gs being zero is fine actually; in fact it seems to be zero to start out with. The problem is that clearing %gs, in some processors, also seems to clear gsbase. This is observed in the ntdll:exception tests.
* %gs is cleared when calling into 16-bit code. Its previous value is restored when calling back into 32-bit code, which we do before doing any syscalls or unix calls, but this doesn't help, because this either doesn't affect gsbase, or clears it again. [Plus, the previous value was zero for me.]
* 94447cee61 is supposed to catch broadly this. It doesn't catch the unix call case (or the syscall case) because it tries to read the faulting instruction with virtual_handle_fault(), but here the faulting instruction isn't in a PE module. We can special-case those safely, I think.
* 94447cee61 *does*, as one might predict, catch the case I mentioned where we fault in wow64cpu.dll. However the game still doesn't launch, and I'm not sure why. I see a subsequent SEGV from the game doing an int21, but for some reason that exception doesn't seem to even reach the PE side of ntdll.