Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/ia64/ia64 Convert cpu_switchto() from assembly to C...



details:   https://anonhg.NetBSD.org/src/rev/f8e44ee37641
branches:  trunk
changeset: 822805:f8e44ee37641
user:      scole <scole%NetBSD.org@localhost>
date:      Sat Apr 08 17:38:43 2017 +0000

description:
Convert cpu_switchto() from assembly to C code.  Remove comment about
possible cpu_switchto() bug.  Actual issue appears to be new processes
using lwp0 instead of own memory, which is still not fixed.

Thanks to <chs> for figuring this out.

diffstat:

 sys/arch/ia64/ia64/context.S    |  88 +----------------------------------------
 sys/arch/ia64/ia64/vm_machdep.c |  49 +++++++++++++++++++---
 2 files changed, 43 insertions(+), 94 deletions(-)

diffs (191 lines):

diff -r 2806715fdc83 -r f8e44ee37641 sys/arch/ia64/ia64/context.S
--- a/sys/arch/ia64/ia64/context.S      Sat Apr 08 17:04:56 2017 +0000
+++ b/sys/arch/ia64/ia64/context.S      Sat Apr 08 17:38:43 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: context.S,v 1.7 2016/12/26 19:46:59 scole Exp $        */
+/*     $NetBSD: context.S,v 1.8 2017/04/08 17:38:43 scole Exp $        */
 
 /*
  * Copyright (c) 2003 Marcel Moolenaar
@@ -806,93 +806,9 @@
 END(restore_high_fp)
 
 /*
- * lwp_t *
- * cpu_switchto(lwp_t *oldlwp, lwp_t *newlwp, bool returning)
- *
- * Switch to the specified next LWP
- *   in0 is oldlwp
- *   in1 is newlwp
- */
-ENTRY(cpu_switchto, 3)
-{      .mmi
-       alloc           loc0=ar.pfs,3,2,2,0
-
-       /*
-        * Save old context, unless the LWP is exiting.
-        */
-       cmp.eq          p6,p0=r0,in0            // p6 = (in0 == 0)
-       add             r14=PC_CURLWP,r13       // r14 = &ci->ci_curlwp
-       ;;
-}
-{      .mii
-       add             r2=L_PCB,in0            // r2 = lwp_getpcb(&oldlwp)
-       add             r3=L_PCB,in1            // r3 = lwp_getpcb(&newlwp)
-       mov             loc1=rp                 // save rp (loc1 = rp)
-       ;;
-}
-{      .mmi
-       st8             [r14]=in1               // ci->ci_curlwp = newlwp
-       mov             r9=in0                  // r9 = oldlwp
-       nop             0
-       ;;
-}
-{      .mmb
-       nop             0
-       /*
-        * Switch to new context, if p6 == true.
-        * We assume to return to restorectx_return_here for swapped context.
-        */
-(p6)   ld8             out0=[r3]               // out0 = pcb of &newlwp
-(p6)   br.call.sptk.many rp=restorectx         // if (p6) restorectx(out0)
-       ;;
-}
-{      .mmb
-       /*
-        * Swap to new context.
-        */
-       ld8             out0=[r2]
-       ld8             out1=[r3]
-       br.call.sptk.many rp=swapctx
-       ;;
-}
-       /*
-        * XXX seems to be a bug here...
-        *
-        * swapctx() and restorectx() (which is called by swapctx())
-        * both adjust the bspstore (and hence bsp) registers.  When
-        * returning to "restorectx_return_here:" the bspstore can
-        * be greater than bsp, a state known as an "Incomplete Register Frame".
-        *
-        * That is not necessarily fatal in itself, but apparently the RSE
-        * engine sets bsp=bspstore to adjust, which re-syncs the stacked
-        * registers (r32-r127).  This clobbers our local registers below
-        * (loc0 and loc1) on the br return from swapctx(), and you get all
-        * kind of mysterious exceptions depeding on what gets restored from
-        * the backing store.
-        *
-        * Not sure of a proper fix is yet or how cpu_switchto should/can
-        * be interacting with restorectx()/swapctx()
-        * 
-        */
-restorectx_return_here:
-{      .mib
-       mov             r8=r9                   // r8(ret0) = oldlwp
-       mov             rp=loc1
-       nop             0
-       ;;
-}
-{      .mib
-       nop             0
-       mov             ar.pfs=loc0
-       br.ret.sptk.many rp
-       ;;
-}
-END(cpu_switchto)
-
-/*
  * lwp_trampoline()
  *
- * Arrange for a function to be invoked neatly, after a cpu_switch().
+ * Arrange for a function to be invoked neatly, after a cpu_switchto().
  *
  * Invokes fork_exit() passing in three arguments: a callout function, an
  * argument to the callout, and a trapframe pointer.  For child processes
diff -r 2806715fdc83 -r f8e44ee37641 sys/arch/ia64/ia64/vm_machdep.c
--- a/sys/arch/ia64/ia64/vm_machdep.c   Sat Apr 08 17:04:56 2017 +0000
+++ b/sys/arch/ia64/ia64/vm_machdep.c   Sat Apr 08 17:38:43 2017 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: vm_machdep.c,v 1.12 2016/08/12 02:08:20 scole Exp $    */
+/*     $NetBSD: vm_machdep.c,v 1.13 2017/04/08 17:38:43 scole Exp $    */
 
 /*
  * Copyright (c) 2006 The NetBSD Foundation, Inc.
@@ -36,6 +36,7 @@
 #include <sys/param.h>
 #include <sys/proc.h>
 #include <sys/systm.h>
+#include <sys/cpu.h>
 
 #include <machine/frame.h>
 #include <machine/md_var.h>
@@ -62,11 +63,44 @@
 }
 
 /*
+ * The cpu_switchto() function saves the context of the LWP which is
+ * currently running on the processor, and restores the context of the LWP
+ * specified by newlwp.  man cpu_switchto(9)
+ */
+lwp_t *
+cpu_switchto(lwp_t *oldlwp, lwp_t *newlwp, bool returning)
+{
+       const struct lwp *l = curlwp;
+       struct pcb *oldpcb = oldlwp ? lwp_getpcb(oldlwp) : NULL;
+       struct pcb *newpcb = lwp_getpcb(newlwp);
+       struct cpu_info *ci = curcpu();
+       register uint64_t reg9 __asm("r9");
+
+       KASSERT(newlwp != NULL);
+       
+       ci->ci_curlwp = newlwp;
+       
+       /* required for lwp_startup, copy oldlwp into r9, "mov r9=in0" */
+       __asm __volatile("mov %0=%1" : "=r"(reg9) : "r"(oldlwp));
+       
+       /* XXX handle RAS eventually */
+       
+       if (oldlwp == NULL) {
+               restorectx(newpcb);
+       } else {
+               KASSERT(oldlwp == l);
+               swapctx(oldpcb, newpcb);
+       }
+       
+       return (oldlwp);
+}
+
+/*
  * Finish a fork operation, with process p2 nearly set up.
  * Copy and update the pcb and trap frame, making the child ready to run.
  * 
  * Rig the child's kernel stack so that it will start out in
- * proc_trampoline() and call child_return() with p2 as an
+ * lwp_trampoline() and call child_return() with p2 as an
  * argument. This causes the newly-created child process to go
  * directly to user level with an apparent return value of 0 from
  * fork(), while the parent process returns normally.
@@ -84,18 +118,17 @@
     void (*func)(void *), void *arg)
 {
        struct pcb *pcb1, *pcb2;
-       struct trapframe * volatile tf;
-
+       struct trapframe *tf;
+       
        pcb1 = lwp_getpcb(l1);
        pcb2 = lwp_getpcb(l2);
 
        /* Copy pcb from lwp l1 to l2. */
        if (l1 == curlwp) {
                /* Sync the PCB before we copy it. */
-               savectx(pcb1);
-#if 0
-               /* ia64_highfp_save(???); */
-#endif
+               if (savectx(pcb1) != 0)
+                       panic("unexpected return from savectx");
+               /* ia64_highfp_save(td1); XXX */
        } else {
                KASSERT(l1 == &lwp0);
        }



Home | Main Index | Thread Index | Old Index