Kernel uses user_contexts, instead of TFs
authorBarret Rhoden <brho@cs.berkeley.edu>
Fri, 12 Apr 2013 23:50:33 +0000 (16:50 -0700)
committerBarret Rhoden <brho@cs.berkeley.edu>
Sat, 13 Apr 2013 00:10:47 +0000 (17:10 -0700)
Pcpui changed to use user_contexts.  Changes set_current_tf to ctx
variants.  Proc and other arch-independent code are all converted.

The kernel headers (and therefore userspace) still use TFs, and
arch-dependent code (like init_tf and pop_tf) still use TFs.

18 files changed:
Documentation/kernel_messages.txt
Documentation/kthreads.txt
Documentation/process-internals.txt
Documentation/processes.txt
kern/arch/i686/trap.c
kern/arch/riscv/env.c
kern/arch/riscv/trap.c
kern/arch/sparc/cpuinfo.c
kern/arch/sparc/env.c
kern/arch/sparc/trap.c
kern/include/env.h
kern/include/process.h
kern/include/smp.h
kern/src/elf.c
kern/src/kthread.c
kern/src/process.c
kern/src/schedule.c
kern/src/syscall.c

index df96c54..21e6c9a 100644 (file)
@@ -34,8 +34,8 @@ work could affect currently executing kernel code (like a syscall).
 For example, some older KMSGs such as __startcore used to not return and would
 pop directly into user space.  This complicted the KMSG code quite a bit.  While
 these functions now return, they still can't be immediate messages.  Proc
-management KMSGs change the cur_tf out from under a syscall, which can lead to a
-bunch of issues.
+management KMSGs change the cur_ctx out from under a syscall, which can lead to
+bunch of issues.
 
 Immediate kernel messages are executed in interrupt context, with interrupts
 disabled.  Routine messages are only executed from places in the code where the
@@ -63,7 +63,7 @@ History:
 --------------------------------
 KMSGs have a long history tied to process management code.  The main issues were
 related to which KMSG functions return and which ones mess with local state (like
-clobbering cur_tf or the owning_proc).  Returning was a big deal because you
+clobbering cur_ctx or the owning_proc).  Returning was a big deal because you
 can't just arbitrarily abandon a kernel context (locks or refcnts could be held,
 etc).  This is why immediates must return.  Likewise, there are certain
 invariants about what a core is doing that shouldn't be changed by an IRQ
index a79a318..d108d40 100644 (file)
@@ -248,7 +248,7 @@ recall).  If it was a _M, things are a bit more complicated, since this should
 only happen if the kthread is for that process (and probably a bunch of other
 things - like they said it was okay to interrupt their vcore to finish the
 syscall).  Note - this might not be accurate anymore (see discussions on
-current_tf).
+current_ctx).
 
 To a certain extent, routine kmsgs don't seem like a nice fit, when we really
 want to be calling schedule().  Though if you think of it as the enactment of a
@@ -258,7 +258,7 @@ when it decided to send the kernel msg.  In the future, we could split this into
 having the handler make the kthread active, and have the scheduler called to
 decide where and when to run the kthread.
 
-Current_tf, Returning Twice, and Blocking
+Current_ctx, Returning Twice, and Blocking
 --------------------------------
 One of the reasons for decoupling kthreads from a vcore or the notion of a
 kernel thread per user processs/task is so that when the kernel blocks (on a
@@ -272,41 +272,41 @@ asynchronous kernel/syscall interface (though it's not limited to syscalls
   go through acrobatics in the code to prevent this.
 
 There are a couple of approaches I considered, and it involves the nature of
-"current_tf", and a brutal bug.  Current_tf is a pointer to the trapframe of the
-process that was interrupted/trapped, and is what user context ought to be
-running on this core if we return.  Current_tf is 'made' when the kernel saves
-the context at the top of the interrupt stack (aka 'stacktop').  Then the
-kernel's call path proceeds down the same stack.  This call path may get blocked
-in a kthread.  When we block, we want to restart the current_tf.  There is a
-coupling between the kthread's stack and the storage of current_tf (contents,
-not the pointer (which is in pcpui)).
+"current_ctx", and a brutal bug.  Current_ctx (formerly current_ctx) is a
+pointer to the trapframe of the process that was interrupted/trapped, and is
+what user context ought to be running on this core if we return.  Current_ctx is
+'made' when the kernel saves the context at the top of the interrupt stack (aka
+'stacktop').  Then the kernel's call path proceeds down the same stack.  This
+call path may get blocked in a kthread.  When we block, we want to restart the
+current_ctx.  There is a coupling between the kthread's stack and the storage of
+current_ctx (contents, not the pointer (which is in pcpui)).
 
 This coupling presents a problem when we are in userspace and get interrupted,
-and that interrupt wants to restart a kthread.  In this case, current_tf points
+and that interrupt wants to restart a kthread.  In this case, current_ctx points
 to the interrupt stack, but then we want to switch to the kthread's stack.  This
 is okay.  When that kthread wants to block again, it needs to switch back to
 another stack.  Up until this commit, it was jumping to the top of the old stack
-it was on, clobbering current_tf (took about 8-10 hours to figure this out).
-While we could just make sure to save space for current_tf, it doesn't solve the
-problem: namely that the current_tf concept is not bound to a specific kernel
-stack (kthread or otherwise).  We could have cases where more than one kthread
-starts up on a core and we end up freeing the page that holds current_tf (since
-it is a stack we no longer need).  We don't want to bother keeping stacks around
-just to hold the current_tf.  Part of the nature of this weird coupling is that
-a given kthread might or might not have the current_tf at the top of its stack.
-What a pain in the ass...
-
-The right answer is to decouple current_tf from kthread stacks.  There are two
-ways to do this.  In both ways, current_tf retains its role of the context the
+it was on, clobbering current_ctx (took about 8-10 hours to figure this out).
+While we could just make sure to save space for current_ctx, it doesn't solve
+the problem: namely that the current_ctx concept is not bound to a specific
+kernel stack (kthread or otherwise).  We could have cases where more than one
+kthread starts up on a core and we end up freeing the page that holds
+current_ctx (since it is a stack we no longer need).  We don't want to bother
+keeping stacks around just to hold the current_ctx.  Part of the nature of this
+weird coupling is that a given kthread might or might not have the current_ctx
+at the top of its stack.  What a pain in the ass...
+
+The right answer is to decouple current_ctx from kthread stacks.  There are two
+ways to do this.  In both ways, current_ctx retains its role of the context the
 kernel restarts (or saves) when it goes back to a process, and is independent of
 blocking kthreads.  SPOILER: solution 1 is not the one I picked
 
 1) All traps/interrupts come in on one stack per core.  That stack never changes
-(regardless of blocking), and current_tf is stored at the top.  Kthreads sort of
-'dispatch' / turn into threads from this event-like handling code.  This
+(regardless of blocking), and current_ctx is stored at the top.  Kthreads sort
+of 'dispatch' / turn into threads from this event-like handling code.  This
 actually sounds really cool!
 
-2) The contents of current_tf get stored in per-cpu-info (pcpui), thereby
+2) The contents of current_ctx get stored in per-cpu-info (pcpui), thereby
 clearly decoupling it from any execution context.  Any thread of execution can
 block without any special treatment (though interrupt handlers shouldn't do
 this).  We handle the "returning twice" problem at the point of return.
@@ -337,7 +337,7 @@ It is doable with syscalls because we have that clearly defined point
 fault handler?  It could block, and lots of other handlers could block too.  All
 of those would need to have a jump point (in trap.c).  We aren't even handling
 events anymore, we are immediately jumping to other stacks, using our "event
-handler" to hold current_tf and handle how we return to current_tf.  Don't
+handler" to hold current_ctx and handle how we return to current_ctx.  Don't
 forget about other code (like the boot code) that wants to block.  Simply put,
 option 1 creates a layer that is a pain to work with, cuts down on the
 flexibility of the kernel to block when it wants, and doesn't handle the issue
@@ -350,7 +350,7 @@ returns.  Now imagine a syscall that blocks.  Most of these calls are going to
 block on occasion, but not always (imagine the read was filled from the page
 cache).  These calls really need to handle both situations.  So in one instance,
 the call blocks.  Since we're async, we return to userspace early (pop the
