From 513952a0663fbd45b25915d09fc80a7c99c802db Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Tue, 11 Nov 2014 03:28:23 +0100 Subject: [PATCH] Added patch to implement emulation SIDT instruction when using Exagear. --- debian/changelog | 1 + ...emulation-SIDT-instruction-when-usin.patch | 288 ++++++++++++++++++ patches/Exagear/definition | 3 + patches/Makefile | 16 + 4 files changed, 308 insertions(+) create mode 100644 patches/Exagear/0001-ntdll-Implement-emulation-SIDT-instruction-when-usin.patch create mode 100644 patches/Exagear/definition diff --git a/debian/changelog b/debian/changelog index 7dc3e2c5..5143875a 100644 --- a/debian/changelog +++ b/debian/changelog @@ -17,6 +17,7 @@ wine-compholio (1.7.31) UNRELEASED; urgency=low * Added patch to emulate 'mov Eb, Gb' instruction on x86 processor architecture. * Added patch to emulate access to KI_USER_SHARED_DATA kernel page on x86_64. * Added patch to initialize irp.Tail.Overlay.OriginalFileObject with stub file object. + * Added patch to implement emulation SIDT instruction when using Exagear. * Removed patch for iphlpapi stub functions (accepted upstream). * Removed patches for FindFirstFileExW (accepted upstream). * Removed patches for TLB dependencies lookup in resources (accepted upstream). diff --git a/patches/Exagear/0001-ntdll-Implement-emulation-SIDT-instruction-when-usin.patch b/patches/Exagear/0001-ntdll-Implement-emulation-SIDT-instruction-when-usin.patch new file mode 100644 index 00000000..8f02c8a1 --- /dev/null +++ b/patches/Exagear/0001-ntdll-Implement-emulation-SIDT-instruction-when-usin.patch @@ -0,0 +1,288 @@ +From 6d81dd96f48dec341e955cb9e66d8238c2917b1e Mon Sep 17 00:00:00 2001 +From: Sebastian Lackner +Date: Tue, 11 Nov 2014 03:11:33 +0100 +Subject: ntdll: Implement emulation SIDT instruction when using Exagear. + +--- + configure.ac | 8 ++ + dlls/ntdll/signal_i386.c | 224 +++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 232 insertions(+) + +diff --git a/configure.ac b/configure.ac +index 92d78a2..c88a139 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -32,6 +32,7 @@ AC_ARG_ENABLE(win16, AS_HELP_STRING([--disable-win16],[do not include Win16 supp + AC_ARG_ENABLE(win64, AS_HELP_STRING([--enable-win64],[build a Win64 emulator on AMD64 (won't run Win32 binaries)])) + AC_ARG_ENABLE(tests, AS_HELP_STRING([--disable-tests],[do not build the regression tests])) + AC_ARG_ENABLE(maintainer-mode, AS_HELP_STRING([--enable-maintainer-mode],[enable maintainer-specific build rules])) ++AC_ARG_ENABLE(exagear-compat, AS_HELP_STRING([--enable-exagear-compat],[use workarounds for known problems in the Exagear emulator])) + + AC_ARG_WITH(alsa, AS_HELP_STRING([--without-alsa],[do not use the Alsa sound support]), + [if test "x$withval" = "xno"; then ac_cv_header_sys_asoundlib_h=no; ac_cv_header_alsa_asoundlib_h=no; fi]) +@@ -367,6 +368,13 @@ fi + WINE_WARNING_WITH(gettext,[test "$MSGFMT" = false], + [gettext tools not found (or too old), translations won't be built.]) + ++dnl **** Enable Exagear workarounds **** ++ ++if test "x$enable_exagear_compat" = "xyes" ++then ++ AC_DEFINE(EXAGEAR_COMPAT, 1, [Define if you want to enable Exagear emulator workarounds]) ++fi ++ + dnl **** Check for some libraries **** + + dnl Check for -li386 for NetBSD and OpenBSD +diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c +index 13df4bb..e24f75e 100644 +--- a/dlls/ntdll/signal_i386.c ++++ b/dlls/ntdll/signal_i386.c +@@ -96,6 +96,14 @@ typedef struct + BYTE Reserved4[96]; + } XMM_SAVE_AREA32; + ++#include "pshpack1.h" ++struct idtr ++{ ++ WORD limit; ++ BYTE *base; ++}; ++#include "poppack.h" ++ + /*********************************************************************** + * signal context platform-specific definitions + */ +@@ -1573,6 +1581,214 @@ static inline DWORD is_privileged_instr( CONTEXT *context ) + } + } + ++ ++#ifdef EXAGEAR_COMPAT ++ ++/*********************************************************************** ++ * INSTR_GetOperandAddr ++ * ++ * Return the address of an instruction operand (from the mod/rm byte). ++ */ ++static BYTE *INSTR_GetOperandAddr( CONTEXT *context, const BYTE *instr, ++ int long_addr, int segprefix, int *len ) ++{ ++ int mod, rm, base = 0, index = 0, ss = 0, off; ++ ++#define GET_VAL(val,type) \ ++ { *val = *(type *)instr; instr += sizeof(type); *len += sizeof(type); } ++ ++ *len = 0; ++ GET_VAL( &mod, BYTE ); ++ rm = mod & 7; ++ mod >>= 6; ++ ++ if (mod == 3) ++ { ++ switch(rm) ++ { ++ case 0: return (BYTE *)&context->Eax; ++ case 1: return (BYTE *)&context->Ecx; ++ case 2: return (BYTE *)&context->Edx; ++ case 3: return (BYTE *)&context->Ebx; ++ case 4: return (BYTE *)&context->Esp; ++ case 5: return (BYTE *)&context->Ebp; ++ case 6: return (BYTE *)&context->Esi; ++ case 7: return (BYTE *)&context->Edi; ++ } ++ } ++ ++ if (long_addr) ++ { ++ if (rm == 4) ++ { ++ BYTE sib; ++ GET_VAL( &sib, BYTE ); ++ rm = sib & 7; ++ ss = sib >> 6; ++ switch((sib >> 3) & 7) ++ { ++ case 0: index = context->Eax; break; ++ case 1: index = context->Ecx; break; ++ case 2: index = context->Edx; break; ++ case 3: index = context->Ebx; break; ++ case 4: index = 0; break; ++ case 5: index = context->Ebp; break; ++ case 6: index = context->Esi; break; ++ case 7: index = context->Edi; break; ++ } ++ } ++ ++ switch(rm) ++ { ++ case 0: base = context->Eax; break; ++ case 1: base = context->Ecx; break; ++ case 2: base = context->Edx; break; ++ case 3: base = context->Ebx; break; ++ case 4: base = context->Esp; break; ++ case 5: base = context->Ebp; break; ++ case 6: base = context->Esi; break; ++ case 7: base = context->Edi; break; ++ } ++ switch (mod) ++ { ++ case 0: ++ if (rm == 5) /* special case: ds:(disp32) */ ++ { ++ GET_VAL( &base, DWORD ); ++ } ++ break; ++ ++ case 1: /* 8-bit disp */ ++ GET_VAL( &off, BYTE ); ++ base += (signed char)off; ++ break; ++ ++ case 2: /* 32-bit disp */ ++ GET_VAL( &off, DWORD ); ++ base += (signed long)off; ++ break; ++ } ++ } ++ else /* short address */ ++ { ++ switch(rm) ++ { ++ case 0: /* ds:(bx,si) */ ++ base = LOWORD(context->Ebx) + LOWORD(context->Esi); ++ break; ++ case 1: /* ds:(bx,di) */ ++ base = LOWORD(context->Ebx) + LOWORD(context->Edi); ++ break; ++ case 2: /* ss:(bp,si) */ ++ base = LOWORD(context->Ebp) + LOWORD(context->Esi); ++ break; ++ case 3: /* ss:(bp,di) */ ++ base = LOWORD(context->Ebp) + LOWORD(context->Edi); ++ break; ++ case 4: /* ds:(si) */ ++ base = LOWORD(context->Esi); ++ break; ++ case 5: /* ds:(di) */ ++ base = LOWORD(context->Edi); ++ break; ++ case 6: /* ss:(bp) */ ++ base = LOWORD(context->Ebp); ++ break; ++ case 7: /* ds:(bx) */ ++ base = LOWORD(context->Ebx); ++ break; ++ } ++ ++ switch(mod) ++ { ++ case 0: ++ if (rm == 6) /* special case: ds:(disp16) */ ++ { ++ GET_VAL( &base, WORD ); ++ } ++ break; ++ ++ case 1: /* 8-bit disp */ ++ GET_VAL( &off, BYTE ); ++ base += (signed char)off; ++ break; ++ ++ case 2: /* 16-bit disp */ ++ GET_VAL( &off, WORD ); ++ base += (signed short)off; ++ break; ++ } ++ base &= 0xffff; ++ } ++ /* FIXME: we assume that all segments have a base of 0 */ ++ return (BYTE *)(base + (index << ss)); ++#undef GET_VAL ++} ++ ++ ++/*********************************************************************** ++ * check_invalid_instr ++ * ++ * Support for instructions not implemented by Exagear. ++ */ ++static inline BOOL check_invalid_instr( CONTEXT *context ) ++{ ++ const BYTE *instr; ++ unsigned int prefix_count = 0; ++ int len, long_addr = 1; ++ ++ if (!wine_ldt_is_system( context->SegCs )) return FALSE; ++ instr = (BYTE *)context->Eip; ++ ++ for (;;) switch (*instr) ++ { ++ /* instruction prefixes */ ++ case 0x2e: /* %cs: */ ++ case 0x36: /* %ss: */ ++ case 0x3e: /* %ds: */ ++ case 0x26: /* %es: */ ++ case 0x64: /* %fs: */ ++ case 0x65: /* %gs: */ ++ case 0x66: /* opcode size */ ++ case 0x67: /* addr size */ ++ case 0xf0: /* lock */ ++ case 0xf2: /* repne */ ++ case 0xf3: /* repe */ ++ if (++prefix_count >= 15) return FALSE; ++ if (*instr == 0x67) long_addr = !long_addr; /* addr size */ ++ instr++; ++ continue; ++ case 0x0f: /* extended instruction */ ++ switch (instr[1]) ++ { ++ case 0x01: ++ if (((instr[2] >> 3) & 7) == 1) /* sidt m */ ++ { ++ struct idtr ret; ++ BYTE *addr; ++ ++ if ((instr[2] & 7) == 3) return FALSE; /* loading to register not allowed */ ++ addr = INSTR_GetOperandAddr( context, instr + 2, long_addr, 0, &len ); ++ ++ /* fake IDT structure */ ++ ret.limit = 0xfff; ++ ret.base = (void *)0xff000000; ++ memcpy(addr, &ret, sizeof(ret)); ++ ++ context->Eip += prefix_count + len + 2; ++ return TRUE; ++ } ++ break; ++ } ++ return FALSE; ++ default: ++ return FALSE; ++ } ++} ++ ++#endif /* EXAGEAR_COMPAT */ ++ ++ + /*********************************************************************** + * check_invalid_gs + * +@@ -1902,6 +2118,14 @@ static void WINAPI raise_segv_exception( EXCEPTION_RECORD *rec, CONTEXT *context + + switch(rec->ExceptionCode) + { ++#ifdef EXAGEAR_COMPAT ++ case EXCEPTION_ILLEGAL_INSTRUCTION: ++ { ++ if (check_invalid_instr( context )) ++ goto done; ++ } ++ break; ++#endif + case EXCEPTION_ACCESS_VIOLATION: + if (rec->NumberParameters == 2) + { +-- +2.1.3 + diff --git a/patches/Exagear/definition b/patches/Exagear/definition new file mode 100644 index 00000000..2617b3f7 --- /dev/null +++ b/patches/Exagear/definition @@ -0,0 +1,3 @@ +Author: Sebastian Lackner +Subject: Implement emulation SIDT instruction when using Exagear. +Revision: 1 diff --git a/patches/Makefile b/patches/Makefile index d98e622e..e2925e0b 100644 --- a/patches/Makefile +++ b/patches/Makefile @@ -19,6 +19,7 @@ APPLY_FILE = @echo "Applying $(1)"; $(APPLY) < "$(CURDIR)/$(1)" # PATCHLIST := \ + Exagear.ok \ Miscellaneous.ok \ Pipelight.ok \ Staging.ok \ @@ -164,6 +165,21 @@ clean: rm -f series patchlist.diff rm -f *.ok +# Patchset Exagear +# | +# | Included patches: +# | * Implement emulation SIDT instruction when using Exagear. [by Sebastian Lackner] +# | +# | Modified files: +# | * configure.ac, dlls/ntdll/signal_i386.c +# | +.INTERMEDIATE: Exagear.ok +Exagear.ok: + $(call APPLY_FILE,Exagear/0001-ntdll-Implement-emulation-SIDT-instruction-when-usin.patch) + @( \ + echo '+ { "Exagear", "Sebastian Lackner", "Implement emulation SIDT instruction when using Exagear." },'; \ + ) > Exagear.ok + # Patchset Miscellaneous # | # | Included patches: