This commit was manufactured by cvs2svn to create tag 'FreeBSD-release/1.0'.
[unix-history] / sys / i386 / i386 / trap.c
index 57195f3..989a732 100644 (file)
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  *
- *     @(#)trap.c      7.4 (Berkeley) 5/13/91
- *
- * PATCHES MAGIC                LEVEL   PATCH THAT GOT US HERE
- * --------------------         -----   ----------------------
- * CURRENT PATCH LEVEL:         1       00137
- * --------------------         -----   ----------------------
- *
- * 08 Apr 93   Bruce Evans             Several VM system fixes
- *             Paul Kranenburg         Add counter for vmstat
+ *     from: @(#)trap.c        7.4 (Berkeley) 5/13/91
+ *     $Id$
  */
  */
-static char rcsid[] = "$Header: /usr/bill/working/sys/i386/i386/RCS/trap.c,v 1.2 92/01/21 14:22:13 william Exp $";
 
 /*
  * 386 Trap and System call handleing
  */
 
 
 /*
  * 386 Trap and System call handleing
  */
 
+#include "npx.h"
 #include "machine/cpu.h"
 #include "machine/psl.h"
 #include "machine/reg.h"
 #include "machine/cpu.h"
 #include "machine/psl.h"
 #include "machine/reg.h"
@@ -70,6 +63,21 @@ static char rcsid[] = "$Header: /usr/bill/working/sys/i386/i386/RCS/trap.c,v 1.2
 
 #include "machine/trap.h"
 
 
 #include "machine/trap.h"
 
+#ifdef __GNUC__
+
+/*
+ * The "r" contraint could be "rm" except for fatal bugs in gas.  As usual,
+ * we omit the size from the mov instruction to avoid nonfatal bugs in gas.
+ */
+#define        read_gs()       ({ u_short gs; __asm("mov %%gs,%0" : "=r" (gs)); gs; })
+#define        write_gs(gs)    __asm("mov %0,%%gs" : : "r" ((u_short) gs))
+
+#else  /* not __GNUC__ */
+
+u_short        read_gs         __P((void));
+void   write_gs        __P((/* promoted u_short */ int gs));
+
+#endif /* __GNUC__ */
 
 struct sysent sysent[];
 int    nsysent;
 
 struct sysent sysent[];
 int    nsysent;
@@ -112,9 +120,25 @@ trap(frame)
                        frame.tf_trapno, frame.tf_err, frame.tf_eip,
                        frame.tf_cs, rcr2(), frame.tf_esp);*/
 if(curpcb == 0 || curproc == 0) goto we_re_toast;
                        frame.tf_trapno, frame.tf_err, frame.tf_eip,
                        frame.tf_cs, rcr2(), frame.tf_esp);*/
 if(curpcb == 0 || curproc == 0) goto we_re_toast;
-       if (curpcb->pcb_onfault && frame.tf_trapno != 0xc) {
+       if (curpcb->pcb_onfault && frame.tf_trapno != T_PAGEFLT) {
+               extern int _udatasel;
+
+               if (read_gs() != (u_short) _udatasel)
+                       /*
+                        * Some user has corrupted %gs but we depend on it in
+                        * copyout() etc.  Fix it up and retry.
+                        *
+                        * (We don't preserve %fs or %gs, so users can change
+                        * them to either _ucodesel, _udatasel or a not-present
+                        * selector, possibly ORed with 0 to 3, making them
+                        * volatile for other users.  Not preserving them saves
+                        * time and doesn't lose functionality or open security
+                        * holes.)
+                        */
+                       write_gs(_udatasel);
+               else
 copyfault:
 copyfault:
-               frame.tf_eip = (int)curpcb->pcb_onfault;
+                       frame.tf_eip = (int)curpcb->pcb_onfault;
                return;
        }
 
                return;
        }
 
@@ -175,12 +199,16 @@ copyfault:
                goto out;
 
        case T_DNA|T_USER:
                goto out;
 
        case T_DNA|T_USER:
-#ifdef NPX
+#if NNPX > 0
                /* if a transparent fault (due to context switch "late") */
                if (npxdna()) return;
                /* if a transparent fault (due to context switch "late") */
                if (npxdna()) return;