-current_tf).  Now, when that kthread unblocks, its code is going to want to
+current_ctx).  Now, when that kthread unblocks, its code is going to want to
 finish and unroll its stack, then pop back to userspace.  This is the 'returning
 twice' problem.  Note that a *kthread* never returns twice.  This is what makes
 the idea of magic jumping points we can't return back across (and tying that to
@@ -359,23 +359,23 @@ how we block in the kernel) painful.
 The way I initially dealt with this was by always calling smp_idle(), and having
 smp_idle decide what to do.  I also used it as a place to dispatch batched
 syscalls, which is what made smp_idle() more attractive.  However, after a bit,
-I realized the real nature of returning twice: current_tf.  If we forget about
+I realized the real nature of returning twice: current_ctx.  If we forget about
 the batching for a second, all we really need to do is not return twice.  The
 best place to do that is at the place where we consider returning to userspace:
 proc_restartcore().  Instead of calling smp_idle() all the time (which was in
-essence a "you can now block" point), and checking for current_tf to return,
+essence a "you can now block" point), and checking for current_ctx to return,
 just check in restartcore to see if there is a tf to restart.  If there isn't,
 then we smp_idle().  And don't forget to handle the cases where we want to start
-and env_tf (which we ought to point current_tf to in proc_run()).
+and scp_ctx (which we ought to point current_ctx to in proc_run()).
 
 As a side note, we ought to use kmsgs for batched syscalls - it will help with
 preemption latencies.  At least for all but the first syscall (which can be
-called directly).  Instead of sending a retval via current_tf about how many
+called directly).  Instead of sending a retval via current_ctx about how many
 started, just put that info in the syscall struct's flags (which might help the
 remote syscall case - no need for a response message, though there are still a
 few differences (no failure model other than death)).
 
 Note that page faults will still be tricky, but at least now we don't have to
-worry about points of no return.  We just check if there is a current_tf to
+worry about points of no return.  We just check if there is a current_ctx to
 restart.  The tricky part is communicating that the PF was sorted when there
 wasn't an explicit syscall made.
index 7f06ba6..05f601e 100644 (file)
@@ -11,7 +11,7 @@ Contents:
 2. When Do We Really Leave "Process Context"?
 3. Leaving the Kernel Stack
 4. Preemption and Notification Issues
-5. current_tf and owning_proc
+5. current_ctx and owning_proc
 6. Locking!
 7. TLB Coherency
 8. Process Management
@@ -116,7 +116,7 @@ Refcnting and especially decreffing gets tricky when there are functions that
 MAY not return.  proc_restartcore() does not return (it pops into userspace).
 proc_run() used to not return, if the core it was called on would pop into
 userspace (if it was a _S, or if the core is part of the vcoremap for a _M).
-This doesn't happen anymore, since we have cur_tf in the per-cpu info.
+This doesn't happen anymore, since we have cur_ctx in the per-cpu info.
 
 Functions that MAY not return will "eat" your reference *IF* they do not return.
 This means that you must have a reference when you call them (like always), and
@@ -265,7 +265,7 @@ it to proc B.
 If no process is running there, current == 0 and boot_cr3 is loaded, meaning no
 process's context is loaded.
 
-All changes to cur_proc, owning_proc, and cur_tf need to be done with
+All changes to cur_proc, owning_proc, and cur_ctx need to be done with
 interrupts disabled, since they change in interrupt handlers.
 
 2.2 Here's how it is done now:
@@ -709,51 +709,55 @@ actually non-trivial to know the state of a vcore (need to check a combination
 of preempt_served and is_mapped), and even if you do that, there are some
 complications with doing this in the ksched.
 
-5. current_tf and owning_proc
+5. current_ctx and owning_proc
 ===========================
-Originally, current_tf is a per-core macro that returns a struct trapframe *
+Originally, current_tf was a per-core macro that returns a struct trapframe *
 that points back on the kernel stack to the user context that was running on
 the given core when an interrupt or trap happened.  Saving the reference to
 the TF helps simplify code that needs to do something with the TF (like save
 it and pop another TF).  This way, we don't need to pass the context all over
 the place, especially through code that might not care.
 
-Now, current_tf is more broadly defined as the user context that should be run
-when the kernel is ready to run a process.  In the older case, it was when the
-kernel tries to return to userspace from a trap/interrupt.  Now, current_tf
-can be set by an IPI/KMSG (like '__startcore') so that when the kernel wants
-to idle, it will find a cur_tf that it needs to run, even though we never
+Then, current_tf was more broadly defined as the user context that should be
+run when the kernel is ready to run a process.  In the older case, it was when
+the kernel tries to return to userspace from a trap/interrupt.  current_tf
+could be set by an IPI/KMSG (like '__startcore') so that when the kernel wants
+to idle, it will find a current_tf that it needs to run, even though we never
 trapped in on that context in the first place.
 
+Finally, current_tf was changed to current_ctx, and instead of tracking a
+struct trapframe (equivalent to a hw_trapframe), it now tracked a struct
+user_context, which could be either a HW or a SW trapframe.
+
 Further, we now have 'owning_proc', which tells the kernel which process
-should be run.  'owning_proc' is a bigger deal than 'current_tf', and it is
-what tells us to run cur_tf.
+should be run.  'owning_proc' is a bigger deal than 'current_ctx', and it is
+what tells us to run cur_ctx.
 
-Process management KMSGs now simply modify 'owning_proc' and cur_tf, as if we
+Process management KMSGs now simply modify 'owning_proc' and cur_ctx, as if we
 had interrupted a process.  Instead of '__startcore' forcing the kernel to
 actually run the process and trapframe, it will just mean we will eventually
 run it.  In the meantime a '__notify' or a '__preempt' can come in, and they
-will apply to the owning_proc/cur_tf.  This greatly simplifies process code
+will apply to the owning_proc/cur_ctx.  This greatly simplifies process code
 and code calling process code (like the scheduler), since we no longer need to
 worry about whether or not we are getting a "stack killing" kernel message.
 Before this, code needed to care where it was running when managing _Ms.
 
-Note that neither 'current_tf' nor 'owning_proc' rely on 'current'/'cur_proc'.
+Note that neither 'current_ctx' nor 'owning_proc' rely on 'current'/'cur_proc'.
 'current' is just what process context we're in, not what process (and which
 trapframe) we will eventually run.
 
-cur_tf does not point to kernel trapframes, which is important when we receive an
-interrupt in the kernel.  At one point, we were (hypothetically) clobbering the
-reference to the user trapframe, and were unable to recover.  We can get away
-with this because the kernel always returns to its previous context from a
-nested handler (via iret on x86).  
+cur_ctx does not point to kernel trapframes, which is important when we
+receive an interrupt in the kernel.  At one point, we were (hypothetically)
+clobbering the reference to the user trapframe, and were unable to recover.
+We can get away with this because the kernel always returns to its previous
+context from a nested handler (via iret on x86).  
 
-In the future, we may need to save kernel contexts and may not always return via
-iret.  At which point, if the code path is deep enough that we don't want to
-carry the TF pointer, we may revisit this.  Until then, current_tf is just for
-userspace contexts, and is simply stored in per_cpu_info.
+In the future, we may need to save kernel contexts and may not always return
+via iret.  At which point, if the code path is deep enough that we don't want
+to carry the TF pointer, we may revisit this.  Until then, current_ctx is just
+for userspace contexts, and is simply stored in per_cpu_info.
 
-Brief note from the future (months after this paragraph was written): cur_tf
+Brief note from the future (months after this paragraph was written): cur_ctx
 has two aspects/jobs:
 1) tell the kernel what we should do (trap, fault, sysc, etc), how we came
 into the kernel (the fact that it is a user tf), which is why we copy-out
@@ -765,12 +769,12 @@ removed when preempted, changed during a notify, created during a startcore,
 etc.  Don't forget it was also an instruction of sorts.  The former case is
 always true throughout the life of the syscall.  The latter only happens to be
 true throughout the life of a *non-blocking* trap since preempts are routine
