home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 6 File / 06-File.zip / ramfs102.zip / src / patch / kernfix.c < prev    next >
Encoding:
C/C++ Source or Header  |  2002-10-20  |  5.6 KB  |  176 lines

  1. /* $Id: kernfix.c,v 1.1.2.1 2002/10/21 00:11:39 root Exp $ */
  2.  
  3. /* Kernel fixup to allow using NPX registers in FSDs.
  4.  *
  5.  * Background: the kernel traps with MMX-based drivers if a user-mode program:
  6.  *
  7.  * 1. Executes FP code (including the LIBCS.DLL setup routines),
  8.  *    AND
  9.  * 2. Operates with files on RAMFS.
  10.  *
  11.  * The trap occurs during program termination in SaveNPX (14.091b_W4):
  12.  *
  13.  * (ebx is zero)
  14.  * 0178:fff19dbe 8b9b38020000   mov       ebx,dword ptr [ebx+00000238]
  15.  * 0178:fff19dc4 66833dccf6dbff02 cmp       word ptr [ffdbf6cc],+02
  16.  * 0178:fff19dcc 7505           jnz       fff19dd3
  17.  * 0178:fff19dce 0fae03         fxsave    dword ptr [ebx]
  18.  * 0178:fff19dd1 eb02           jmp       fff19dd5
  19.  * 0178:fff19dd3 dd33           fsave     byte ptr [ebx]
  20.  * 0178:fff19dd5 32c0           xor       al,al
  21.  * 0178:fff19dd7 e6f0           out       f0,al
  22.  * 0178:fff19dd9 66c70562addbff0000 mov       word ptr [NPX_Owner (ffdbad62)],0000
  23.  * 0178:fff19de2 07             pop     es
  24.  * 0178:fff19de3 5e             pop       esi
  25.  * 0178:fff19de4 59             pop       ecx
  26.  *
  27.  * Seems like the kernel is trying to save the NPX context for a thread that is
  28.  * being cleaned up. And yes, the FSD _does_ perform the necessary fsave/frstor
  29.  * around the memory transfers.
  30.  *
  31.  * Mangling with CR0 TS/EM flags would slow down the system to a freeze, so not
  32.  * letting the kernel to know about NPX transactions in the FSD is a wrong way.
  33.  *
  34.  * The correct workaround was to cut in the kernel code above the failing
  35.  * instruction:
  36.  *
  37.  * 0178:fff19dbb 8B1C98         mov       ebx,[eax][ebx]*4
  38.  * 0178:fff19dbe 8B9B38020000   mov       ebx,[ebx][000000238]
  39.  *
  40.  * And replace it with a far call to our routine (to fit in 9 bytes):
  41.  *
  42.  * 0178:fff19dbb 9Axxxxxxxxxxxx call      far32 ptr _savenpx_override
  43.  * 0178:fff19dbe 7215           jc        fff19dd9
  44.  *
  45.  * See the ASM file for the routine body.
  46.  *
  47.  * AAB 15/10/2002 */
  48.  
  49. #include <stddef.h>
  50.  
  51. #include "std32.h"
  52.  
  53. #include "ldrtypes.h"
  54. #include "ldrmte.h"
  55.  
  56. #include "patchram.h"
  57.  
  58. /* Imported stuff */
  59.  
  60. struct ldrmte_s * locate_krnl_mte();
  61. extern unsigned long npx_tcb_base;
  62. void savenpx_override();
  63. unsigned short get_cs();
  64.  
  65. /* SaveNPX */
  66.  
  67. struct locator os2krnl_savenpx[]=
  68. {
  69.  {0, 1, 0x50},                          /* Entry */
  70.  {1, 1, 0x51},
  71.  {1, 1, 0x56},
  72.  {1, 1, 0x06},
  73.  {1, 1, 0x0F},
  74.  {1, 1, 0x06},
  75.  {4, 12, 0x0F},                         /* movzx ebx, bx */
  76.  {1, 1, 0xB7},
  77.  {1, 1, 0xDB},
  78.  {1, 16, 0xA1},                         /* mov eax, ... _papTCBSlots */
  79.  {3, 16, 0x8B},                         /* mov ebx, dword ptr [eax+ebx*4] */
  80.  {1, 1, 0x1C},
  81.  {1, 1, 0x98},
  82.  {1, 1, 0x8B},                          /* mov ebx,                     */
  83.  {1, 1, 0x9B},                          /*          dword ptr [ebx+...] */
  84.  /* 6 bytes (incl. previous 2 bytes) to cut in here! */
  85.  {3, 1, 0x00},                          /* The structures are unlikely */
  86.  {1, 1, 0x00},                          /* to exceed 65536 bytes! */
  87.  /* Cut-in area ends! Next goes a Katmai branch which is kernel specific
  88.     (older kernels don't care about SSE), and some gap should be accounted
  89.     for. */
  90.  {3, 127, 0x66},                        /* Landing area */
  91.  {1, 1, 0xC7},                          /* Store immediate value: */
  92.  {6, 1, 0x00},                          /* 00 */
  93.  {1, 1, 0x00},                          /* 00 */
  94.  {1, 32, 0x07},                         /* Exit sequence */
  95.  {1, 1, 0x5E},
  96.  {1, 1, 0x59},
  97.  {1, 1, 0x58},
  98.  {-1, -1, 0} 
  99. };
  100.  
  101. /* Patch area */
  102.  
  103. struct locator os2krnl_npx_takeoff[]=
  104. {
  105.  {0, 1, 0x8B},                          /* mov ebx, dword ptr [eax+ebx*4] */
  106.  {1, 1, 0x1C},
  107.  {1, 1, 0x98},
  108.  {1, 1, 0x8B},                          /* mov ebx,                     */
  109.  {1, 1, 0x9B},                          /*          dword ptr [ebx+...] */
  110.  /* 6 bytes (incl. previous 2 bytes) to cut in here! */
  111.  {3, 1, 0x00},                          /* The structures is unlikely */
  112.  {1, 1, 0x00},                          /* to exceed 65536 bytes! */
  113.  {-1, -1, 0} 
  114. };
  115.  
  116. /* Landing area */
  117.  
  118. struct locator os2krnl_npx_landing[]=
  119. {
  120.  {0, 1, 0x66},                          /* 386 */
  121.  {1, 1, 0xC7},                          /* Store immediate value: */
  122.  {6, 1, 0x00},                          /* 00 */
  123.  {1, 1, 0x00},                          /* 00 */
  124.  {1, 32, 0x07},                         /* Exit sequence */
  125.  {1, 1, 0x5E},
  126.  {1, 1, 0x59},
  127.  {1, 1, 0x58},
  128.  {-1, -1, 0} 
  129. };
  130.  
  131. /* Installs the NPX hook */
  132.  
  133. int _far fix_kernel()
  134. {
  135.  struct ldrote_s *objtab;
  136.  struct ldrmte_s *pmte;
  137.  unsigned int i, j;
  138.  struct area a;
  139.  long o, ot, ol;
  140.  int rc=1;
  141.  int npx_hook_installed=0;
  142.  
  143.  pmte=locate_krnl_mte();
  144.  if(pmte==NULL)
  145.   return(1);
  146.  objtab=(struct ldrote_s *)pmte->mte_swapmte->smte_objtab;
  147.  if(objtab==NULL)
  148.   return(1);
  149.  i=pmte->mte_swapmte->smte_objcnt-1;
  150.  a.first=(char *)objtab[i].ote_base;
  151.  a.len=objtab[i].ote_size;
  152.  /* NPX hook */
  153.  if(!npx_hook_installed)
  154.  {
  155.   if((o=locate(os2krnl_savenpx, (struct area *)SSToDS(&a), 0))!=-1&&
  156.      (ot=locate(os2krnl_npx_takeoff, (struct area *)SSToDS(&a), o))!=-1&&
  157.      (ol=locate(os2krnl_npx_landing, (struct area *)SSToDS(&a), ot))!=-1&&
  158.      (ol-ot)<137)
  159.   {
  160.    npx_tcb_base=*(unsigned long *)&a.first[ot+5];
  161.    /* Compose the code to drive away from IBM's procedure */
  162.    a.pos=ot;
  163.    ac(0x9A);                          /* call far ... */
  164.    ad((unsigned long)savenpx_override);
  165.    aw(get_cs());
  166.    ac(0x72);                          /* jc */
  167.    ac((unsigned char)((ol-ot)-9));
  168.    npx_hook_installed=1;
  169.    a.pos=o;
  170.    rc=0;
  171.   }
  172.  }
  173.  /* Report if the patch found its way into the kernel. */
  174.  return(rc);
  175. }
  176.