ALPHA-pl15d
diff --git a/Makefile b/Makefile
index 5c71b86..a65d090 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 0.99
 PATCHLEVEL = 15
-ALPHA = c
+ALPHA = d
 
 all:	Version zImage
 
diff --git a/drivers/FPU-emu/README b/drivers/FPU-emu/README
index 8493558..1ae3263 100644
--- a/drivers/FPU-emu/README
+++ b/drivers/FPU-emu/README
@@ -47,7 +47,7 @@
 
 
 --Bill Metzenthen
-  Jan 1994
+  Feb 1994
 
 
 ----------------------- Internals of wm-FPU-emu -----------------------
@@ -92,21 +92,12 @@
 ----------------------- Limitations of wm-FPU-emu -----------------------
 
 There are a number of differences between the current wm-FPU-emu
-(version beta 1.5) and the 80486 FPU (apart from bugs). Some of the
+(version beta 1.10) and the 80486 FPU (apart from bugs). Some of the
 more important differences are listed below:
 
-Segment overrides don't do anything yet.
-
-All internal computations are performed at 64 bit or higher precision
-and the results rounded etc as required by the PC bits of the FPU
-control word.  Under the crt0 version for Linux current at June 1993,
-the FPU PC bits specify 64 bits precision.
-
-The precision flag (PE of the FPU status word) and the Roundup flag
-(C1 of the status word) are now implemented. Does anyone write code
-which uses these features? The Roundup flag does not have much meaning
-for the transcendental functions and its 80486 value with these
-functions is likely to differ from its emulator value.
+The Roundup flag does not have much meaning for the transcendental
+functions and its 80486 value with these functions is likely to differ
+from its emulator value.
 
 In a few rare cases the Underflow flag obtained with the emulator will
 be different from that obtained with an 80486. This occurs when the
@@ -140,6 +131,19 @@
 numbers in an FPU register with its identity as a PseudoDenormal, but
 the emulator will not; they are always converted to a valid number.
 
+Self modifying code can cause the emulator to fail. An example of such
+code is:
+          movl %esp,[%ebx]
+	  fld1
+The FPU instruction may be (usually will be) loaded into the pre-fetch
+queue of the cpu before the mov instruction is executed. If the
+destination of the 'movl' overlaps the FPU instruction then the bytes
+in the prefetch queue and memory will be inconsistent when the FPU
+instruction is executed. The emulator will be invoked but will not be
+able to find the instruction which caused the device-not-present
+exception. For this case, the emulator cannot emulate the behaviour of
+an 80486DX.
+
 ----------------------- Performance of wm-FPU-emu -----------------------
 
 Speed.
diff --git a/drivers/FPU-emu/errors.c b/drivers/FPU-emu/errors.c
index 99de4fa..0454c51 100644
--- a/drivers/FPU-emu/errors.c
+++ b/drivers/FPU-emu/errors.c
@@ -85,13 +85,15 @@
   RE_ENTRANT_CHECK_OFF;
   /* No need to verify_area(), we have previously fetched these bytes. */
   printk("At %p: ", (void *) address);
-  while ( 1 )
+#define MAX_PRINTED_BYTES 20
+  for ( i = 0; i < MAX_PRINTED_BYTES; i++ )
     {
       byte1 = get_fs_byte((unsigned char *) address);
       if ( (byte1 & 0xf8) == 0xd8 ) break;
       printk("[%02x]", byte1);
       address++;
     }
+  if ( i == MAX_PRINTED_BYTES ) printk("[more..]");
   printk("%02x ", byte1);
   FPU_modrm = get_fs_byte(1 + (unsigned char *) address);
   partial_status = status_word();
@@ -234,6 +236,7 @@
 	      0x126  in fpu_entry.c
 	      0x127  in poly_2xm1.c
 	      0x128  in fpu_entry.c
+	      0x130  in get_address.c
        0x2nn  in an *.S file:
               0x201  in reg_u_add.S
               0x202  in reg_u_div.S
@@ -310,11 +313,11 @@
 #endif PRINT_MESSAGES
 	}
       else
-	printk("FP emulator: Unknown Exception: 0x%04x!\n", n);
+	printk("FPU emulator: Unknown Exception: 0x%04x!\n", n);
       
       if ( n == EX_INTERNAL )
 	{
-	  printk("FP emulator: Internal error type 0x%04x\n", int_type);
+	  printk("FPU emulator: Internal error type 0x%04x\n", int_type);
 	  emu_printall();
 	}
 #ifdef PRINT_MESSAGES
diff --git a/drivers/FPU-emu/fpu_emu.h b/drivers/FPU-emu/fpu_emu.h
index 7b1a7e8..49e02ed 100644
--- a/drivers/FPU-emu/fpu_emu.h
+++ b/drivers/FPU-emu/fpu_emu.h
@@ -94,7 +94,11 @@
 
 typedef void (*FUNC)(void);
 typedef struct fpu_reg FPU_REG;
-typedef struct { unsigned char address_size, segment; } overrides;
+typedef struct { unsigned char address_size, operand_size, segment; }
+        overrides;
+/* This structure is 32 bits: */
+typedef struct { overrides override;
+		 unsigned char vm86; } fpu_addr_modes;
 
 #define	st(x)	( regs[((top+x) &7 )] )
 
diff --git a/drivers/FPU-emu/fpu_entry.c b/drivers/FPU-emu/fpu_entry.c
index 063f54f..944a9da 100644
--- a/drivers/FPU-emu/fpu_entry.c
+++ b/drivers/FPU-emu/fpu_entry.c
@@ -137,13 +137,14 @@
 char emulating=0;
 #endif PARANOID
 