-KMSGs.  But if we block in a syscall, the cur_tf is no longer the TF we came
-in on (and possibly the one we are asked to operate on), and that old cur_tf
+KMSGs.  But if we block in a syscall, the cur_ctx is no longer the TF we came
+in on (and possibly the one we are asked to operate on), and that old cur_ctx
 has probably restarted.
 
-(Note that cur_tf is a pointer, and syscalls/traps actually operate on the TF
-they came in on regardless of what happens to cur_tf or pcpui->actual_tf.)
+(Note that cur_ctx is a pointer, and syscalls/traps actually operate on the TF
+they came in on regardless of what happens to cur_ctx or pcpui->actual_tf.)
 
 6. Locking!
 ===========================
@@ -1120,7 +1124,7 @@ waiting on us to handle the preempt (same circular waiting issue as above).
 This was fine, albeit subpar, until a new issue showed up.  Sending IMMED
 KMSGs worked fine if we were coming from userspace already, but if we were in
 the kernel, those messages would run immediately (hence the name), just like
-an IRQ handler, and could confuse syscalls that touched cur_tf/pcpui.  If a
+an IRQ handler, and could confuse syscalls that touched cur_ctx/pcpui.  If a
 preempt came in during a syscall, the process/vcore could be changed before
 the syscall took place.  Some syscalls could handle this, albeit poorly.
 sys_proc_yield() and sys_change_vcore() delicately tried to detect if they
@@ -1140,11 +1144,11 @@ unmapped vcoreid).  There are a bunch of other scenarios that trigger similar
 disasters, and they are very hard to avoid.
 
 One way out of this was a per-core history counter, that changed whenever we
-changed cur_tf.  Then when we trapped in for a syscall, we could save the
+changed cur_ctx.  Then when we trapped in for a syscall, we could save the
 value, enable_irqs(), and go about our business.  Later on, we'd have to
 disable_irqs() and compare the counters.  If they were different, we'd have to
 bail out some how.  This could have worked for change_to and yield, and some
-others.  But any syscall that wanted to operate on cur_tf in some way would
+others.  But any syscall that wanted to operate on cur_ctx in some way would
 fail (imagine a hypothetical sys_change_stack_pointer()).  The context that
 trapped has already returned on another core.  I guess we could just fail that
 syscall, though it seems a little silly to not be able to do that.
@@ -1163,7 +1167,7 @@ interrupts / kthread during a page fault (imaging hitting disk).  Yikes.
 So I looked into going back to ROUTINE kernel messages.  With ROUTINE
 messages, I didn't have to worry about having the carpet pulled out from under
 syscalls and exceptions (traps, faults, etc).  The 'carpet' is stuff like
-cur_tf, owning_proc, owning_vcoreid, etc.  We still cannot trust the vcoremap,
+cur_ctx, owning_proc, owning_vcoreid, etc.  We still cannot trust the vcoremap,
 unless we *know* there were no preempts or other KMSGs waiting for us.
 (Incidentally, in the recent fix a93aa7559, we merely use the vcoremap as a
 sanity check).
@@ -1244,7 +1248,7 @@ just being a bool.
 
 Regardless of whether or not we were preempted, we still can look at
 pcpui->owning_proc and owning_vcoreid to figure out what the vcoreid of the
