From c100d9ee2d7d02253b55349bf55796efb3be5699 Mon Sep 17 00:00:00 2001
From: kolya <kolya>
Date: Wed, 15 Oct 2008 05:14:10 +0000
Subject: [PATCH] cleaner swtch.S

---
 defs.h  |  2 +-
 proc.c  |  8 ++++----
 proc.h  | 26 +++++++++++---------------
 swtch.S | 36 +++++++++++++++---------------------
 4 files changed, 31 insertions(+), 41 deletions(-)

diff --git a/defs.h b/defs.h
index 661f761..a472b2e 100644
--- a/defs.h
+++ b/defs.h
@@ -107,7 +107,7 @@ void            wakeup(void*);
 void            yield(void);
 
 // swtch.S
-void            swtch(struct context*, struct context*);
+void            swtch(struct context**, struct context**);
 
 // spinlock.c
 void            acquire(struct spinlock*);
diff --git a/proc.c b/proc.c
index fdd633d..5ecf474 100644
--- a/proc.c
+++ b/proc.c
@@ -137,9 +137,9 @@ copyproc(struct proc *p)
   }
 
   // Set up new context to start executing at forkret (see below).
-  memset(&np->context, 0, sizeof(np->context));
-  np->context.eip = (uint)forkret;
-  np->context.esp = (uint)np->tf;
+  np->context = (struct context *)np->tf - 1;
+  memset(np->context, 0, sizeof(*np->context));
+  np->context->eip = (uint)forkret;
 
   // Clear %eax so that fork system call returns 0 in child.
   np->tf->eax = 0;
@@ -477,7 +477,7 @@ procdump(void)
       state = "???";
     cprintf("%d %s %s", p->pid, state, p->name);
     if(p->state == SLEEPING){
-      getcallerpcs((uint*)p->context.ebp+2, pc);
+      getcallerpcs((uint*)p->context->ebp+2, pc);
       for(j=0; j<10 && pc[j] != 0; j++)
         cprintf(" %p", pc[j]);
     }
diff --git a/proc.h b/proc.h
index 502361d..41860c6 100644
--- a/proc.h
+++ b/proc.h
@@ -7,21 +7,17 @@
 #define NSEGS     6
 
 // Saved registers for kernel context switches.
-// Don't need to save all the %fs etc. segment registers,
+// Don't need to save all the segment registers (%cs, etc),
 // because they are constant across kernel contexts.
-// Save all the regular registers so we don't need to care
-// which are caller save, but not the return register %eax.
-// (Not saving %eax just simplifies the switching code.)
+// Stack pointer is encoded in the address of context,
+// which must be placed at the bottom of the stack.
 // The layout of context must match code in swtch.S.
 struct context {
-  int eip;
-  int esp;
-  int ebx;
-  int ecx;
-  int edx;
-  int esi;
-  int edi;
-  int ebp;
+  uint edi;
+  uint esi;
+  uint ebx;
+  uint ebp;
+  uint eip;
 };
 
 enum proc_state { UNUSED, EMBRYO, SLEEPING, RUNNABLE, RUNNING, ZOMBIE };
@@ -38,8 +34,8 @@ struct proc {
   int killed;               // If non-zero, have been killed
   struct file *ofile[NOFILE];  // Open files
   struct inode *cwd;        // Current directory
-  struct context context;   // Switch here to run process
-  struct trapframe *tf;     // Trap frame for current interrupt
+  struct context *context;  // Switch here to run process
+  struct trapframe *tf;     // Trap frame for current syscall
   char name[16];            // Process name (debugging)
 };
 
@@ -53,7 +49,7 @@ struct proc {
 struct cpu {
   uchar apicid;               // Local APIC ID
   struct proc *curproc;       // Process currently running.
-  struct context context;     // Switch here to enter scheduler
+  struct context *context;    // Switch here to enter scheduler
   struct taskstate ts;        // Used by x86 to find stack for interrupt
   struct segdesc gdt[NSEGS];  // x86 global descriptor table
   volatile uint booted;        // Has the CPU started?
diff --git a/swtch.S b/swtch.S
index 786e9ac..ada98f3 100644
--- a/swtch.S
+++ b/swtch.S
@@ -1,32 +1,26 @@
-#   void swtch(struct context *old, struct context *new);
+#   void swtch(struct context **old, struct context **new);
 #  
 # Save current register context in old
 # and then load register context from new.
 
 .globl swtch
 swtch:
-  # Save old registers
   movl 4(%esp), %eax
+  movl 8(%esp), %edx
 
-  popl 0(%eax)  # %eip
-  movl %esp, 4(%eax)
-  movl %ebx, 8(%eax)
-  movl %ecx, 12(%eax)
-  movl %edx, 16(%eax)
-  movl %esi, 20(%eax)
-  movl %edi, 24(%eax)
-  movl %ebp, 28(%eax)
+  # Save old callee-save registers
+  pushl %ebp
+  pushl %ebx
+  pushl %esi
+  pushl %edi
 
-  # Load new registers
-  movl 4(%esp), %eax  # not 8(%esp) - popped return address above
-
-  movl 28(%eax), %ebp
-  movl 24(%eax), %edi
-  movl 20(%eax), %esi
-  movl 16(%eax), %edx
-  movl 12(%eax), %ecx
-  movl 8(%eax), %ebx
-  movl 4(%eax), %esp
-  pushl 0(%eax)  # %eip
+  # Switch stacks
+  movl %esp, (%eax)
+  movl (%edx), %esp
 
+  # Load new callee-save registers
+  popl %edi
+  popl %esi
+  popl %ebx
+  popl %ebp
   ret
-- 
GitLab