-static int valid_prefix(unsigned char *byte, overrides *override);
+static int valid_prefix(unsigned char *Byte, unsigned char **fpu_eip,
+			overrides *override);
 
 
 asmlinkage void math_emulate(long arg)
 {
   unsigned char  FPU_modrm, byte1;
-  overrides override;
+  fpu_addr_modes addr_modes;
   int unmasked;
 
 #ifdef PARANOID
@@ -170,35 +171,40 @@
 
   SETUP_DATA_AREA(arg);
 
+  addr_modes.vm86 = (FPU_EFLAGS & 0x00020000) != 0;
+
+  if ( addr_modes.vm86 )
+    FPU_EIP += FPU_CS << 4;
+
   FPU_ORIG_EIP = FPU_EIP;
 
-  /* We cannot handle emulation in v86-mode */
-  if (FPU_EFLAGS & 0x00020000)
+  if ( !addr_modes.vm86 )
     {
-      math_abort(FPU_info,SIGILL);
-    }
+      /* user code space? */
+      if (FPU_CS == KERNEL_CS)
+	{
+	  printk("math_emulate: %04x:%08lx\n",FPU_CS,FPU_EIP);
+	  panic("Math emulation needed in kernel");
+	}
 
-  /* user code space? */
-  if (FPU_CS == KERNEL_CS)
-    {
-      printk("math_emulate: %04x:%08lx\n",FPU_CS,FPU_EIP);
-      panic("Math emulation needed in kernel");
-    }
-
-  /* We cannot handle multiple segments yet */
-  if (FPU_CS != USER_CS || FPU_DS != USER_DS)
-    {
-      math_abort(FPU_info,SIGILL);
+      /* We cannot handle multiple segments yet */
+      if (FPU_CS != USER_CS || FPU_DS != USER_DS)
+	{
+	  math_abort(FPU_info,SIGILL);
+	}
     }
 
   FPU_lookahead = 1;
   if (current->flags & PF_PTRACED)
-  	FPU_lookahead = 0;
+    FPU_lookahead = 0;
 
-  if ( !valid_prefix(&byte1, &override) )
+  if ( !valid_prefix(&byte1, (unsigned char **)&FPU_EIP,
+		     &addr_modes.override) )
     {
       RE_ENTRANT_CHECK_OFF;
-      printk("FPU emulator: Unknown prefix byte 0x%02x\n", byte1);
+      printk("FPU emulator: Unknown prefix byte 0x%02x, probably due to\n"
+	     "FPU emulator: self-modifying code! (emulation impossible)\n",
+	     byte1);
       RE_ENTRANT_CHECK_ON;
       EXCEPTION(EX_INTERNAL|0x126);
       math_abort(FPU_info,SIGILL);
@@ -289,7 +295,11 @@
   if ( FPU_modrm < 0300 )
     {
       /* All of these instructions use the mod/rm byte to get a data address */
-      get_address(FPU_modrm, override);
+      if ( addr_modes.vm86
+	  ^ (addr_modes.override.address_size == ADDR_SIZE_PREFIX) )
+	get_address_16(FPU_modrm, &FPU_EIP, addr_modes);
+      else
+	get_address(FPU_modrm, &FPU_EIP, addr_modes);
       if ( !(byte1 & 1) )
 	{
 	  unsigned short status1 = partial_status;
@@ -303,16 +313,16 @@
 	      switch ( (byte1 >> 1) & 3 )
 		{
 		case 0:
-		  unmasked = reg_load_single(override);
+		  unmasked = reg_load_single();
 		  break;
 		case 1:
-		  reg_load_int32(override);
+		  reg_load_int32();
 		  break;
 		case 2:
-		  unmasked = reg_load_double(override);
+		  unmasked = reg_load_double();
 		  break;
 		case 3:
-		  reg_load_int16(override);
+		  reg_load_int16();
 		  break;
 		}
 	      
@@ -440,7 +450,8 @@
 	}
       else
 	{
-	  load_store_instr(((FPU_modrm & 0x38) | (byte1 & 6)) >> 1, override);
+	  load_store_instr(((FPU_modrm & 0x38) | (byte1 & 6)) >> 1,
+			   addr_modes);
 	}
 
     reg_mem_instr_done:
@@ -527,10 +538,14 @@
   if (FPU_lookahead && !need_resched)
     {
       FPU_ORIG_EIP = FPU_EIP;
-      if ( valid_prefix(&byte1, &override) )
+      if ( valid_prefix(&byte1, (unsigned char **)&FPU_EIP,
+			&addr_modes.override) )
 	goto do_another_FPU_instruction;
     }
 
+  if ( addr_modes.vm86 )
+    FPU_EIP -= FPU_CS << 4;
+
   RE_ENTRANT_CHECK_OFF;
 }
 
@@ -539,16 +554,17 @@
    all prefix bytes, further changes are needed in the emulator code
    which accesses user address space. Access to separate segments is
    important for msdos emulation. */
-static int valid_prefix(unsigned char *Byte, overrides *override)
+static int valid_prefix(unsigned char *Byte, unsigned char **fpu_eip,
+			overrides *override)
 {
   unsigned char byte;
-  unsigned long ip = FPU_EIP;
+  unsigned char *ip = *fpu_eip;
 
-  *override = (overrides) { 0, PREFIX_DS };       /* defaults */
+  *override = (overrides) { 0, 0, PREFIX_DS };       /* defaults */
 
   RE_ENTRANT_CHECK_OFF;
   FPU_code_verify_area(1);
-  byte = get_fs_byte((unsigned char *) FPU_EIP);
+  byte = get_fs_byte(ip);
   RE_ENTRANT_CHECK_ON;
 
   while ( 1 )
@@ -558,6 +574,11 @@
 	case ADDR_SIZE_PREFIX:
 	  override->address_size = ADDR_SIZE_PREFIX;
 	  goto do_next_byte;
+
+	case OP_SIZE_PREFIX:
+	  override->operand_size = OP_SIZE_PREFIX;
+	  goto do_next_byte;
+
 	case PREFIX_CS:
 	  override->segment = PREFIX_CS;
 	  goto do_next_byte;
@@ -585,12 +606,11 @@
 	case PREFIX_REPE:
 	case PREFIX_REPNE:
 
-	case OP_SIZE_PREFIX:  /* Used often by gcc, but has no effect. */
 	do_next_byte:
-	  FPU_EIP++;
+	  ip++;
 	  RE_ENTRANT_CHECK_OFF;
 	  FPU_code_verify_area(1);
-	  byte = get_fs_byte((unsigned char *) (FPU_EIP));
+	  byte = get_fs_byte(ip);
 	  RE_ENTRANT_CHECK_ON;
 	  break;
 	case FWAIT_OPCODE:
@@ -600,6 +620,7 @@
 	  if ( (byte & 0xf8) == 0xd8 )
 	    {
 	      *Byte = byte;
+	      *fpu_eip = ip;
 	      return 1;
 	    }
 	  else
@@ -607,7 +628,6 @@
 	      /* Not a valid sequence of prefix bytes followed by
 		 an FPU instruction. */
 	      *Byte = byte;  /* Needed for error message. */
-	      FPU_EIP = ip;
 	      return 0;
 	    }
 	}
diff --git a/drivers/FPU-emu/fpu_proto.h b/drivers/FPU-emu/fpu_proto.h
index ca659a2..a55f2d9 100644
--- a/drivers/FPU-emu/fpu_proto.h
+++ b/drivers/FPU-emu/fpu_proto.h
@@ -63,10 +63,13 @@
 extern void trig_b(void);
 
 /* get_address.c */
-extern void get_address(unsigned char FPU_modrm, overrides override);
+extern void get_address(unsigned char FPU_modrm, unsigned long *fpu_eip,
+			fpu_addr_modes);
+extern void get_address_16(unsigned char FPU_modrm, unsigned long *fpu_eip,
+			   fpu_addr_modes);
 
 /* load_store.c */
-extern void load_store_instr(char type, overrides override);
+extern void load_store_instr(char type, fpu_addr_modes addr_modes);
 
 /* poly_2xm1.c */
 extern int poly_2xm1(FPU_REG const *arg, FPU_REG *result);
@@ -105,26 +108,26 @@
 extern void fconst(void);
 
 /* reg_ld_str.c */
-extern int reg_load_extended(overrides override);
-extern int reg_load_double(overrides override);
-extern int reg_load_single(overrides override);
-extern void reg_load_int64(overrides override);
-extern void reg_load_int32(overrides override);
-extern void reg_load_int16(overrides override);
-extern void reg_load_bcd(overrides override);
-extern int reg_store_extended(overrides override);
-extern int reg_store_double(overrides override);
-extern int reg_store_single(overrides override);
-extern int reg_store_int64(overrides override);
-extern int reg_store_int32(overrides override);
-extern int reg_store_int16(overrides override);
-extern int reg_store_bcd(overrides override);
+extern int reg_load_extended(void);
+extern int reg_load_double(void);
+extern int reg_load_single(void);
+extern void reg_load_int64(void);
+extern void reg_load_int32(void);
+extern void reg_load_int16(void);
+extern void reg_load_bcd(void);
+extern int reg_store_extended(void);
+extern int reg_store_double(void);
+extern int reg_store_single(void);
+extern int reg_store_int64(void);
+extern int reg_store_int32(void);
+extern int reg_store_int16(void);
+extern int reg_store_bcd(void);
 extern int round_to_int(FPU_REG *r);
-extern char *fldenv(void);
-extern void frstor(void);
+extern char *fldenv(fpu_addr_modes addr_modes);
+extern void frstor(fpu_addr_modes addr_modes);
 extern unsigned short tag_word(void);
-extern char *fstenv(void);
-extern void fsave(void);
+extern char *fstenv(fpu_addr_modes addr_modes);
+extern void fsave(fpu_addr_modes addr_modes);
 
 /* reg_mul.c */
 extern int reg_mul(FPU_REG const *a, FPU_REG const *b,
diff --git a/drivers/FPU-emu/fpu_system.h b/drivers/FPU-emu/fpu_system.h
index 52ae0f7..a8e7af3 100644
--- a/drivers/FPU-emu/fpu_system.h
+++ b/drivers/FPU-emu/fpu_system.h
@@ -23,7 +23,12 @@
 #define FPU_info		(I387.soft.info)
 
 #define FPU_CS			(*(unsigned short *) &(FPU_info->___cs))
+#define FPU_SS			(*(unsigned short *) &(FPU_info->___ss))
 #define FPU_DS			(*(unsigned short *) &(FPU_info->___ds))
+#define FPU_VM86_ES             ((&FPU_SS)[2])
+#define FPU_VM86_DS             ((&FPU_SS)[4])
+#define FPU_VM86_FS             ((&FPU_SS)[6])
+#define FPU_VM86_GS             ((&FPU_SS)[8])
 #define FPU_EAX			(FPU_info->___eax)
 #define FPU_EFLAGS		(FPU_info->___eflags)
 #define FPU_EIP			(FPU_info->___eip)
diff --git a/drivers/FPU-emu/get_address.c b/drivers/FPU-emu/get_address.c
index f2b00b5..224cb60 100644
--- a/drivers/FPU-emu/get_address.c
+++ b/drivers/FPU-emu/get_address.c
@@ -41,16 +41,16 @@
 
 
 /* Decode the SIB byte. This function assumes mod != 0 */
-static void *sib(int mod)
+static void *sib(int mod, unsigned long *fpu_eip)
 {
   unsigned char ss,index,base;
   long offset;
 
   RE_ENTRANT_CHECK_OFF;
   FPU_code_verify_area(1);
-  base = get_fs_byte((char *) FPU_EIP);   /* The SIB byte */
+  base = get_fs_byte((char *) (*fpu_eip));   /* The SIB byte */
   RE_ENTRANT_CHECK_ON;
-  FPU_EIP++;
+  (*fpu_eip)++;
   ss = base >> 6;
   index = (base >> 3) & 7;
   base &= 7;
@@ -77,23 +77,51 @@
       /* 8 bit signed displacement */
       RE_ENTRANT_CHECK_OFF;
       FPU_code_verify_area(1);
-      offset += (signed char) get_fs_byte((char *) FPU_EIP);
+      offset += (signed char) get_fs_byte((char *) (*fpu_eip));
       RE_ENTRANT_CHECK_ON;
-      FPU_EIP++;
+      (*fpu_eip)++;
     }
   else if (mod == 2 || base == 5) /* The second condition also has mod==0 */
     {
       /* 32 bit displacment */
       RE_ENTRANT_CHECK_OFF;
       FPU_code_verify_area(4);
-      offset += (signed) get_fs_long((unsigned long *) FPU_EIP);
+      offset += (signed) get_fs_long((unsigned long *) (*fpu_eip));
       RE_ENTRANT_CHECK_ON;
-      FPU_EIP += 4;
+      (*fpu_eip) += 4;
     }
 
   return (void *) offset;
 }
 
+static unsigned long vm86_segment(char segment)
+{ 
+  switch ( segment )
+    {
+    case PREFIX_CS:
+      return FPU_CS << 4;
+      break;
+    case PREFIX_SS:
+      return FPU_SS << 4;
+      break;
+    case PREFIX_ES:
+      return FPU_VM86_ES << 4;
+      break;
+    case PREFIX_DS:
+      return FPU_VM86_DS << 4;
+      break;
+    case PREFIX_FS:
+      return FPU_VM86_FS << 4;
+      break;
+    case PREFIX_GS:
+      return FPU_VM86_GS << 4;
+      break;
+    default:
+      EXCEPTION(EX_INTERNAL|0x130);
+      return 0; /* Keep gcc quiet. */
+    }
+}
+
 
 /*
        MOD R/M byte:  MOD == 3 has a special use for the FPU
@@ -112,7 +140,8 @@
 
 */
 
-void get_address(unsigned char FPU_modrm, overrides override)
+void get_address(unsigned char FPU_modrm, unsigned long *fpu_eip,
+		 fpu_addr_modes addr_modes)
 {
   unsigned char mod;
   long *cpu_reg_ptr;
@@ -123,11 +152,20 @@
   FPU_data_selector = FPU_DS;
 #endif PECULIAR_486
 
+  /* Memory accessed via the cs selector is write protected
+     in 32 bit protected mode. */
+#define FPU_WRITE_BIT 0x10
+  if ( !addr_modes.vm86 && (FPU_modrm & FPU_WRITE_BIT)
+      && (addr_modes.override.segment == PREFIX_CS) )
+    {
+      math_abort(FPU_info,SIGSEGV);
+    }
+
   mod = (FPU_modrm >> 6) & 3;
 
   if (FPU_rm == 4 && mod != 3)
     {
-      FPU_data_address = sib(mod);
+      FPU_data_address = sib(mod, fpu_eip);
       return;
     }
 
@@ -137,20 +175,11 @@
     case 0:
       if (FPU_rm == 5)
 	{
-	  /* Special case: disp16 or disp32 */
+	  /* Special case: disp32 */
 	  RE_ENTRANT_CHECK_OFF;
-	  if ( override.address_size == ADDR_SIZE_PREFIX )
-	    {
-	      FPU_code_verify_area(2);
-	      offset = get_fs_word((unsigned short *) FPU_EIP);
-	      FPU_EIP += 2;
-	    }
-	  else
-	    {
-	      FPU_code_verify_area(4);
-	      offset = get_fs_long((unsigned long *) FPU_EIP);
-	      FPU_EIP += 4;
-	    }
+	  FPU_code_verify_area(4);
+	  offset = get_fs_long((unsigned long *) (*fpu_eip));
+	  (*fpu_eip) += 4;
 	  RE_ENTRANT_CHECK_ON;
 	  FPU_data_address = (void *) offset;
 	  return;
@@ -165,25 +194,16 @@
       /* 8 bit signed displacement */
       RE_ENTRANT_CHECK_OFF;
       FPU_code_verify_area(1);
-      offset = (signed char) get_fs_byte((char *) FPU_EIP);
+      offset = (signed char) get_fs_byte((char *) (*fpu_eip));
       RE_ENTRANT_CHECK_ON;
-      FPU_EIP++;
+      (*fpu_eip)++;
       break;
     case 2:
-      /* 16 or 32 bit displacement */
+      /* 32 bit displacement */
       RE_ENTRANT_CHECK_OFF;
-      if ( override.address_size == ADDR_SIZE_PREFIX )
-	{
-	  FPU_code_verify_area(2);
-	  offset = (signed) get_fs_word((unsigned short *) FPU_EIP);
-	  FPU_EIP += 2;
-	}
-      else
-	{
-	  FPU_code_verify_area(4);
-	  offset = (signed) get_fs_long((unsigned long *) FPU_EIP);
-	  FPU_EIP += 4;
-	}
+      FPU_code_verify_area(4);
+      offset = (signed) get_fs_long((unsigned long *) (*fpu_eip));
+      (*fpu_eip) += 4;
       RE_ENTRANT_CHECK_ON;
       break;
     case 3:
@@ -191,7 +211,108 @@
       EXCEPTION(EX_Invalid);
     }
 
+  if ( addr_modes.vm86 )
+    {
+      offset += vm86_segment(addr_modes.override.segment);
+    }
+
   FPU_data_address = offset + (char *)*cpu_reg_ptr;
-  if ( override.address_size == ADDR_SIZE_PREFIX )
-    FPU_data_address = (void *)((long)FPU_data_address & 0xffff);
 }
+
+
+void get_address_16(unsigned char FPU_modrm, unsigned long *fpu_eip,
+		      fpu_addr_modes addr_modes)
+{
+  unsigned char mod;
+  int offset = 0;     /* Default used for mod == 0 */
+
+#ifndef PECULIAR_486
+  /* This is a reasonable place to do this */
+  FPU_data_selector = FPU_DS;
+#endif PECULIAR_486
+
+  /* Memory accessed via the cs selector is write protected
+     in 32 bit protected mode. */
+#define FPU_WRITE_BIT 0x10
+  if ( !addr_modes.vm86 && (FPU_modrm & FPU_WRITE_BIT)
+      && (addr_modes.override.segment == PREFIX_CS) )
+    {
+      math_abort(FPU_info,SIGSEGV);
+    }
+
+  mod = (FPU_modrm >> 6) & 3;
+
+  switch (mod)
+    {
+    case 0:
+      if (FPU_rm == 6)
+	{
+	  /* Special case: disp16 */
+	  RE_ENTRANT_CHECK_OFF;
+	  FPU_code_verify_area(2);
+	  offset = (unsigned short)get_fs_word((unsigned short *) (*fpu_eip));
+	  (*fpu_eip) += 2;
+	  RE_ENTRANT_CHECK_ON;
+	  goto add_segment;
+	}
+      break;
+    case 1:
+      /* 8 bit signed displacement */
+      RE_ENTRANT_CHECK_OFF;
+      FPU_code_verify_area(1);
+      offset = (signed char) get_fs_byte((signed char *) (*fpu_eip));
+      RE_ENTRANT_CHECK_ON;
+      (*fpu_eip)++;
+      break;
+    case 2:
+      /* 16 bit displacement */
+      RE_ENTRANT_CHECK_OFF;
+      FPU_code_verify_area(2);
+      offset = (unsigned) get_fs_word((unsigned short *) (*fpu_eip));
+      (*fpu_eip) += 2;
+      RE_ENTRANT_CHECK_ON;
+      break;
+    case 3:
+      /* Not legal for the FPU */
+      EXCEPTION(EX_Invalid);
+      break;
+    }
+  switch ( FPU_rm )
+    {
+    case 0:
+      offset += FPU_info->___ebx + FPU_info->___esi;
+      break;
+    case 1:
+      offset += FPU_info->___ebx + FPU_info->___edi;
+      break;
+    case 2:
+      offset += FPU_info->___ebp + FPU_info->___esi;
+      break;
+    case 3:
+      offset += FPU_info->___ebp + FPU_info->___edi;
+      break;
+    case 4:
+      offset += FPU_info->___esi;
+      break;
+    case 5:
+      offset += FPU_info->___edi;
+      break;
+    case 6:
+      offset += FPU_info->___ebp;
+      break;
+    case 7:
+      offset += FPU_info->___ebx;
+      break;
+    }
+
+ add_segment:
+  offset &= 0xffff;
+
+  if ( addr_modes.vm86 )
+    {
+      offset += vm86_segment(addr_modes.override.segment);
+    }
+
+  FPU_data_address = (void *)offset ;
+}
+
diff --git a/drivers/FPU-emu/load_store.c b/drivers/FPU-emu/load_store.c
index 5b5737b..d1c1f75 100644
--- a/drivers/FPU-emu/load_store.c
+++ b/drivers/FPU-emu/load_store.c
@@ -46,7 +46,7 @@
   _NONE_, _REG0_, _NONE_, _REG0_
   };
 