-trap/syscall is, and we know that the cur_tf is still the correct cur_tf (no
+trap/syscall is, and we know that the cur_ctx is still the correct cur_ctx (no
 carpet pulled out), since while there could be a preempt ROUTINE message
 waiting for us, we simply haven't run it yet.  So calls like yield should
 still fail (since your core has been unmapped and you need to bail out and run
@@ -1378,11 +1382,11 @@ Here's some good ideas for the ordering of locks/irqs/messages:
 If for some reason a syscall or fault handler blocks *unexpectedly*, we could
 have issues.  Imagine if change_to happens to block in some early syscall code
 (like instrumentation, or who knows what, that blocks in memory allocation).
-When the syscall kthread restarts, its old cur_tf is gone.  It may or may not
+When the syscall kthread restarts, its old cur_ctx is gone.  It may or may not
 be running on a core owned by the original process.  If it was, we probably
 would accidentally yield that vcore (clearly a bug).  
 
-For now, any of these calls that care about cur_tf/pcpui need to not block
+For now, any of these calls that care about cur_ctx/pcpui need to not block
 without some sort of protection.  None of them do, but in the future we might
 do something that causes them to block.  We could deal with it by having a
 pcpu or per-kthread/syscall flag that says if it ever blocked, and possibly
@@ -1390,7 +1394,7 @@ abort.  We get into similar nasty areas as with preempts, but this time, we
 can't solve it by making preempt a routine KMSG - we block as part of that
 syscall/handler code.  Odds are, we'll just have to outlaw this, now and
 forever.  Just note that if a syscall/handler blocks, the TF it came in on is
-probably not cur_tf any longer, and that old cur_tf has probably restarted.
+probably not cur_ctx any longer, and that old cur_ctx has probably restarted.
 
 10. TBD
 ===========================
index 8cc44c3..53c7f11 100644 (file)
@@ -228,7 +228,7 @@ not wanting the core anymore.  The other is in response to a preemption.  Yield
 may not be called remotely (ARSC).
 
 In _S mode, it will transition from RUNNING_S to RUNNABLE_S.  The context is
-saved in env_tf.
+saved in scp_ctx.
 
 In _M mode, this yields the calling core.  A yield will *not* transition from _M
 to _S.  The kernel will rip it out of your vcore list.  A process can yield its
index e976941..978c942 100644 (file)
@@ -283,9 +283,9 @@ static void trap_dispatch(struct hw_trapframe *hw_tf)
                        /* We will muck with the actual TF.  If we're dealing with
                         * userspace, we need to make sure we edit the actual TF that will
                         * get restarted (pcpui), and not the TF on the kstack (which aren't
-                        * the same).  See set_current_tf() for more info. */
+                        * the same).  See set_current_ctx() for more info. */
                        if (!in_kernel(hw_tf))
-                               hw_tf = pcpui->cur_tf;
+                               hw_tf = &pcpui->cur_ctx->tf.hw_tf;
                        printd("bad opcode, eip: %08p, next 3 bytes: %x %x %x\n",
                               hw_tf->tf_eip, 
                               *(uint8_t*)(hw_tf->tf_eip + 0), 
@@ -344,21 +344,33 @@ env_pop_ancillary_state(env_t* e)
 /* Helper.  For now, this copies out the TF to pcpui.  Eventually, we should
  * consider doing this in trapentry.S
  *
- * TODO: consider having this return pcpui->cur_tf, so we can set tf in trap and
+ * TODO: consider having this return the tf used, so we can set tf in trap and
  * irq handlers to edit the TF that will get restarted.  Right now, the kernel
  * uses and restarts tf, but userspace restarts the old pcpui tf.  It is
  * tempting to do this, but note that tf stays on the stack of the kthread,
- * while pcpui->cur_tf is for the core we trapped in on.  Meaning if we ever
- * block, suddenly cur_tf is pointing to some old clobbered state that was
+ * while pcpui->cur_ctx is for the core we trapped in on.  Meaning if we ever
+ * block, suddenly cur_ctx is pointing to some old clobbered state that was
  * already returned to and can't be trusted.  Meanwhile tf can always be trusted
  * (like with an in_kernel() check).  The only types of traps from the user that
  * can be expected to have editable trapframes are ones that don't block. */
-static void set_current_tf(struct per_cpu_info *pcpui, struct trapframe *tf)
+static void set_current_ctx_hw(struct per_cpu_info *pcpui,
+                               struct hw_trapframe *hw_tf)
 {
        assert(!irq_is_enabled());
-       assert(!pcpui->cur_tf);
-       pcpui->actual_tf = *tf;
-       pcpui->cur_tf = &pcpui->actual_tf;
+       assert(!pcpui->cur_ctx);
+       pcpui->actual_ctx.type = ROS_HW_CTX;
+       pcpui->actual_ctx.tf.hw_tf = *hw_tf;
+       pcpui->cur_ctx = &pcpui->actual_ctx;
+}
+
+static void set_current_ctx_sw(struct per_cpu_info *pcpui,
+                               struct sw_trapframe *sw_tf)
+{
+       assert(!irq_is_enabled());
+       assert(!pcpui->cur_ctx);
+       pcpui->actual_ctx.type = ROS_SW_CTX;
+       pcpui->actual_ctx.tf.sw_tf = *sw_tf;
+       pcpui->cur_ctx = &pcpui->actual_ctx;
 }
 
 /* If the interrupt interrupted a halt, we advance past it.  Made to work with
@@ -384,7 +396,7 @@ void trap(struct hw_trapframe *hw_tf)
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
        /* Copy out the TF for now */
        if (!in_kernel(hw_tf))
-               set_current_tf(pcpui, hw_tf);
+               set_current_ctx_hw(pcpui, hw_tf);
        else
                inc_ktrap_depth(pcpui);
 
@@ -488,7 +500,7 @@ void irq_handler(struct hw_trapframe *hw_tf)
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
        /* Copy out the TF for now */
        if (!in_kernel(hw_tf))
-               set_current_tf(pcpui, hw_tf);
+               set_current_ctx_hw(pcpui, hw_tf);
        inc_irq_depth(pcpui);
        /* Coupled with cpu_halt() and smp_idle() */
        abort_halt(hw_tf);
@@ -573,7 +585,7 @@ void sysenter_callwrapper(struct hw_trapframe *hw_tf)
 {
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
        assert(!in_kernel(hw_tf));
-       set_current_tf(pcpui, hw_tf);
+       set_current_ctx_hw(pcpui, hw_tf);
        /* Once we've set_current_ctx, we can enable interrupts.  This used to be
         * mandatory (we had immediate KMSGs that would muck with cur_ctx).  Now it
         * should only help for sanity/debugging. */
index a9466d7..e2b2ac9 100644 (file)
@@ -7,7 +7,7 @@
 void
 env_push_ancillary_state(env_t* e)
 {
-       if(e->env_tf.sr & SR_EF)
+       if(e->scp_ctx.hw_tf.sr & SR_EF)
                save_fp_state(&e->env_ancillary_state);
 }
 
@@ -59,7 +59,7 @@ save_fp_state(ancillary_state_t* silly)
 void
 env_pop_ancillary_state(env_t* e)
 { 
-       if(e->env_tf.sr & SR_EF)
+       if(e->scp_ctx.hw_tf.sr & SR_EF)
                restore_fp_state(&e->env_ancillary_state);
 }
 
index 6ddaf16..feb63a9 100644 (file)
@@ -58,16 +58,28 @@ sysenter_init(void)
 {
 }
 
-/* Helper.  For now, this copies out the TF to pcpui, and sets cur_tf to point
+/* Helper.  For now, this copies out the TF to pcpui, and sets cur_ctx to point
  * to it. */
-static void
-set_current_tf(struct per_cpu_info *pcpui, struct trapframe *tf)
+static void set_current_ctx_hw(struct per_cpu_info *pcpui,
+                               struct hw_trapframe *hw_tf)
+{
+       if (irq_is_enabled())
+               warn("Turn off IRQs until cur_ctx is set!");
+       assert(!pcpui->cur_ctx);
+       pcpui->actual_ctx.type = ROS_HW_CTX;
+       pcpui->actual_ctx.hw_tf = *hw_tf;
+       pcpui->cur_ctx = &pcpui->actual_ctx;
+}
+
+static void set_current_ctx_sw(struct per_cpu_info *pcpui,
+                               struct sw_trapframe *sw_tf)
 {
        if (irq_is_enabled())
-               warn("Turn off IRQs until cur_tf is set!");
-       assert(!pcpui->cur_tf);
-       pcpui->actual_tf = *tf;
-       pcpui->cur_tf = &pcpui->actual_tf;
+               warn("Turn off IRQs until cur_ctx is set!");
+       assert(!pcpui->cur_ctx);
+       pcpui->actual_ctx.type = ROS_SW_CTX;
+       pcpui->actual_ctx.sw_tf = *sw_tf;
+       pcpui->cur_ctx = &pcpui->actual_ctx;
 }
 
 static int
@@ -205,7 +217,7 @@ handle_fault_fetch(struct hw_trapframe *state)
                panic("Instruction Page Fault in the Kernel at %p!", state->epc);
        }
 
-       set_current_tf(&per_cpu_info[core_id()], state);
+       set_current_ctx_hw(&per_cpu_info[core_id()], state);
 
        if(handle_page_fault(current, state->epc, PROT_EXEC))
                unhandled_trap(state, "Instruction Page Fault");
@@ -220,7 +232,7 @@ handle_fault_load(struct hw_trapframe *state)
                panic("Load Page Fault in the Kernel at %p!", state->badvaddr);
        }
 
-       set_current_tf(&per_cpu_info[core_id()], state);
+       set_current_ctx_hw(&per_cpu_info[core_id()], state);
 
        if(handle_page_fault(current, state->badvaddr, PROT_READ))
                unhandled_trap(state, "Load Page Fault");
@@ -235,7 +247,7 @@ handle_fault_store(struct hw_trapframe *state)
                panic("Store Page Fault in the Kernel at %p!", state->badvaddr);
        }
 
-       set_current_tf(&per_cpu_info[core_id()], state);
+       set_current_ctx_hw(&per_cpu_info[core_id()], state);
 
        if(handle_page_fault(current, state->badvaddr, PROT_WRITE))
                unhandled_trap(state, "Store Page Fault");
@@ -247,10 +259,10 @@ handle_illegal_instruction(struct hw_trapframe *state)
        assert(!in_kernel(state));
 
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
-       set_current_tf(pcpui, state);
+       set_current_ctx_hw(pcpui, state);
        if (emulate_fpu(state) == 0)
        {
-               advance_pc(pcpui->cur_tf);
+               advance_pc(&pcpui->cur_ctx->hw_tf);
                return;
        }
 
@@ -274,7 +286,7 @@ handle_syscall(struct hw_trapframe *state)
        uintptr_t a1 = state->gpr[5];
 
        advance_pc(state);
-       set_current_tf(&per_cpu_info[core_id()], state);
+       set_current_ctx_hw(&per_cpu_info[core_id()], state);
        enable_irq();
        prep_syscalls(current, (struct syscall*)a0, a1);
 }
@@ -319,7 +331,7 @@ handle_trap(struct hw_trapframe *hw_tf)
                if (in_kernel(hw_tf))
                        exit_halt_loop(hw_tf);
                else
-                       set_current_tf(&per_cpu_info[core_id()], hw_tf);
+                       set_current_ctx_hw(&per_cpu_info[core_id()], hw_tf);
 
                inc_irq_depth(pcpui);
                irq_handlers[irq](hw_tf);
index 368e041..4cd17b7 100644 (file)
@@ -22,7 +22,7 @@ static_asserts_can_go_here()
        static_assert(SIZEOF_TRAPFRAME_T % 8 == 0);
        static_assert(SIZEOF_KERNEL_MESSAGE_T == sizeof(kernel_message_t));
        static_assert(SIZEOF_KERNEL_MESSAGE_T % 8 == 0);
-       static_assert(offsetof(env_t,env_tf) % 8 == 0);
+       static_assert(offsetof(env_t,scp_ctx) % 8 == 0);
        static_assert(offsetof(env_t,env_ancillary_state) % 8 == 0);
 }
 
index ee13489..71c2271 100644 (file)
@@ -16,7 +16,7 @@
 void
 ( env_push_ancillary_state)(env_t* e)
 {
-       if(e->env_tf.psr & PSR_EF)
+       if(e->scp_ctx.hw_tf.psr & PSR_EF)
                save_fp_state(&e->env_ancillary_state);
 }
 
@@ -54,7 +54,7 @@ save_fp_state(ancillary_state_t* silly)
 void
 ( env_pop_ancillary_state)(env_t* e)
 { 
-       if(e->env_tf.psr & PSR_EF)
+       if(e->scp_ctx.hw_tf.psr & PSR_EF)
                restore_fp_state(&e->env_ancillary_state);
 }
 
index 4b446eb..14c3eec 100644 (file)
@@ -80,15 +80,28 @@ sysenter_init(void)
 {
 }
 