-#endif
+#endif /* NNPX > 0 */
+#ifdef MATH_EMULATE
                i = math_emulate(&frame);
                if (i == 0) return;
                i = math_emulate(&frame);
                if (i == 0) return;
+#else  /* MATH_EMULTATE */
+               panic("trap: math emulation necessary!");
+#endif /* MATH_EMULTATE */
                ucode = FPE_FPU_NP_TRAP;
                break;
 
                ucode = FPE_FPU_NP_TRAP;
                break;
 
@@ -222,27 +250,6 @@ copyfault:
                unsigned nss,v;
 
                va = trunc_page((vm_offset_t)eva);
                unsigned nss,v;
 
                va = trunc_page((vm_offset_t)eva);
-               /*
-                * Avoid even looking at pde_v(va) for high va's.   va's
-                * above VM_MAX_KERNEL_ADDRESS don't correspond to normal
-                * PDE's (half of them correspond to APDEpde and half to
-                * an unmapped kernel PDE).  va's betweeen 0xFEC00000 and
-                * VM_MAX_KERNEL_ADDRESS correspond to unmapped kernel PDE's
-                * (XXX - why are only 3 initialized when 6 are required to
-                * reach VM_MAX_KERNEL_ADDRESS?).  Faulting in an unmapped
-                * kernel page table would give inconsistent PTD's.
-                *
-                * XXX - faulting in unmapped page tables wastes a page if
-                * va turns out to be invalid.
-                *
-                * XXX - should "kernel address space" cover the kernel page
-                * tables?  Might have same problem with PDEpde as with
-                * APDEpde (or there may be no problem with APDEpde).
-                */
-               if (va > 0xFEBFF000) {
-                       rv = KERN_FAILURE;      /* becomes SIGBUS */
-                       goto nogo;
-               }
                /*
                 * It is only a kernel address space fault iff:
                 *      1. (type & T_USER) == 0  and
                /*
                 * It is only a kernel address space fault iff:
                 *      1. (type & T_USER) == 0  and
@@ -396,18 +403,49 @@ out:
 }
 
 /*
 }
 
 /*
- * Compensate for 386 brain damage (missing URKR)
+ * Compensate for 386 brain damage (missing URKR).
+ * This is a little simpler than the pagefault handler in trap() because
+ * it the page tables have already been faulted in and high addresses
+ * are thrown out early for other reasons.
  */
  */
-int trapwrite(unsigned addr) {
-       int rv;
+int trapwrite(addr)
+       unsigned addr;
+{
+       unsigned nss;
+       struct proc *p;
        vm_offset_t va;
        vm_offset_t va;
+       struct vmspace *vm;
 
        va = trunc_page((vm_offset_t)addr);
 
        va = trunc_page((vm_offset_t)addr);
-       if (va > VM_MAXUSER_ADDRESS) return(1);
-       rv = vm_fault(&curproc->p_vmspace->vm_map, va,
-               VM_PROT_READ | VM_PROT_WRITE, FALSE);
-       if (rv == KERN_SUCCESS) return(0);
-       else return(1);
+       /*
+        * XXX - MAX is END.  Changed > to >= for temp. fix.
+        */
+       if (va >= VM_MAXUSER_ADDRESS)
+               return (1);
+       /*
+        * XXX: rude stack hack adapted from trap().
+        */
+       nss = 0;
+       p = curproc;
+       vm = p->p_vmspace;
+       if ((caddr_t)va >= vm->vm_maxsaddr && dostacklimits) {
+               nss = clrnd(btoc((unsigned)vm->vm_maxsaddr + MAXSSIZ
+                                - (unsigned)va));
+               if (nss > btoc(p->p_rlimit[RLIMIT_STACK].rlim_cur))
+                       return (1);
+       }
+
+       if (vm_fault(&vm->vm_map, va, VM_PROT_READ | VM_PROT_WRITE, FALSE)
+           != KERN_SUCCESS)
+               return (1);
+
+       /*
+        * XXX: continuation of rude stack hack
+        */
+       if (nss > vm->vm_ssize)
+               vm->vm_ssize = nss;
+
+       return (0);
 }
 
 /*
 }
 
 /*