-void load_store_instr(char type, overrides override)
+void load_store_instr(char type, fpu_addr_modes addr_modes)
 {
   FPU_REG *pop_ptr;  /* We need a version of FPU_st0_ptr which won't
 			change if the emulator is re-entered. */
@@ -85,7 +85,7 @@
   {
   case 000:       /* fld m32real */
     clear_C1();
-    reg_load_single(override);
+    reg_load_single();
     if ( (FPU_loaded_data.tag == TW_NaN) &&
 	real_2op_NaN(&FPU_loaded_data, &FPU_loaded_data, &FPU_loaded_data) )
       {
@@ -96,12 +96,12 @@
     break;
   case 001:      /* fild m32int */
     clear_C1();
-    reg_load_int32(override);
+    reg_load_int32();
     reg_move(&FPU_loaded_data, pop_ptr);
     break;
   case 002:      /* fld m64real */
     clear_C1();
-    reg_load_double(override);
+    reg_load_double();
     if ( (FPU_loaded_data.tag == TW_NaN) &&
 	real_2op_NaN(&FPU_loaded_data, &FPU_loaded_data, &FPU_loaded_data) )
       {
@@ -112,58 +112,58 @@
     break;
   case 003:      /* fild m16int */
     clear_C1();
-    reg_load_int16(override);
+    reg_load_int16();
     reg_move(&FPU_loaded_data, pop_ptr);
     break;
   case 010:      /* fst m32real */
     clear_C1();
-    reg_store_single(override);
+    reg_store_single();
     break;
   case 011:      /* fist m32int */
     clear_C1();
-    reg_store_int32(override);
+    reg_store_int32();
     break;
   case 012:     /* fst m64real */
     clear_C1();
-    reg_store_double(override);
+    reg_store_double();
     break;
   case 013:     /* fist m16int */
     clear_C1();
-    reg_store_int16(override);
+    reg_store_int16();
     break;
   case 014:     /* fstp m32real */
     clear_C1();
-    if ( reg_store_single(override) )
+    if ( reg_store_single() )
       pop_0();  /* pop only if the number was actually stored
 		 (see the 80486 manual p16-28) */
     break;
   case 015:     /* fistp m32int */
     clear_C1();
-    if ( reg_store_int32(override) )
+    if ( reg_store_int32() )
       pop_0();  /* pop only if the number was actually stored
 		 (see the 80486 manual p16-28) */
     break;
   case 016:     /* fstp m64real */
     clear_C1();
-    if ( reg_store_double(override) )
+    if ( reg_store_double() )
       pop_0();  /* pop only if the number was actually stored
 		 (see the 80486 manual p16-28) */
     break;
   case 017:     /* fistp m16int */
     clear_C1();
-    if ( reg_store_int16(override) )
+    if ( reg_store_int16() )
       pop_0();  /* pop only if the number was actually stored
 		 (see the 80486 manual p16-28) */
     break;
   case 020:     /* fldenv  m14/28byte */
-    fldenv();
+    fldenv(addr_modes);
     break;
   case 022:     /* frstor m94/108byte */
-    frstor();
+    frstor(addr_modes);
     break;
   case 023:     /* fbld m80dec */
     clear_C1();
-    reg_load_bcd(override);
+    reg_load_bcd();
     reg_move(&FPU_loaded_data, pop_ptr);
     break;
   case 024:     /* fldcw */
@@ -183,25 +183,25 @@
     break;
   case 025:      /* fld m80real */
     clear_C1();
-    reg_load_extended(override);
+    reg_load_extended();
     reg_move(&FPU_loaded_data, pop_ptr);
     break;
   case 027:      /* fild m64int */
     clear_C1();
-    reg_load_int64(override);
+    reg_load_int64();
     reg_move(&FPU_loaded_data, pop_ptr);
     break;
   case 030:     /* fstenv  m14/28byte */
-    fstenv();
+    fstenv(addr_modes);
     NO_NET_DATA_EFFECT;
     break;
   case 032:      /* fsave */
-    fsave();
+    fsave(addr_modes);
     NO_NET_DATA_EFFECT;
     break;
   case 033:      /* fbstp m80dec */
     clear_C1();
-    if ( reg_store_bcd(override) )
+    if ( reg_store_bcd() )
       pop_0();  /* pop only if the number was actually stored
 		 (see the 80486 manual p16-28) */
     break;
@@ -215,7 +215,7 @@
     break;
   case 035:      /* fstp m80real */
     clear_C1();
-    if ( reg_store_extended(override) )
+    if ( reg_store_extended() )
       pop_0();  /* pop only if the number was actually stored
 		 (see the 80486 manual p16-28) */
     break;
@@ -229,7 +229,7 @@
     break;
   case 037:      /* fistp m64int */
     clear_C1();
-    if ( reg_store_int64(override) )
+    if ( reg_store_int64() )
       pop_0();  /* pop only if the number was actually stored
 		 (see the 80486 manual p16-28) */
     break;
diff --git a/drivers/FPU-emu/reg_ld_str.c b/drivers/FPU-emu/reg_ld_str.c
index e8a55be..a768b4c 100644
--- a/drivers/FPU-emu/reg_ld_str.c
+++ b/drivers/FPU-emu/reg_ld_str.c
@@ -44,7 +44,7 @@
 
 
 /* Get a long double from user memory */
-int reg_load_extended(overrides override)
+int reg_load_extended(void)
 {
   long double *s = (long double *)FPU_data_address;
   unsigned long sigl, sigh, exp;
@@ -145,7 +145,7 @@
 
 
 /* Get a double from user memory */
-int reg_load_double(overrides override)
+int reg_load_double(void)
 {
   double *dfloat = (double *)FPU_data_address;
   int exp;
@@ -223,7 +223,7 @@
 
 
 /* Get a float from user memory */
-int reg_load_single(overrides override)
+int reg_load_single(void)
 {
   float *single = (float *)FPU_data_address;
   unsigned m32;
@@ -292,7 +292,7 @@
 
 
 /* Get a long long from user memory */
-void reg_load_int64(overrides override)
+void reg_load_int64(void)
 {
   long long *_s = (long long *)FPU_data_address;
   int e;
@@ -324,7 +324,7 @@
 
 
 /* Get a long from user memory */
-void reg_load_int32(overrides override)
+void reg_load_int32(void)
 {
   long *_s = (long *)FPU_data_address;
   long s;
@@ -356,7 +356,7 @@
 
 
 /* Get a short from user memory */
-void reg_load_int16(overrides override)
+void reg_load_int16(void)
 {
   short *_s = (short *)FPU_data_address;
   int s, e;
@@ -389,7 +389,7 @@
 
 
 /* Get a packed bcd array from user memory */
-void reg_load_bcd(overrides override)
+void reg_load_bcd(void)
 {
   char *s = (char *)FPU_data_address;
   int pos;
@@ -436,7 +436,7 @@
 /*===========================================================================*/
 
 /* Put a long double into user memory */
-int reg_store_extended(overrides override)
+int reg_store_extended(void)
 {
   /*
     The only exception raised by an attempt to store to an
@@ -475,7 +475,7 @@
 
 
 /* Put a double into user memory */
-int reg_store_double(overrides override)
+int reg_store_double(void)
 {
   double *dfloat = (double *)FPU_data_address;
   unsigned long l[2];
@@ -670,7 +670,7 @@
 
 
 /* Put a float into user memory */
-int reg_store_single(overrides override)
+int reg_store_single(void)
 {
   float *single = (float *)FPU_data_address;
   long templ;
@@ -859,7 +859,7 @@
 
 
 /* Put a long long into user memory */
-int reg_store_int64(overrides override)
+int reg_store_int64(void)
 {
   long long *d = (long long *)FPU_data_address;
   FPU_REG t;
@@ -918,7 +918,7 @@
 
 
 /* Put a long into user memory */
-int reg_store_int32(overrides override)
+int reg_store_int32(void)
 {
   long *d = (long *)FPU_data_address;
   FPU_REG t;
@@ -972,7 +972,7 @@
 
 
 /* Put a short into user memory */
-int reg_store_int16(overrides override)
+int reg_store_int16(void)
 {
   short *d = (short *)FPU_data_address;
   FPU_REG t;
@@ -1026,7 +1026,7 @@
 
 
 /* Put a packed bcd array into user memory */
-int reg_store_bcd(overrides override)
+int reg_store_bcd(void)
 {
   char *d = (char *)FPU_data_address;
   FPU_REG t;
@@ -1163,23 +1163,47 @@
 
 /*===========================================================================*/
 
-char *fldenv(void)
+char *fldenv(fpu_addr_modes addr_modes)
 {
   char *s = (char *)FPU_data_address;
   unsigned short tag_word = 0;
   unsigned char tag;
   int i;
 
-  RE_ENTRANT_CHECK_OFF;
-  FPU_verify_area(VERIFY_READ, s, 0x1c);
-  control_word = get_fs_word((unsigned short *) s);
-  partial_status = get_fs_word((unsigned short *) (s+4));
-  tag_word = get_fs_word((unsigned short *) (s+8));
-  ip_offset = get_fs_long((unsigned long *) (s+0x0c));
-  cs_selector = get_fs_long((unsigned long *) (s+0x10));
-  data_operand_offset = get_fs_long((unsigned long *) (s+0x14));
-  operand_selector = get_fs_long((unsigned long *) (s+0x18));
-  RE_ENTRANT_CHECK_ON;
+  if ( addr_modes.vm86
+      || (addr_modes.override.operand_size == OP_SIZE_PREFIX) )
+    {
+      RE_ENTRANT_CHECK_OFF;
+      FPU_verify_area(VERIFY_READ, s, 0x0e);
+      control_word = get_fs_word((unsigned short *) s);
+      partial_status = get_fs_word((unsigned short *) (s+2));
+      tag_word = get_fs_word((unsigned short *) (s+4));
+      ip_offset = get_fs_word((unsigned short *) (s+6));
+      cs_selector = get_fs_word((unsigned short *) (s+8));
+      data_operand_offset = get_fs_word((unsigned short *) (s+0x0a));
+      operand_selector = get_fs_word((unsigned short *) (s+0x0c));
+      RE_ENTRANT_CHECK_ON;
+      s += 0x0e;
+      if ( addr_modes.vm86 )
+	{
+	  ip_offset += (cs_selector & 0xf000) << 4;
+	  data_operand_offset += (operand_selector & 0xf000) << 4;
+	}
+    }
+  else
+    {
+      RE_ENTRANT_CHECK_OFF;
+      FPU_verify_area(VERIFY_READ, s, 0x1c);
+      control_word = get_fs_word((unsigned short *) s);
+      partial_status = get_fs_word((unsigned short *) (s+4));
+      tag_word = get_fs_word((unsigned short *) (s+8));
+      ip_offset = get_fs_long((unsigned long *) (s+0x0c));
+      cs_selector = get_fs_long((unsigned long *) (s+0x10));
+      data_operand_offset = get_fs_long((unsigned long *) (s+0x14));
+      operand_selector = get_fs_long((unsigned long *) (s+0x18));
+      RE_ENTRANT_CHECK_ON;
+      s += 0x1c;
+    }
 
   top = (partial_status >> SW_Top_Shift) & 7;
 
@@ -1226,21 +1250,21 @@
   NO_NET_DATA_EFFECT;
   NO_NET_INSTR_EFFECT;
 
-  return s + 0x1c;
+  return s;
 }
 
 
-void frstor(void)
+void frstor(fpu_addr_modes addr_modes)
 {
   int i, stnr;
   unsigned char tag;
-  char *s = fldenv();
+  char *s = fldenv(addr_modes);
 
   for ( i = 0; i < 8; i++ )
     {
       /* Load each register. */
       FPU_data_address = (void *)(s+i*10);
-      reg_load_extended((overrides){0,0});
+      reg_load_extended();
       stnr = (i+top) & 7;
       tag = regs[stnr].tag;   /* Derived from the loaded tag word. */
       reg_move(&FPU_loaded_data, &regs[stnr]);
@@ -1285,46 +1309,75 @@
 }
 
 
-char *fstenv(void)
+char *fstenv(fpu_addr_modes addr_modes)
 {
   char *d = (char *)FPU_data_address;
 
-  RE_ENTRANT_CHECK_OFF;
-  FPU_verify_area(VERIFY_WRITE,d,28);
+  if ( addr_modes.vm86
+      || (addr_modes.override.operand_size == OP_SIZE_PREFIX) )
+    {
+      RE_ENTRANT_CHECK_OFF;
+      FPU_verify_area(VERIFY_WRITE,d,14);
+      put_fs_word(control_word, (unsigned short *) d);
+      put_fs_word(status_word(), (unsigned short *) (d+2));
+      put_fs_word(tag_word(), (unsigned short *) (d+4));
+      put_fs_word(ip_offset, (unsigned short *) (d+6));
+      put_fs_word(data_operand_offset, (unsigned short *) (d+0x0a));
+      if ( addr_modes.vm86 )
+	{
+	  put_fs_word((ip_offset & 0xf0000) >> 4,
+		      (unsigned short *) (d+8));
+	  put_fs_word((data_operand_offset & 0xf0000) >> 4,
+		      (unsigned short *) (d+0x0c));
+	}
+      else
+	{
+	  put_fs_word(cs_selector, (unsigned short *) (d+8));
+	  put_fs_word(operand_selector, (unsigned short *) (d+0x0c));
+	}
+      RE_ENTRANT_CHECK_ON;
+      d += 0x0e;
+    }
+  else
+    {
+      RE_ENTRANT_CHECK_OFF;
+      FPU_verify_area(VERIFY_WRITE,d,28);
 #ifdef PECULIAR_486
-  /* An 80486 sets all the reserved bits to 1. */
-  put_fs_long(0xffff0040 | (control_word & ~0xe080), (unsigned long *) d);
-  put_fs_long(0xffff0000 | status_word(), (unsigned long *) (d+4));
-  put_fs_long(0xffff0000 | tag_word(), (unsigned long *) (d+8));
+      /* An 80486 sets all the reserved bits to 1. */
+      put_fs_long(0xffff0040 | (control_word & ~0xe080), (unsigned long *) d);
+      put_fs_long(0xffff0000 | status_word(), (unsigned long *) (d+4));
+      put_fs_long(0xffff0000 | tag_word(), (unsigned long *) (d+8));
 #else
-  put_fs_word(control_word, (unsigned short *) d);
-  put_fs_word(status_word(), (unsigned short *) (d+4));
-  put_fs_word(tag_word(), (unsigned short *) (d+8));
+      put_fs_word(control_word, (unsigned short *) d);
+      put_fs_word(status_word(), (unsigned short *) (d+4));
+      put_fs_word(tag_word(), (unsigned short *) (d+8));
 #endif PECULIAR_486
-  put_fs_long(ip_offset, (unsigned long *) (d+0x0c));
-  put_fs_long(cs_selector & ~0xf8000000, (unsigned long *) (d+0x10));
-  put_fs_long(data_operand_offset, (unsigned long *) (d+0x14));
+      put_fs_long(ip_offset, (unsigned long *) (d+0x0c));
+      put_fs_long(cs_selector & ~0xf8000000, (unsigned long *) (d+0x10));
+      put_fs_long(data_operand_offset, (unsigned long *) (d+0x14));
 #ifdef PECULIAR_486
-  /* An 80486 sets all the reserved bits to 1. */
-  put_fs_long(0xffff0000 | operand_selector, (unsigned long *) (d+0x18));
+      /* An 80486 sets all the reserved bits to 1. */
+      put_fs_long(0xffff0000 | operand_selector, (unsigned long *) (d+0x18));
 #else
-  put_fs_long(operand_selector, (unsigned long *) (d+0x18));
+      put_fs_long(operand_selector, (unsigned long *) (d+0x18));
 #endif PECULIAR_486
-  RE_ENTRANT_CHECK_ON;
+      RE_ENTRANT_CHECK_ON;
+      d += 0x1c;
+    }
   
   control_word |= CW_Exceptions;
   partial_status &= ~(SW_Summary | SW_Backward);
 
-  return d + 0x1c;
+  return d;
 }
 
 
-void fsave(void)
+void fsave(fpu_addr_modes addr_modes)
 {
   char *d;
   int i;
 
-  d = fstenv();
+  d = fstenv(addr_modes);
   RE_ENTRANT_CHECK_OFF;
   FPU_verify_area(VERIFY_WRITE,d,80);
   RE_ENTRANT_CHECK_ON;
diff --git a/drivers/FPU-emu/version.h b/drivers/FPU-emu/version.h
index d2c264d..94045f0 100644
--- a/drivers/FPU-emu/version.h
+++ b/drivers/FPU-emu/version.h
@@ -9,5 +9,5 @@
  |                                                                           |
  +---------------------------------------------------------------------------*/
 
-#define FPU_VERSION "wm-FPU-emu version Beta 1.9"
+#define FPU_VERSION "wm-FPU-emu version Beta 1.10"
 
diff --git a/drivers/net/Space.c b/drivers/net/Space.c
index 6cc4cf6..fc70286 100644
--- a/drivers/net/Space.c
+++ b/drivers/net/Space.c
@@ -139,14 +139,10 @@
 #endif
 
 /* The first device defaults to I/O base '0', which means autoprobe. */
-#ifdef EI8390
-# define ETH0_ADDR EI8390
-#else
+#ifndef ETH0_ADDR
 # define ETH0_ADDR 0
 #endif
-#ifdef EI8390_IRQ
-# define ETH0_IRQ EI8390_IRQ
-#else
+#ifndef ETH0_IRQ
 # define ETH0_IRQ 0
 #endif
 /* "eth0" defaults to autoprobe, other use a base of "-0x20", "don't probe".
diff --git a/fs/binfmt_coff.c b/fs/binfmt_coff.c
index bf57016..b65f470 100644
--- a/fs/binfmt_coff.c
+++ b/fs/binfmt_coff.c
@@ -7,43 +7,12 @@
  * This file is based upon code written by Eric Youndale for the ELF object
  * file format.
  *
- * Revision information:
- *    28 August 1993
- *       Al Longyear (longyear@sii.com)
- *       initial release to alpha level testing. This version does not load
- *       shared libraries, but will identify them and log the file names.
+ * Author: Al Longyear (longyear@sii.com)
  *
- *     4 September 1993
- *       Al Longyear (longyear@sii.com)
- *       Added support for shared libraries.
- *
- *     9 September 1993
- *       Al Longyear (longyear@sii.com)
- *       Load the FS register with the proper value prior to the call to
- *       sys_uselib().
- *
- *       Built the parameter and envionment strings before destroying the
- *       current executable.
- *
- *    10 September 1993
- *       Al Longyear (longyear@sii.com)
- *       Added new parameter to the create_tables() function to allow the
- *       proper creation of the IBCS environment stack when the process is
- *       started.
- *
- *       Added code to create_tables() which I mistakenly deleted in the
- *       last patch.
- *
- *    13 September 1993
- *       Al Longyear (longyear@sii.com)
- *       Removed erroneous code which mistakenly folded .data with .bss for
- *       a shared library. 
- *
- *     8 Janurary 1994
- *       Al Longyear (longyear@sii.com)
- *       Corrected problem with read of library section returning the byte
- *       count rather than zero. This was a change between the pl12 and
- *       pl14 kernels which slipped by me.
+ * Latest Revision:
+ *    3 Feburary 1994
+ *      Al Longyear (longyear@sii.com)
+ *      Cleared first page of bss section using put_fs_byte.
  */
 
 #include <linux/fs.h>
@@ -105,6 +74,37 @@
 }
 
 /*
+ *    Clear the bytes in the last page of data.
+ */
+
+static
+int clear_memory (unsigned long addr, unsigned long size)
+{
+    int status;
+
+    size = (PAGE_SIZE - (addr & ~PAGE_MASK)) & ~PAGE_MASK;
+    if (size == 0)
+        status = 0;
+    else {
+      
+#ifdef COFF_DEBUG
+        printk ("un-initialized storage in last page %d\n", size);
+#endif
+
+	status = verify_area (VERIFY_WRITE,
+			      (void *) addr, size);
+#ifdef COFF_DEBUG
+	printk ("result from verify_area = %d\n", status);
+#endif
+
+	if (status >= 0)
+	    while (size-- != 0)
+	        put_fs_byte (0, addr++);
+    }
+    return status;
+}
+
+/*
  *  Helper function to process the load operation.
  */
 
@@ -521,11 +521,13 @@
 	    zeromap_page_range (PAGE_ALIGN (bss_vaddr),
 				PAGE_ALIGN (bss_size),
 				PAGE_COPY);
+
+	    status = clear_memory (bss_vaddr, bss_size);
 	}
 /*
  *  Load any shared library for the executable.
  */
-	if (lib_ok && lib_count != 0) {
+	if (status >= 0 && lib_ok && lib_count != 0) {
 	    int nIndex;
 	    COFF_SCNHDR *sect_ptr = sect_bufr;
 /*
diff --git a/fs/nfs/proc.c b/fs/nfs/proc.c
index 59cb050..82f46f4 100644
--- a/fs/nfs/proc.c
+++ b/fs/nfs/proc.c
@@ -1,7 +1,7 @@
 /*
  *  linux/fs/nfs/proc.c
  *
- *  Copyright (C) 1992  Rick Sladkey
+ *  Copyright (C) 1992, 1993, 1994  Rick Sladkey
  *
  *  OS-independent nfs remote procedure call functions
  */
@@ -41,7 +41,7 @@
 
 #endif /* !NFS_PROC_DEBUG */
 
-static int *nfs_rpc_header(int *p, int procedure);
+static int *nfs_rpc_header(int *p, int procedure, int ruid);
 static int *nfs_rpc_verify(int *p);
 static int nfs_stat_to_errno(int stat);
 
@@ -192,11 +192,13 @@
 {
 	int *p, *p0;
 	int status;
+	int ruid = 0;
 
 	PRINTK("NFS call  getattr\n");
 	if (!(p0 = nfs_rpc_alloc()))
 		return -EIO;
-	p = nfs_rpc_header(p0, NFSPROC_GETATTR);
+retry:
+	p = nfs_rpc_header(p0, NFSPROC_GETATTR, ruid);
 	p = xdr_encode_fhandle(p, fhandle);
 	if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 		nfs_rpc_free(p0);
@@ -208,8 +210,13 @@
 		p = xdr_decode_fattr(p, fattr);
 		PRINTK("NFS reply getattr\n");
 	}
-	else
+	else {
+		if (!ruid && current->euid == 0 && current->uid != 0) {
+			ruid = 1;
+			goto retry;
+		}
 		PRINTK("NFS reply getattr failed = %d\n", status);
+	}
 	nfs_rpc_free(p0);
 	return -nfs_stat_to_errno(status);
 }
@@ -219,11 +226,13 @@
 {
 	int *p, *p0;
 	int status;
+	int ruid = 0;
 
 	PRINTK("NFS call  setattr\n");
 	if (!(p0 = nfs_rpc_alloc()))
 		return -EIO;
-	p = nfs_rpc_header(p0, NFSPROC_SETATTR);
+retry:
+	p = nfs_rpc_header(p0, NFSPROC_SETATTR, ruid);
 	p = xdr_encode_fhandle(p, fhandle);
 	p = xdr_encode_sattr(p, sattr);
 	if ((status = nfs_rpc_call(server, p0, p)) < 0) {
@@ -236,8 +245,13 @@
 		p = xdr_decode_fattr(p, fattr);
 		PRINTK("NFS reply setattr\n");
 	}
-	else
+	else {
+		if (!ruid && current->euid == 0 && current->uid != 0) {
+			ruid = 1;
+			goto retry;
+		}
 		PRINTK("NFS reply setattr failed = %d\n", status);
+	}
 	nfs_rpc_free(p0);
 	return -nfs_stat_to_errno(status);
 }
@@ -247,6 +261,7 @@
 {
 	int *p, *p0;
 	int status;
+	int ruid = 0;
 
 	PRINTK("NFS call  lookup %s\n", name);
 #ifdef NFS_PROC_DEBUG
@@ -255,7 +270,8 @@
 #endif
 	if (!(p0 = nfs_rpc_alloc()))
 		return -EIO;
-	p = nfs_rpc_header(p0, NFSPROC_LOOKUP);
+retry:
+	p = nfs_rpc_header(p0, NFSPROC_LOOKUP, ruid);
 	p = xdr_encode_fhandle(p, dir);
 	p = xdr_encode_string(p, name);
 	if ((status = nfs_rpc_call(server, p0, p)) < 0) {
@@ -269,8 +285,13 @@
 		p = xdr_decode_fattr(p, fattr);
 		PRINTK("NFS reply lookup\n");
 	}
-	else
+	else {
+		if (!ruid && current->euid == 0 && current->uid != 0) {
+			ruid = 1;
+			goto retry;
+		}
 		PRINTK("NFS reply lookup failed = %d\n", status);
+	}
 	nfs_rpc_free(p0);
 	return -nfs_stat_to_errno(status);
 }
@@ -280,11 +301,13 @@
 {
 	int *p, *p0;
 	int status;
+	int ruid = 0;
 
 	PRINTK("NFS call  readlink\n");
 	if (!(p0 = nfs_rpc_alloc()))
 		return -EIO;
-	p = nfs_rpc_header(p0, NFSPROC_READLINK);
+retry:
+	p = nfs_rpc_header(p0, NFSPROC_READLINK, ruid);
 	p = xdr_encode_fhandle(p, fhandle);
 	if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 		nfs_rpc_free(p0);
@@ -300,8 +323,13 @@
 		else
 			PRINTK("NFS reply readlink %s\n", res);
 	}
-	else
+	else {
+		if (!ruid && current->euid == 0 && current->uid != 0) {
+			ruid = 1;
+			goto retry;
+		}
 		PRINTK("NFS reply readlink failed = %d\n", status);
+	}
 	nfs_rpc_free(p0);
 	return -nfs_stat_to_errno(status);
 }
@@ -311,12 +339,14 @@
 {
 	int *p, *p0;
 	int status;
+	int ruid = 0;
 	int len = 0; /* = 0 is for gcc */
 
 	PRINTK("NFS call  read %d @ %d\n", count, offset);
 	if (!(p0 = nfs_rpc_alloc()))
 		return -EIO;
-	p = nfs_rpc_header(p0, NFSPROC_READ);
+retry:
+	p = nfs_rpc_header(p0, NFSPROC_READ, ruid);
 	p = xdr_encode_fhandle(p, fhandle);
 	*p++ = htonl(offset);
 	*p++ = htonl(count);
@@ -336,8 +366,13 @@
 		else
 			PRINTK("NFS reply read %d\n", len);
 	}
-	else
+	else {
+		if (!ruid && current->euid == 0 && current->uid != 0) {
+			ruid = 1;
+			goto retry;
+		}
 		PRINTK("NFS reply read failed = %d\n", status);
+	}
 	nfs_rpc_free(p0);
 	return (status == NFS_OK) ? len : -nfs_stat_to_errno(status);
 }
@@ -347,11 +382,13 @@
 {
 	int *p, *p0;
 	int status;
+	int ruid = 0;
 
 	PRINTK("NFS call  write %d @ %d\n", count, offset);
 	if (!(p0 = nfs_rpc_alloc()))
 		return -EIO;
-	p = nfs_rpc_header(p0, NFSPROC_WRITE);
+retry:
+	p = nfs_rpc_header(p0, NFSPROC_WRITE, ruid);
 	p = xdr_encode_fhandle(p, fhandle);
 	*p++ = htonl(offset); /* traditional, could be any value */
 	*p++ = htonl(offset);
@@ -367,8 +404,13 @@
 		p = xdr_decode_fattr(p, fattr);
 		PRINTK("NFS reply write\n");
 	}
-	else
+	else {
+		if (!ruid && current->euid == 0 && current->uid != 0) {
+			ruid = 1;
+			goto retry;
+		}
 		PRINTK("NFS reply write failed = %d\n", status);
+	}
 	nfs_rpc_free(p0);
 	return -nfs_stat_to_errno(status);
 }
@@ -379,11 +421,13 @@
 {
 	int *p, *p0;
 	int status;
+	int ruid = 0;
 
 	PRINTK("NFS call  create %s\n", name);
 	if (!(p0 = nfs_rpc_alloc()))
 		return -EIO;
-	p = nfs_rpc_header(p0, NFSPROC_CREATE);
+retry:
+	p = nfs_rpc_header(p0, NFSPROC_CREATE, ruid);
 	p = xdr_encode_fhandle(p, dir);
 	p = xdr_encode_string(p, name);
 	p = xdr_encode_sattr(p, sattr);
@@ -398,8 +442,13 @@
 		p = xdr_decode_fattr(p, fattr);
 		PRINTK("NFS reply create\n");
 	}
-	else
+	else {
+		if (!ruid && current->euid == 0 && current->uid != 0) {
+			ruid = 1;
+			goto retry;
+		}
 		PRINTK("NFS reply create failed = %d\n", status);
+	}
 	nfs_rpc_free(p0);
 	return -nfs_stat_to_errno(status);
 }
@@ -408,11 +457,13 @@
 {
 	int *p, *p0;
 	int status;
+	int ruid = 0;
 
 	PRINTK("NFS call  remove %s\n", name);
 	if (!(p0 = nfs_rpc_alloc()))
 		return -EIO;
-	p = nfs_rpc_header(p0, NFSPROC_REMOVE);
+retry:
+	p = nfs_rpc_header(p0, NFSPROC_REMOVE, ruid);
 	p = xdr_encode_fhandle(p, dir);
 	p = xdr_encode_string(p, name);
 	if ((status = nfs_rpc_call(server, p0, p)) < 0) {
@@ -424,8 +475,13 @@
 	else if ((status = ntohl(*p++)) == NFS_OK) {
 		PRINTK("NFS reply remove\n");
 	}
-	else
+	else {
+		if (!ruid && current->euid == 0 && current->uid != 0) {
+			ruid = 1;
+			goto retry;
+		}
 		PRINTK("NFS reply remove failed = %d\n", status);
+	}
 	nfs_rpc_free(p0);
 	return -nfs_stat_to_errno(status);
 }
@@ -436,11 +492,13 @@
 {
 	int *p, *p0;
 	int status;
+	int ruid = 0;
 
 	PRINTK("NFS call  rename %s -> %s\n", old_name, new_name);
 	if (!(p0 = nfs_rpc_alloc()))
 		return -EIO;
-	p = nfs_rpc_header(p0, NFSPROC_RENAME);
+retry:
+	p = nfs_rpc_header(p0, NFSPROC_RENAME, ruid);
 	p = xdr_encode_fhandle(p, old_dir);
 	p = xdr_encode_string(p, old_name);
 	p = xdr_encode_fhandle(p, new_dir);
@@ -454,8 +512,13 @@
 	else if ((status = ntohl(*p++)) == NFS_OK) {
 		PRINTK("NFS reply rename\n");
 	}
-	else
+	else {
+		if (!ruid && current->euid == 0 && current->uid != 0) {
+			ruid = 1;
+			goto retry;
+		}
 		PRINTK("NFS reply rename failed = %d\n", status);
+	}
 	nfs_rpc_free(p0);
 	return -nfs_stat_to_errno(status);
 }
@@ -465,11 +528,13 @@
 {
 	int *p, *p0;
 	int status;
+	int ruid = 0;
 
 	PRINTK("NFS call  link %s\n", name);
 	if (!(p0 = nfs_rpc_alloc()))
 		return -EIO;
-	p = nfs_rpc_header(p0, NFSPROC_LINK);
+retry:
+	p = nfs_rpc_header(p0, NFSPROC_LINK, ruid);
 	p = xdr_encode_fhandle(p, fhandle);
 	p = xdr_encode_fhandle(p, dir);
 	p = xdr_encode_string(p, name);
@@ -482,8 +547,13 @@
 	else if ((status = ntohl(*p++)) == NFS_OK) {
 		PRINTK("NFS reply link\n");
 	}
-	else
+	else {
+		if (!ruid && current->euid == 0 && current->uid != 0) {
+			ruid = 1;
+			goto retry;
+		}
 		PRINTK("NFS reply link failed = %d\n", status);
+	}
 	nfs_rpc_free(p0);
 	return -nfs_stat_to_errno(status);
 }
@@ -493,11 +563,13 @@
 {
 	int *p, *p0;
 	int status;
+	int ruid = 0;
 
 	PRINTK("NFS call  symlink %s -> %s\n", name, path);
 	if (!(p0 = nfs_rpc_alloc()))
 		return -EIO;
-	p = nfs_rpc_header(p0, NFSPROC_SYMLINK);
+retry:
+	p = nfs_rpc_header(p0, NFSPROC_SYMLINK, ruid);
 	p = xdr_encode_fhandle(p, dir);
 	p = xdr_encode_string(p, name);
 	p = xdr_encode_string(p, path);
@@ -511,8 +583,13 @@
 	else if ((status = ntohl(*p++)) == NFS_OK) {
 		PRINTK("NFS reply symlink\n");
 	}
-	else
+	else {
+		if (!ruid && current->euid == 0 && current->uid != 0) {
+			ruid = 1;
+			goto retry;
+		}
 		PRINTK("NFS reply symlink failed = %d\n", status);
+	}
 	nfs_rpc_free(p0);
 	return -nfs_stat_to_errno(status);
 }
@@ -523,11 +600,13 @@
 {
 	int *p, *p0;
 	int status;
+	int ruid = 0;
 
 	PRINTK("NFS call  mkdir %s\n", name);
 	if (!(p0 = nfs_rpc_alloc()))
 		return -EIO;
-	p = nfs_rpc_header(p0, NFSPROC_MKDIR);
+retry:
+	p = nfs_rpc_header(p0, NFSPROC_MKDIR, ruid);
 	p = xdr_encode_fhandle(p, dir);
 	p = xdr_encode_string(p, name);
 	p = xdr_encode_sattr(p, sattr);
@@ -542,8 +621,13 @@
 		p = xdr_decode_fattr(p, fattr);
 		PRINTK("NFS reply mkdir\n");
 	}
-	else
+	else {
+		if (!ruid && current->euid == 0 && current->uid != 0) {
+			ruid = 1;
+			goto retry;
+		}
 		PRINTK("NFS reply mkdir failed = %d\n", status);
+	}
 	nfs_rpc_free(p0);
 	return -nfs_stat_to_errno(status);
 }
@@ -552,11 +636,13 @@
 {
 	int *p, *p0;
 	int status;
+	int ruid = 0;
 
 	PRINTK("NFS call  rmdir %s\n", name);
 	if (!(p0 = nfs_rpc_alloc()))
 		return -EIO;
-	p = nfs_rpc_header(p0, NFSPROC_RMDIR);
+retry:
+	p = nfs_rpc_header(p0, NFSPROC_RMDIR, ruid);
 	p = xdr_encode_fhandle(p, dir);
 	p = xdr_encode_string(p, name);
 	if ((status = nfs_rpc_call(server, p0, p)) < 0) {
@@ -568,8 +654,13 @@
 	else if ((status = ntohl(*p++)) == NFS_OK) {
 		PRINTK("NFS reply rmdir\n");
 	}
-	else
+	else {
+		if (!ruid && current->euid == 0 && current->uid != 0) {
+			ruid = 1;
+			goto retry;
+		}
 		PRINTK("NFS reply rmdir failed = %d\n", status);
+	}
 	nfs_rpc_free(p0);
 	return -nfs_stat_to_errno(status);
 }
@@ -579,6 +670,7 @@
 {
 	int *p, *p0;
 	int status;
+	int ruid = 0;
 	int i = 0; /* = 0 is for gcc */
 	int size;
 	int eof;
@@ -587,7 +679,8 @@
 	size = server->rsize;
 	if (!(p0 = nfs_rpc_alloc()))
 		return -EIO;
-	p = nfs_rpc_header(p0, NFSPROC_READDIR);
+retry:
+	p = nfs_rpc_header(p0, NFSPROC_READDIR, ruid);
 	p = xdr_encode_fhandle(p, fhandle);
 	*p++ = htonl(cookie);
 	*p++ = htonl(size);
@@ -615,8 +708,13 @@
 			       eof ? "eof" : "");
 		}
 	}
-	else
+	else {
+		if (!ruid && current->euid == 0 && current->uid != 0) {
+			ruid = 1;
+			goto retry;
+		}
 		PRINTK("NFS reply readdir failed = %d\n", status);
+	}
 	nfs_rpc_free(p0);
 	return (status == NFS_OK) ? i : -nfs_stat_to_errno(status);
 }
@@ -626,11 +724,13 @@
 {
 	int *p, *p0;
 	int status;
+	int ruid = 0;
 
 	PRINTK("NFS call  statfs\n");
 	if (!(p0 = nfs_rpc_alloc()))
 		return -EIO;
-	p = nfs_rpc_header(p0, NFSPROC_STATFS);
+retry:
+	p = nfs_rpc_header(p0, NFSPROC_STATFS, ruid);
 	p = xdr_encode_fhandle(p, fhandle);
 	if ((status = nfs_rpc_call(server, p0, p)) < 0) {
 		nfs_rpc_free(p0);
@@ -642,8 +742,13 @@
 		p = xdr_decode_fsinfo(p, res);
 		PRINTK("NFS reply statfs\n");
 	}
-	else
+	else {
+		if (!ruid && current->euid == 0 && current->uid != 0) {
+			ruid = 1;
+			goto retry;
+		}
 		PRINTK("NFS reply statfs failed = %d\n", status);
+	}
 	nfs_rpc_free(p0);
 	return -nfs_stat_to_errno(status);
 }
@@ -652,7 +757,7 @@
  * Here are a few RPC-assist functions.
  */
 
-static int *nfs_rpc_header(int *p, int procedure)
+static int *nfs_rpc_header(int *p, int procedure, int ruid)
 {
 	int *p1, *p2;
 	int i;
@@ -673,7 +778,7 @@
 	p1 = p++;
 	*p++ = htonl(CURRENT_TIME); /* traditional, could be anything */
 	p = xdr_encode_string(p, (char *) sys);
-	*p++ = htonl(current->euid);
+	*p++ = htonl(ruid ? current->uid : current->euid);
 	*p++ = htonl(current->egid);
 	p2 = p++;
 	for (i = 0; i < 16 && i < NGROUPS && current->groups[i] != NOGROUP; i++)
diff --git a/include/linux/in_systm.h b/include/linux/in_systm.h
new file mode 100644
index 0000000..eac9a58
--- /dev/null
+++ b/include/linux/in_systm.h
@@ -0,0 +1,32 @@
+/*
+ * INET		An implementation of the TCP/IP protocol suite for the LINUX
+ *		operating system.  INET is implemented using the  BSD Socket
+ *		interface as the means of communication with the user level.
+ *
+ *		Miscellaneous internetwork definitions for kernel.
+ *
+ * Version:	@(#)in_systm.h  1.0.0   12/17/93
+ *
+ * Authors:	Original taken from Berkeley BSD UNIX 4.3-RENO.
+ *		Fred N. van Kempen, <waltje@uwalt.nl.mugnet.org>
+ *
+ *		This program is free software; you can redistribute it and/or
+ *		modify it under the terms of the GNU General Public License
+ *		as published by the Free Software Foundation; either version
+ *		2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IN_SYSTM_H
+#define _LINUX_IN_SYSTM_H
+
+/*
+ * Network types.
+ * The n_ types are network-order variants of their natural
+ * equivalents.  The Linux kernel NET-2 code does not use
+ * them (yet), but it might in the future.  This is mostly
+ * there for compatibility with BSD user-level programs.
+ */
+typedef u_short	n_short;	/* short as received from the net	*/
+typedef u_long	n_long;		/* long as received from the net	*/
+typedef u_long	n_time;		/* ms since 00:00 GMT, byte rev		*/
+
+#endif /* _LINUX_IN_SYSTM_H */
diff --git a/include/linux/mm.h b/include/linux/mm.h
index d890096..d1ae039 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -81,7 +81,7 @@
 extern int nr_secondary_pages;
 extern unsigned long secondary_page_list;
 
-#define MAX_SECONDARY_PAGES 10
+#define MAX_SECONDARY_PAGES 20
 
 /*
  * This is timing-critical - most of the time in getting a new page
diff --git a/kernel/signal.c b/kernel/signal.c
index db3df6d..dde9e11 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -183,6 +183,9 @@
 		return -EINVAL;
 	p = signum - 1 + current->sigaction;
 	if (action) {
+		int err = verify_area(VERIFY_READ, action, sizeof(*action));
+		if (err)
+			return err;
 		memcpy_fromfs(&new_sa, action, sizeof(struct sigaction));
 		if (new_sa.sa_flags & SA_NOMASK)
 			new_sa.sa_mask = 0;
@@ -194,8 +197,10 @@
 			return -EFAULT;
 	}
 	if (oldaction) {
-		if (!verify_area(VERIFY_WRITE,oldaction, sizeof(struct sigaction)))
-			memcpy_tofs(oldaction, p, sizeof(struct sigaction));
+		int err = verify_area(VERIFY_WRITE, oldaction, sizeof(*oldaction));
+		if (err)
+			return err;
+		memcpy_tofs(oldaction, p, sizeof(struct sigaction));
 	}
 	if (action) {
 		*p = new_sa;
diff --git a/net/inet/route.c b/net/inet/route.c
index 5a67bd7..f8c2a58 100644
--- a/net/inet/route.c
+++ b/net/inet/route.c
@@ -276,9 +276,12 @@
 	mask = ((struct sockaddr_in *) &r->rt_genmask)->sin_addr.s_addr;
 	gw = ((struct sockaddr_in *) &r->rt_gateway)->sin_addr.s_addr;
 
+	if (bad_mask(mask, daddr))
+		mask = 0;
+
 	if (flags & RTF_HOST)
 		mask = 0xffffffff;
-	else if (r->rt_genmask.sa_family != AF_INET)
+	else if (mask && r->rt_genmask.sa_family != AF_INET)
 		return -EAFNOSUPPORT;
 
 	if (flags & RTF_GATEWAY) {
@@ -292,9 +295,6 @@
 	if (dev == NULL)
 		return -ENETUNREACH;
 
-	if (bad_mask(mask, daddr))
-		mask = 0;
-
 	rt_add(flags, daddr, mask, gw, dev);
 	return 0;
 }