-/* Helper.  For now, this copies out the TF to pcpui, and sets cur_tf to point
+/* Helper.  For now, this copies out the TF to pcpui, and sets cur_ctx to point
  * to it. */
-static void set_current_tf(struct per_cpu_info *pcpui, struct trapframe *tf)
+static void set_current_ctx_hw(struct per_cpu_info *pcpui,
+                               struct hw_trapframe *hw_tf)
 {
        if (irq_is_enabled())
-               warn("Turn off IRQs until cur_tf is set!");
-       assert(!pcpui->cur_tf);
-       pcpui->actual_tf = *tf;
-       pcpui->cur_tf = &pcpui->actual_tf;
+               warn("Turn off IRQs until cur_ctx is set!");
+       assert(!pcpui->cur_ctx);
+       pcpui->actual_ctx.type = ROS_HW_CTX;
+       pcpui->actual_ctx.hw_tf = *hw_tf;
+       pcpui->cur_ctx = &pcpui->actual_ctx;
+}
+
+static void set_current_ctx_sw(struct per_cpu_info *pcpui,
+                               struct sw_trapframe *sw_tf)
+{
+       if (irq_is_enabled())
+               warn("Turn off IRQs until cur_ctx is set!");
+       assert(!pcpui->cur_ctx);
+       pcpui->actual_ctx.type = ROS_SW_CTX;
+       pcpui->actual_ctx.sw_tf = *sw_tf;
+       pcpui->cur_ctx = &pcpui->actual_ctx;
 }
 
 static int format_trapframe(struct hw_trapframe *hw_tf, char *buf, int bufsz)
