_M procs start up at _start/hart_entry for vcore0
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 9 Apr 2010 18:07:20 +0000 (11:07 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:41 +0000 (17:35 -0700)
The kernel will save the calling context in vcore0's notif_tf slot.
Userspace should set up its scheduler/code so that it can restart the
thread/context that was in _S mode.

Documentation/processes.txt
kern/src/process.c
kern/src/resource.c
tests/mhello.c
user/parlib/syscall.c

index fb1ab8c..47a7e90 100644 (file)
@@ -116,7 +116,8 @@ PROC_RUNNABLE_M
 PROC_RUNNING_M
 
 Difference between the _M and the _S states:
-- _S : legacy process mode
+- _S : legacy process mode.  There is no need for a second-level scheduler, and
+  the code running is analogous to a user-level thread.
 - RUNNING_M implies *guaranteed* core(s).  You can be a single core in the
   RUNNING_M state.  The guarantee is subject to time slicing, but when you
   run, you get all of your cores.
@@ -162,21 +163,30 @@ is currently done via sys_getcpuid().  The name will probably change.
 2.4.1: To go from _S to _M, a process requests cores.
 --------------
 A resource request from 0 to 1 or more causes a transition from _S to _M.  The
-calling context moves to vcore0 (proc_run() handles that) and continues from
-where it left off (the return point of the syscall).  
-
-For all other cores, and all subsequently allocated cores, they start at the
-elf entry point, with vcoreid in eax or a suitable arch-specific manner.  This
-could be replaced with a syscall that returns the vcoreid, but probably won't
-to help out sparc.
+calling context is saved in the notification slot (notif_tf) in vcore0's
+preemption data (in procdata).  The second level scheduler needs to be able to
+restart the context when vcore0 starts up.  To do this, it will need to save the
+TLS/TCB descriptor and the floating point/silly state (if applicable) in the
+user-thread control block, and do whatever is needed to signal vcore0 to run the
+_S context when it starts up.  One way would be to mark vcore0's "active thread"
+variable to point to the _S thread.  When vcore0 starts up at
+_start/hart_entry() (like all vcores), it will see a thread was running there
+and restart it.  This will need to have some special casing for the FP/silly
+state.
+
+In general, all cores (and all subsequently allocated cores) start at the elf
+entry point, with vcoreid in eax or a suitable arch-specific manner.  There is
+also a syscall to get the vcoreid, but this will save an extra trap at vcore
+start time.
 
 Future proc_runs(), like from RUNNABLE_M to RUNNING_M start all cores at the
-entry point, including vcore0.  The magic of moving contexts only happens on
+entry point, including vcore0.  The saving of a _S context to vcore0's notif_tf only happens on
 the transition from _S to _M (which the process needs to be aware of for a
 variety of reasons).  This also means that userspace needs to handle vcore0
-coming up at the entry point again (and not starting the program over).  I
-recommend setting a global variable that can be checked from assembly before
-going to _M the first time.
+coming up at the entry point again (and not starting the program over).  This is
+currently done in sysdeps-ros/start.c, via the static variable init.  Note there
+are some tricky things involving dynamically linked programs, but it all works
+currently.
 
 When coming in to the entry point, whether as the result of a startcore or a
 notification, the kernel will set the stack pointer to whatever is requested
@@ -198,7 +208,8 @@ be dealt with.
 When the caller next switches to _M, that context (including its stack)
 maintains its old vcore identity.  If vcore3 causes the switch to _S mode, it
 ought to remain vcore3 (lots of things get broken otherwise).
-As of March 2010, the code does not reflect this
+As of March 2010, the code does not reflect this.  Don't rely on anything in
+this section for the time being.
 
 2.4.3: Requesting more cores while in _M
 --------------
index f64c10d..a8be5c6 100644 (file)
@@ -417,15 +417,9 @@ void proc_run(struct proc *p)
                                if (is_mapped_vcore(p, core_id()))
                                        self_ipi_pending = TRUE;
                                // TODO: handle silly state (HSS)
-                               // set virtual core 0 to run the main context on transition
-                               if (p->env_flags & PROC_TRANSITION_TO_M) {
-                                       p->env_flags &= !PROC_TRANSITION_TO_M;
-                                       p->procinfo->vcoremap[0].tf_to_run = &p->env_tf;
-                               } else {
-                                       assert(!p->procinfo->vcoremap[0].tf_to_run);
-                               }
                                /* others should be zeroed after a previous use too. */
-                               for (int i = 1; i < p->procinfo->num_vcores; i++)
+                               // TODO: remove me
+                               for (int i = 0; i < p->procinfo->num_vcores; i++)
                                        assert(!p->procinfo->vcoremap[i].tf_to_run);
                                for (int i = 0; i < p->procinfo->num_vcores; i++)
                                        send_kernel_message(p->procinfo->vcoremap[i].pcoreid,
index 46be3df..fa0c474 100644 (file)
@@ -100,13 +100,9 @@ ssize_t core_request(struct proc *p)
                                // TODO: relies on vcore0 being the caller (VC#)
                                if ((current != p) || (p->procinfo->vcoremap[0].pcoreid != core_id()))
                                        panic("We don't handle async RUNNING_S core requests yet.");
-                               /* save the tf to be restarted on another core (in proc_run) */
-                               p->env_tf = *current_tf;
-                               env_push_ancillary_state(p);
-                               /* set the return code to 0. since we're transitioning, vcore0
-                                * will start up with the tf manually, and not get the return
-                                * value through the regular syscall return path */
-                               proc_set_syscall_retval(&p->env_tf, ESUCCESS);
+                               /* save the tf so userspace can restart it.  Like in __notify,
+                                * this assumes a user tf is the same as a kernel tf. */
+                               p->procdata->vcore_preempt_data[0].notif_tf = *current_tf;
                                /* in the async case, we'll need to remotely stop and bundle
                                 * vcore0's TF.  this is already done for the sync case (local
                                 * syscall). */
@@ -121,8 +117,6 @@ ssize_t core_request(struct proc *p)
                                need_to_idle = TRUE;
                                // change to runnable_m (it's TF is already saved)
                                __proc_set_state(p, PROC_RUNNABLE_M);
-                               // signals to proc_run that this is a _S to _M transition
-                               p->env_flags |= PROC_TRANSITION_TO_M;
                                break;
                        case (PROC_RUNNABLE_S):
                                /* Issues: being on the runnable_list, proc_set_state not liking
index 6f52de6..d91eff2 100644 (file)
@@ -37,6 +37,8 @@ int main(int argc, char** argv)
        /* Need to save this somewhere that you can find it again when restarting
         * core0 */
        core0_tls = get_tls_desc(0);
+       /* Need to save our floating point state somewhere (like in the
+        * user_thread_tcb so it can be restarted too */
 
        /* don't forget to enable notifs on vcore0 at some point */
        struct preempt_data *vcpd;
@@ -55,7 +57,8 @@ int main(int argc, char** argv)
                //retval = sys_resource_req(RES_CORES, 2, 0);
                //retval = hart_request(hart_max_harts()-2);
                retval = hart_request(2); // doesn't do what you think.  this gives 3.
-               //debug("retval = %d\n", retval);
+               //printf("retval = %d\n", retval);
+               printf("This is vcore0, right after hart_request\n");
        }
 
 #if 0
@@ -116,6 +119,7 @@ void hart_entry(void)
        if (vcoreid == 0) {
                printf("restarting vcore0 from userspace\n");
                set_tls_desc(core0_tls, 0);
+               /* Load silly state (Floating point) too */
                pop_ros_tf(&vcpd->notif_tf, &vcpd->notif_enabled);
                panic("should never see me!");
        }       
index ecc7bed..af9d8a1 100644 (file)
@@ -91,7 +91,11 @@ ssize_t sys_eth_read(void* buf, size_t len)
 /* Request resources from the kernel.  Flags in ros/resource.h. */
 ssize_t sys_resource_req(int type, size_t amt_max, size_t amt_min, uint32_t flags)
 {
+#ifdef __i386__
+       return syscall_trap(SYS_resource_req, type, amt_max, amt_min, flags, 0);
+#else
        return ros_syscall(SYS_resource_req, type, amt_max, amt_min, flags, 0);
+#endif
 }
 
 void sys_reboot()