@@ -179,7 +192,7 @@ void handle_ipi(struct hw_trapframe *hw_tf)
 {
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
        if (!in_kernel(hw_tf))
-               set_current_tf(pcpui, hw_tf);
+               set_current_ctx_hw(pcpui, hw_tf);
        else if((void*)hw_tf->pc == &__cpu_halt) // break out of the __cpu_halt loop
                advance_pc(hw_tf);
 
@@ -308,7 +321,7 @@ void fp_disabled(struct hw_trapframe *state)
 void handle_pop_tf(struct hw_trapframe *state)
 {
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
-       set_current_tf(pcpui, state);
+       set_current_ctx_hw(pcpui, state);
 
        struct hw_trapframe hw_tf, *hw_tf_p = &hw_tf;
        if (memcpy_from_user(current, &hw_tf, (void*)state->gpr[8],sizeof(hw_tf))) {
@@ -318,7 +331,7 @@ void handle_pop_tf(struct hw_trapframe *state)
        }
 
        proc_secure_trapframe(&hw_tf);
-       set_current_tf(pcpui, hw_tf_p);
+       set_current_ctx_hw(pcpui, hw_tf_p);
        proc_restartcore();
 }
 
@@ -343,7 +356,7 @@ void handle_syscall(struct hw_trapframe *state)
        enable_irq();
        struct per_cpu_info* coreinfo = &per_cpu_info[core_id()];
 
-       set_current_tf(pcpui, state);
+       set_current_ctx_hw(pcpui, state);
 
        prep_syscalls(current, (struct syscall*)a0, a1);
 
index d5636ea..0df0724 100644 (file)
@@ -29,7 +29,7 @@ struct proc {
        TAILQ_ENTRY(proc) proc_arsc_link;
        TAILQ_ENTRY(proc) sibling_link;
        spinlock_t proc_lock;
-       trapframe_t env_tf;                                             // Saved registers
+       struct user_context scp_ctx;    /* context for an SCP.  TODO: move to vc0 */
        ancillary_state_t env_ancillary_state;  // State saved when descheduled
        pid_t pid;
        /* Tempting to add a struct proc *parent, but we'd need to protect the use
index 3afe382..7c4c09d 100644 (file)
@@ -75,7 +75,7 @@ void proc_destroy(struct proc *p);
 void proc_signal_parent(struct proc *child);
 int __proc_disown_child(struct proc *parent, struct proc *child);
 int proc_change_to_m(struct proc *p);
-void __proc_save_context_s(struct proc *p, struct trapframe *tf);
+void __proc_save_context_s(struct proc *p, struct user_context *ctx);
 void proc_yield(struct proc *SAFE p, bool being_nice);
 void proc_notify(struct proc *p, uint32_t vcoreid);
 void proc_wakeup(struct proc *p);
@@ -129,7 +129,7 @@ void proc_tlbshootdown(struct proc *p, uintptr_t start, uintptr_t end);
 
 /* Kernel message handlers for process management */
 void __startcore(uint32_t srcid, long a0, long a1, long a2);
-void __set_curtf(uint32_t srcid, long a0, long a1, long a2);
+void __set_curctx(uint32_t srcid, long a0, long a1, long a2);
 void __notify(uint32_t srcid, long a0, long a1, long a2);
 void __preempt(uint32_t srcid, long a0, long a1, long a2);
 void __death(uint32_t srcid, long a0, long a1, long a2);
index 42a0f0a..f19642d 100644 (file)
@@ -27,10 +27,10 @@ struct per_cpu_info {
        /* Process management */
        // cur_proc should be valid on all cores that are not management cores.
        struct proc *cur_proc;          /* which process context is loaded */
-       struct proc *owning_proc;       /* proc owning the core / cur_tf */
+       struct proc *owning_proc;       /* proc owning the core / cur_ctx */
        uint32_t owning_vcoreid;        /* vcoreid of owning proc (if applicable */
-       struct trapframe *cur_tf;       /* user tf we came in on (can be 0) */
-       struct trapframe actual_tf;     /* storage for cur_tf */
+       struct user_context *cur_ctx;   /* user ctx we came in on (can be 0) */
+       struct user_context actual_ctx; /* storage for cur_ctx */
        uint32_t __ctx_depth;           /* don't access directly.  see trap.h. */
        int __lock_depth_disabled;      /* disables spinlock depth checking */
        struct syscall *cur_sysc;       /* ptr is into cur_proc's address space */
@@ -58,11 +58,11 @@ struct per_cpu_info {
 /* Allows the kernel to figure out what process is running on this core.  Can be
  * used just like a pointer to a struct proc. */
 #define current per_cpu_info[core_id()].cur_proc
-/* Allows the kernel to figure out what *user* tf is on this core's stack.  Can
- * be used just like a pointer to a struct Trapframe.  Note the distinction
+/* Allows the kernel to figure out what *user* ctx is on this core's stack.  Can
+ * be used just like a pointer to a struct user_context.  Note the distinction
  * between kernel and user contexts.  The kernel always returns to its nested,
  * interrupted contexts via iret/etc.  We never do that for user contexts. */
-#define current_tf per_cpu_info[core_id()].cur_tf
+#define current_ctx per_cpu_info[core_id()].cur_ctx
 
 typedef struct per_cpu_info NTPTV(t) NTPTV(a0t) NTPTV(a1t) NTPTV(a2t) per_cpu_info_t;
 
index c5e1322..d4f79a6 100644 (file)
@@ -256,7 +256,7 @@ int load_elf(struct proc* p, struct file* f)
        memcpy(p->procinfo->argp+auxp_pos,auxp,sizeof(auxp));
 
        uintptr_t core0_entry = ei.dynamic ? interp_ei.entry : ei.entry;
-       proc_init_trapframe(&p->env_tf,0,core0_entry,USTACKTOP);
+       proc_init_trapframe(&p->scp_ctx.tf.hw_tf, 0, core0_entry, USTACKTOP);
        p->env_entry = ei.entry;
 
        int flags = MAP_FIXED | MAP_ANONYMOUS;
index c59469c..cb07a82 100644 (file)
@@ -102,7 +102,7 @@ static void __launch_kthread(uint32_t srcid, long a0, long a1, long a2)
                        spin_lock(&pcpui->owning_proc->proc_lock);
                        /* Wrap up / yield the _S proc */
                        __proc_set_state(pcpui->owning_proc, PROC_WAITING);
-                       __proc_save_context_s(pcpui->owning_proc, current_tf);
+                       __proc_save_context_s(pcpui->owning_proc, current_ctx);
                        spin_unlock(&pcpui->owning_proc->proc_lock);
                        proc_wakeup(p);
                        abandon_core();
index dc19a4d..b719b2b 100644 (file)
@@ -32,7 +32,7 @@
 struct kmem_cache *proc_cache;
 
 /* Other helpers, implemented later. */
-static void __proc_startcore(struct proc *p, trapframe_t *tf);
+static void __proc_startcore(struct proc *p, struct user_context *ctx);
 static bool is_mapped_vcore(struct proc *p, uint32_t pcoreid);
 static uint32_t get_vcoreid(struct proc *p, uint32_t pcoreid);
 static uint32_t try_get_pcoreid(struct proc *p, uint32_t vcoreid);
@@ -442,7 +442,7 @@ static bool scp_is_vcctx_ready(struct preempt_data *vcpd)
  *
  * This will always return, regardless of whether or not the calling core is
  * being given to a process. (it used to pop the tf directly, before we had
- * cur_tf).
+ * cur_ctx).
  *
  * Since it always returns, it will never "eat" your reference (old
  * documentation talks about this a bit). */
@@ -462,7 +462,7 @@ void proc_run_s(struct proc *p)
                        /* We will want to know where this process is running, even if it is
                         * only in RUNNING_S.  can use the vcoremap, which makes death easy.
                         * Also, this is the signal used in trap.c to know to save the tf in
-                        * env_tf. */
+                        * scp_ctx. */
                        __seq_start_write(&p->procinfo->coremap_seqctr);
                        p->procinfo->num_vcores = 0;    /* TODO (VC#) */
                        /* TODO: For now, we won't count this as an active vcore (on the
@@ -488,12 +488,12 @@ void proc_run_s(struct proc *p)
                        if (!vcpd->notif_disabled && vcpd->notif_pending
                                                  && scp_is_vcctx_ready(vcpd)) {
                                vcpd->notif_disabled = TRUE;
-                               /* save the _S's tf in the notify slot, build and pop a new one
-                                * in actual/cur_tf. */
-                               vcpd->notif_tf = p->env_tf;
-                               pcpui->cur_tf = &pcpui->actual_tf;
-                               memset(pcpui->cur_tf, 0, sizeof(struct trapframe));
-                               proc_init_trapframe(pcpui->cur_tf, 0, p->env_entry,
+                               /* save the _S's ctx in the notify slot, build and pop a new one
+                                * in actual/cur_ctx. */
+                               vcpd->notif_tf = p->scp_ctx.tf.hw_tf;   /* TODO CTX */
+                               pcpui->cur_ctx = &pcpui->actual_ctx;
+                               memset(pcpui->cur_ctx, 0, sizeof(struct user_context));
+                               proc_init_trapframe(&pcpui->cur_ctx->tf.hw_tf, 0, p->env_entry,
                                                    vcpd->transition_stack);
                        } else {
                                /* If they have no transition stack, then they can't receive
@@ -502,8 +502,8 @@ void proc_run_s(struct proc *p)
                                 * that for them. */
                                if (!scp_is_vcctx_ready(vcpd))
                                        vcpd->notif_pending = FALSE;
-                               /* this is one of the few times cur_tf != &actual_tf */
-                               pcpui->cur_tf = &p->env_tf;
+                               /* this is one of the few times cur_ctx != &actual_ctx */
+                               pcpui->cur_ctx = &p->scp_ctx;
                        }
                        /* When the calling core idles, it'll call restartcore and run the
                         * _S process's context. */
@@ -562,8 +562,7 @@ void __proc_run_m(struct proc *p)
                        return;
                case (PROC_RUNNABLE_M):
                        /* vcoremap[i] holds the coreid of the physical core allocated to
-                        * this process.  It is set outside proc_run.  For the kernel
-                        * message, a0 = struct proc*, a1 = struct trapframe*.   */
+                        * this process.  It is set outside proc_run. */
                        if (p->procinfo->num_vcores) {
                                __send_bulkp_events(p);
                                __proc_set_state(p, PROC_RUNNING_M);
@@ -613,7 +612,7 @@ void __proc_run_m(struct proc *p)
  * in current and you have one reference, like proc_run(non_current_p), then
  * also do nothing.  The refcnt for your *p will count for the reference stored
  * in current. */
-static void __proc_startcore(struct proc *p, trapframe_t *tf)
+static void __proc_startcore(struct proc *p, struct user_context *ctx)
 {
        assert(!irq_is_enabled());
        __set_proc_current(p);
@@ -628,12 +627,12 @@ static void __proc_startcore(struct proc *p, trapframe_t *tf)
         * __startcore.  */
        if (p->state == PROC_RUNNING_S)
                env_pop_ancillary_state(p);
-       /* Clear the current_tf, since it is no longer used */
-       current_tf = 0; /* TODO: might not need this... */
-       env_pop_tf(tf);
+       /* Clear the current_ctx, since it is no longer used */
+       current_ctx = 0;        /* TODO: might not need this... */
+       env_pop_tf(&ctx->tf.hw_tf); /* TODO CTX */
 }
 
-/* Restarts/runs the current_tf, which must be for the current process, on the
+/* Restarts/runs the current_ctx, which must be for the current process, on the
  * core this code executes on.  Calls an internal function to do the work.
  *
  * In case there are pending routine messages, like __death, __preempt, or
@@ -665,8 +664,8 @@ void proc_restartcore(void)
                abandon_core();
                smp_idle();
        }
-       assert(pcpui->cur_tf);
-       __proc_startcore(pcpui->owning_proc, pcpui->cur_tf);
+       assert(pcpui->cur_ctx);
+       __proc_startcore(pcpui->owning_proc, pcpui->cur_ctx);
 }
 
 /* Destroys the process.  It will destroy the process and return any cores
@@ -813,9 +812,9 @@ int proc_change_to_m(struct proc *p)
                         * it in the preempt slot so that we can also save the silly
                         * state. */
                        struct preempt_data *vcpd = &p->procdata->vcore_preempt_data[0];
-                       assert(current_tf);
+                       assert(current_ctx);
                        /* Copy uthread0's context to the notif slot */
-                       vcpd->notif_tf = *current_tf;
+                       vcpd->notif_tf = current_ctx->tf.hw_tf; /* TODO CTX */
                        clear_owning_proc(core_id());   /* so we don't restart */
                        save_fp_state(&vcpd->preempt_anc);
                        /* Userspace needs to not fuck with notif_disabled before
@@ -869,8 +868,8 @@ uint32_t __proc_change_to_s(struct proc *p, uint32_t *pc_arr)
        printk("[kernel] trying to transition _M -> _S (deprecated)!\n");
        assert(p->state == PROC_RUNNING_M); // TODO: (ACR) async core req
        /* save the context, to be restarted in _S mode */
-       assert(current_tf);
-       p->env_tf = *current_tf;
+       assert(current_ctx);
+       p->scp_ctx = *current_ctx;
        clear_owning_proc(core_id());   /* so we don't restart */
        env_push_ancillary_state(p); // TODO: (HSS)
        /* sending death, since it's not our job to save contexts or anything in
@@ -912,10 +911,12 @@ static uint32_t get_pcoreid(struct proc *p, uint32_t vcoreid)
 }
 
 /* Helper: saves the SCP's tf state and unmaps vcore 0.  In the future, we'll
- * probably use vc0's space for env_tf and the silly state. */
-void __proc_save_context_s(struct proc *p, struct trapframe *tf)
+ * probably use vc0's space for scp_ctx and the silly state.  If we ever do
+ * that, we'll need to stop using scp_ctx (soon to be in VCPD) as a location for
+ * pcpui->cur_ctx to point (dangerous) */
+void __proc_save_context_s(struct proc *p, struct user_context *ctx)
 {
-       p->env_tf= *tf;
+       p->scp_ctx = *ctx;
        env_push_ancillary_state(p);                    /* TODO: (HSS) */
        __unmap_vcore(p, 0);    /* VC# keep in sync with proc_run_s */
 }
@@ -940,9 +941,9 @@ void __proc_save_context_s(struct proc *p, struct trapframe *tf)
  * Also note that it needs a non-current/edible reference, since it will abandon
  * and continue to use the *p (current == 0, no cr3, etc).
  *
- * We disable interrupts for most of it too, since we need to protect current_tf
- * and not race with __notify (which doesn't play well with concurrent
- * yielders). */
+ * We disable interrupts for most of it too, since we need to protect
+ * current_ctx and not race with __notify (which doesn't play well with
+ * concurrent yielders). */
 void proc_yield(struct proc *SAFE p, bool being_nice)
 {
        uint32_t vcoreid, pcoreid = core_id();
@@ -951,7 +952,7 @@ void proc_yield(struct proc *SAFE p, bool being_nice)
        struct preempt_data *vcpd;
        /* Need to lock to prevent concurrent vcore changes (online, inactive, the
         * mapping, etc).  This plus checking the nr_preempts is enough to tell if
-        * our vcoreid and cur_tf ought to be here still or if we should abort */
+        * our vcoreid and cur_ctx ought to be here still or if we should abort */
        spin_lock(&p->proc_lock); /* horrible scalability.  =( */
        switch (p->state) {
                case (PROC_RUNNING_S):
@@ -976,13 +977,13 @@ void proc_yield(struct proc *SAFE p, bool being_nice)
                                /* if we're here, we want to sleep.  a concurrent event that
                                 * hasn't already written notif_pending will have seen WAITING,
                                 * and will be spinning while we do this. */
-                               __proc_save_context_s(p, current_tf);
+                               __proc_save_context_s(p, current_ctx);
                                spin_unlock(&p->proc_lock);
                        } else {
                                /* yielding to allow other processes to run.  we're briefly
                                 * WAITING, til we are woken up */
                                __proc_set_state(p, PROC_WAITING);
-                               __proc_save_context_s(p, current_tf);
+                               __proc_save_context_s(p, current_ctx);
                                spin_unlock(&p->proc_lock);
                                /* immediately wake up the proc (makes it runnable) */
                                proc_wakeup(p);
@@ -1592,7 +1593,7 @@ void clear_owning_proc(uint32_t coreid)
        struct proc *p = pcpui->owning_proc;
        pcpui->owning_proc = 0;
        pcpui->owning_vcoreid = 0xdeadbeef;
-       pcpui->cur_tf = 0;                      /* catch bugs for now (will go away soon) */
+       pcpui->cur_ctx = 0;                     /* catch bugs for now (may go away) */
        if (p)
                proc_decref(p);
 }
@@ -1669,11 +1670,11 @@ void proc_tlbshootdown(struct proc *p, uintptr_t start, uintptr_t end)
        spin_unlock(&p->proc_lock);
 }
 
-/* Helper, used by __startcore and __set_curtf, which sets up cur_tf to run a
+/* Helper, used by __startcore and __set_curctx, which sets up cur_ctx to run a
  * given process's vcore.  Caller needs to set up things like owning_proc and
  * whatnot.  Note that we might not have p loaded as current. */
-static void __set_curtf_to_vcoreid(struct proc *p, uint32_t vcoreid,
-                                   uint32_t old_nr_preempts_sent)
+static void __set_curctx_to_vcoreid(struct proc *p, uint32_t vcoreid,
+                                    uint32_t old_nr_preempts_sent)
 {
        struct per_cpu_info *pcpui = &per_cpu_info[core_id()];
        struct preempt_data *vcpd = &p->procdata->vcore_preempt_data[vcoreid];
@@ -1707,19 +1708,19 @@ static void __set_curtf_to_vcoreid(struct proc *p, uint32_t vcoreid,
        if (vcpd->notif_disabled) {
                restore_fp_state(&vcpd->preempt_anc);
                /* copy-in the tf we'll pop, then set all security-related fields */
-               pcpui->actual_tf = vcpd->preempt_tf;
-               proc_secure_trapframe(&pcpui->actual_tf);
+               pcpui->actual_ctx.tf.hw_tf = vcpd->preempt_tf;  /* TODO CTX */
+               proc_secure_trapframe(&pcpui->actual_ctx.tf.hw_tf);
        } else { /* not restarting from a preemption, use a fresh vcore */
                assert(vcpd->transition_stack);
                /* TODO: consider 0'ing the FP state.  We're probably leaking. */
-               proc_init_trapframe(&pcpui->actual_tf, vcoreid, p->env_entry,
+               proc_init_trapframe(&pcpui->actual_ctx.tf.hw_tf, vcoreid, p->env_entry,
                                    vcpd->transition_stack);
                /* Disable/mask active notifications for fresh vcores */
                vcpd->notif_disabled = TRUE;
        }
-       /* cur_tf was built above (in actual_tf), now use it */
-       pcpui->cur_tf = &pcpui->actual_tf;
-       /* this cur_tf will get run when the kernel returns / idles */
+       /* cur_ctx was built above (in actual_ctx), now use it */
+       pcpui->cur_ctx = &pcpui->actual_ctx;
+       /* this cur_ctx will get run when the kernel returns / idles */
 }
 
 /* Changes calling vcore to be vcoreid.  enable_my_notif tells us about how the
@@ -1796,9 +1797,9 @@ int proc_change_to_vcore(struct proc *p, uint32_t new_vcoreid,
                 * and we don't care about either the notif_tf or the preempt_tf. */
                caller_vcpd->notif_disabled = FALSE;
        } else {
-               /* need to set up the calling vcore's tf so that it'll get restarted by
+               /* need to set up the calling vcore's ctx so that it'll get restarted by
                 * __startcore, to make the caller look like it was preempted. */
-               caller_vcpd->preempt_tf = *current_tf;
+               caller_vcpd->preempt_tf = current_ctx->tf.hw_tf; // TODO CTX
                save_fp_state(&caller_vcpd->preempt_anc);
                /* Mark our core as preempted (for userspace recovery). */
                atomic_or(&caller_vcpd->flags, VC_PREEMPTED);
@@ -1830,15 +1831,15 @@ int proc_change_to_vcore(struct proc *p, uint32_t new_vcoreid,
        /* So this core knows which vcore is here. (cur_proc and owning_proc are
         * already correct): */
        pcpui->owning_vcoreid = new_vcoreid;
-       /* Until we set_curtf, we don't really have a valid current tf.  The stuff
+       /* Until we set_curctx, we don't really have a valid current tf.  The stuff
         * in that old one is from our previous vcore, not the current
         * owning_vcoreid.  This matters for other KMSGS that will run before
-        * __set_curtf (like __notify). */
-       pcpui->cur_tf = 0;
-       /* Need to send a kmsg to finish.  We can't set_curtf til the __PR is done,
+        * __set_curctx (like __notify). */
+       pcpui->cur_ctx = 0;
+       /* Need to send a kmsg to finish.  We can't set_curctx til the __PR is done,
         * but we can't spin right here while holding the lock (can't spin while
         * waiting on a message, roughly) */
-       send_kernel_message(pcoreid, __set_curtf, (long)p, (long)new_vcoreid,
+       send_kernel_message(pcoreid, __set_curctx, (long)p, (long)new_vcoreid,
                            (long)new_vc->nr_preempts_sent, KMSG_ROUTINE);
        retval = 0;
        /* Fall through to exit */
@@ -1877,25 +1878,24 @@ void __startcore(uint32_t srcid, long a0, long a1, long a2)
        }
        /* Note we are not necessarily in the cr3 of p_to_run */
        /* Now that we sorted refcnts and know p / which vcore it should be, set up
-        * pcpui->cur_tf so that it will run that particular vcore */
-       __set_curtf_to_vcoreid(p_to_run, vcoreid, old_nr_preempts_sent);
+        * pcpui->cur_ctx so that it will run that particular vcore */
+       __set_curctx_to_vcoreid(p_to_run, vcoreid, old_nr_preempts_sent);
 }
 
 /* Kernel message handler to load a proc's vcore context on this core.  Similar
  * to __startcore, except it is used when p already controls the core (e.g.
  * change_to).  Since the core is already controlled, pcpui such as owning proc,
  * vcoreid, and cur_proc are all already set. */
-void __set_curtf(uint32_t srcid, long a0, long a1, long a2)
+void __set_curctx(uint32_t srcid, long a0, long a1, long a2)
 {
        struct proc *p = (struct proc*)a0;
        uint32_t vcoreid = (uint32_t)a1;
        uint32_t old_nr_preempts_sent = (uint32_t)a2;
-       __set_curtf_to_vcoreid(p, vcoreid, old_nr_preempts_sent);
+       __set_curctx_to_vcoreid(p, vcoreid, old_nr_preempts_sent);
 }
 
-/* Bail out if it's the wrong process, or if they no longer want a notif.  Don't
- * use the TF we passed in, we care about cur_tf.  Try not to grab locks or
- * write access to anything that isn't per-core in here. */
+/* Bail out if it's the wrong process, or if they no longer want a notif.  Try
+ * not to grab locks or write access to anything that isn't per-core in here. */
 void __notify(uint32_t srcid, long a0, long a1, long a2)
 {
        uint32_t vcoreid, coreid = core_id();
@@ -1906,12 +1906,11 @@ void __notify(uint32_t srcid, long a0, long a1, long a2)
        /* Not the right proc */
        if (p != pcpui->owning_proc)
                return;
-       /* the core might be owned, but not have a valid cur_tf (if we're in the
+       /* the core might be owned, but not have a valid cur_ctx (if we're in the
         * process of changing */
-       if (!pcpui->cur_tf)
+       if (!pcpui->cur_ctx)
                return;
-       /* Common cur_tf sanity checks.  Note cur_tf could be an _S's env_tf */
-       assert(!in_kernel(pcpui->cur_tf));
+       /* Common cur_ctx sanity checks.  Note cur_ctx could be an _S's scp_ctx */
        vcoreid = pcpui->owning_vcoreid;
        vcpd = &p->procdata->vcore_preempt_data[vcoreid];
        /* for SCPs that haven't (and might never) call vc_event_init, like rtld.
@@ -1926,11 +1925,11 @@ void __notify(uint32_t srcid, long a0, long a1, long a2)
        vcpd->notif_disabled = TRUE;
        /* save the old tf in the notify slot, build and pop a new one.  Note that
         * silly state isn't our business for a notification. */
-       vcpd->notif_tf = *pcpui->cur_tf;
-       memset(pcpui->cur_tf, 0, sizeof(struct trapframe));
-       proc_init_trapframe(pcpui->cur_tf, vcoreid, p->env_entry,
+       vcpd->notif_tf = pcpui->cur_ctx->tf.hw_tf; /* TODO CTX */
+       memset(pcpui->cur_ctx, 0, sizeof(struct user_context));
+       proc_init_trapframe(&pcpui->cur_ctx->tf.hw_tf, vcoreid, p->env_entry,
                            vcpd->transition_stack);
-       /* this cur_tf will get run when the kernel returns / idles */
+       /* this cur_ctx will get run when the kernel returns / idles */
 }
 
 void __preempt(uint32_t srcid, long a0, long a1, long a2)
@@ -1945,22 +1944,21 @@ void __preempt(uint32_t srcid, long a0, long a1, long a2)
                panic("__preempt arrived for a process (%p) that was not owning (%p)!",
                      p, pcpui->owning_proc);
        }
-       /* Common cur_tf sanity checks */
-       assert(pcpui->cur_tf);
-       assert(pcpui->cur_tf == &pcpui->actual_tf);
-       assert(!in_kernel(pcpui->cur_tf));
+       /* Common cur_ctx sanity checks */
+       assert(pcpui->cur_ctx);
+       assert(pcpui->cur_ctx == &pcpui->actual_ctx);
        vcoreid = pcpui->owning_vcoreid;
        vcpd = &p->procdata->vcore_preempt_data[vcoreid];
        printd("[kernel] received __preempt for proc %d's vcore %d on pcore %d\n",
               p->procinfo->pid, vcoreid, coreid);
        /* if notifs are disabled, the vcore is in vcore context (as far as we're
         * concerned), and we save it in the preempt slot. o/w, we save the
-        * process's cur_tf in the notif slot, and it'll appear to the vcore when it
-        * comes back up that it just took a notification. */
+        * process's cur_ctx in the notif slot, and it'll appear to the vcore when
+        * it comes back up that it just took a notification. */
        if (vcpd->notif_disabled)
-               vcpd->preempt_tf = *pcpui->cur_tf;
+               vcpd->preempt_tf = pcpui->cur_ctx->tf.hw_tf; /* TODO CTX */
        else
-               vcpd->notif_tf = *pcpui->cur_tf;
+               vcpd->notif_tf = pcpui->cur_ctx->tf.hw_tf; /* TODO CTX */
        /* either way, we save the silly state (FP) */
        save_fp_state(&vcpd->preempt_anc);
        /* Mark the vcore as preempted and unlock (was locked by the sender). */
index 4065ffa..3aa3218 100644 (file)
@@ -361,7 +361,7 @@ static bool __schedule_scp(void)
        /* if there are any runnables, run them here and put any currently running
         * SCP on the tail of the runnable queue. */
        if ((p = TAILQ_FIRST(&runnable_scps))) {
-               /* protect owning proc, cur_tf, etc.  note this nests with the
+               /* protect owning proc, cur_ctx, etc.  note this nests with the
                 * calls in proc_yield_s */
                disable_irqsave(&state);
                /* someone is currently running, dequeue them */
@@ -371,7 +371,7 @@ static bool __schedule_scp(void)
                        /* locking just to be safe */
                        spin_lock(&p->proc_lock);
                        __proc_set_state(pcpui->owning_proc, PROC_RUNNABLE_S);
-                       __proc_save_context_s(pcpui->owning_proc, pcpui->cur_tf);
+                       __proc_save_context_s(pcpui->owning_proc, pcpui->cur_ctx);
                        spin_unlock(&p->proc_lock);
                        /* round-robin the SCPs (inserts at the end of the queue) */
                        switch_lists(pcpui->owning_proc, &unrunnable_scps, &runnable_scps);
index c35b026..27304d4 100644 (file)
@@ -406,13 +406,13 @@ static ssize_t sys_fork(env_t* e)
 
        env->heap_top = e->heap_top;
        env->ppid = e->pid;
-       disable_irqsave(&state);        /* protect cur_tf */
-       /* Can't really fork if we don't have a current_tf to fork */
-       if (!current_tf) {
+       disable_irqsave(&state);        /* protect cur_ctx */
+       /* Can't really fork if we don't have a current_ctx to fork */
+       if (!current_ctx) {
                set_errno(EINVAL);
                return -1;
        }
-       env->env_tf = *current_tf;
+       env->scp_ctx = *current_ctx;
        enable_irqsave(&state);
 
        env->cache_colors_map = cache_colors_map_alloc();
@@ -490,22 +490,22 @@ static int sys_exec(struct proc *p, char *path, size_t path_l,
        t_path = user_strdup_errno(p, path, path_l);
        if (!t_path)
                return -1;
-       disable_irqsave(&state);        /* protect cur_tf */
-       /* Can't exec if we don't have a current_tf to restart (if we fail).  This
+       disable_irqsave(&state);        /* protect cur_ctx */
+       /* Can't exec if we don't have a current_ctx to restart (if we fail).  This
         * isn't 100% true, but I'm okay with it. */
-       if (!pcpui->cur_tf) {
+       if (!pcpui->cur_ctx) {
                enable_irqsave(&state);
                set_errno(EINVAL);
                return -1;
        }
-       /* Preemptively copy out the cur_tf, in case we fail later (easier on cur_tf
-        * if we do this now) */
-       p->env_tf = *pcpui->cur_tf;
-       /* Clear the current_tf.  We won't be returning the 'normal' way.  Even if
+       /* Preemptively copy out the cur_ctx, in case we fail later (easier on
+        * cur_ctx if we do this now) */
+       p->scp_ctx = *pcpui->cur_ctx;
+       /* Clear the current_ctx.  We won't be returning the 'normal' way.  Even if
         * we want to return with an error, we need to go back differently in case
         * we succeed.  This needs to be done before we could possibly block, but
         * unfortunately happens before the point of no return. */
-       pcpui->cur_tf = 0;
+       pcpui->cur_ctx = 0;
        enable_irqsave(&state);
        /* This could block: */
        program = do_file_open(t_path, 0, 0);