Fixed up sysenter/sysexit semantics to allow another environment to be run on exit
authorKevin Klues <klueska@eecs.berkeley.edu>
Sat, 27 Jun 2009 04:05:03 +0000 (21:05 -0700)
committerKevin Klues <klueska@eecs.berkeley.edu>
Sat, 27 Jun 2009 04:05:03 +0000 (21:05 -0700)
Looking at the diff files it should be fairly obvious what was done.  Also, I fixed up some errors we had in the 'ifdefs' for SERIAL_IO in console.c

include/env.h
kern/src/console.c
kern/src/env.c
kern/src/syscall.c
user/parlib/src/syscall.c

index 7efc56a..b21e66f 100644 (file)
@@ -26,6 +26,8 @@ int   envid2env(envid_t envid, env_t **env_store, bool checkperm);
 // The following two functions do not return
 void   (IN_HANDLER env_run)(env_t *e) __attribute__((noreturn));
 void   env_pop_tf(trapframe_t *tf) __attribute__((noreturn));
+void   env_pop_tf_sysexit(trapframe_t *tf) __attribute__((noreturn));
+
 
 /* Helper handler for smp_call to dispatch jobs to other cores */
 void run_env_handler(trapframe_t *tf, void* data);
index 6e50ca9..5cdfc14 100644 (file)
@@ -526,7 +526,9 @@ cons_getc(void)
 void
 cons_putc(int c)
 {
-       serial_putc(c);
+       #ifndef SERIAL_IO
+               serial_putc(c);
+       #endif
        //lpt_putc(c);
        cga_putc(c);
 }
@@ -537,9 +539,7 @@ cons_init(void)
 {
        cga_init();
        kbd_init();
-       #ifndef SERIAL_IO
-               serial_init();
-       #endif
+       serial_init();
 
        if (!serial_exists)
                cprintf("Serial port does not exist!\n");
index 8e0805a..f0d09e5 100644 (file)
@@ -578,19 +578,34 @@ env_destroy(env_t *e)
 // This exits the kernel and starts executing some environment's code.
 // This function does not return.
 //
-void
-env_pop_tf(trapframe_t *tf)
+void env_pop_tf(trapframe_t *tf)
 {
-       __asm __volatile("movl %0,%%esp\n"
-               "\tpopal\n"
-               "\tpopl %%es\n"
-               "\tpopl %%ds\n"
-               "\taddl $0x8,%%esp\n" /* skip tf_trapno and tf_errcode */
-               "\tiret"
-               : : "g" (tf) : "memory");
+       __asm __volatile(
+           "movl %0,%%esp\n"
+           "\tpopal\n"
+           "\tpopl %%es\n"
+           "\tpopl %%ds\n"
+           "\taddl $0x8,%%esp\n" /* skip tf_trapno and tf_errcode */
+           "\tiret"
+           : : "g" (tf) : "memory");
        panic("iret failed");  /* mostly to placate the compiler */
 }
 
+
+void env_pop_tf_sysexit(trapframe_t *tf)
+{
+       __asm __volatile(
+           "movl %0,%%esp\n"
+           "\tpopal\n"
+           "\tpopl %%es\n"
+           "\tpopl %%ds\n"
+           "\tmovl %%ebp, %%ecx\n"
+           "\tmovl %%esi, %%edx\n"
+           "\tsysexit"
+           : : "g" (tf) : "memory");
+       panic("sysexit failed");  /* mostly to placate the compiler */
+}
+
 //
 // Context switch from curenv to env e.
 // Note: if this is the first call to env_run, curenv is NULL.
@@ -619,8 +634,26 @@ env_run(env_t *e)
                curenvs[lapic_get_id()] = e;
                e->env_runs++;
                lcr3(e->env_cr3);
+               
+               #ifndef SYSCALL_TRAP
+                       // The first time through we need to set up 
+                       // ebp and esi because there is no corresponding 
+                       // sysenter call and we have not set them up yet
+                       // for use by the env_pop_tf_sysexit() call that 
+                       // follows
+                       if(e->env_runs == 1) {
+                               e->env_tf.tf_regs.reg_ebp = e->env_tf.tf_esp;
+                               e->env_tf.tf_regs.reg_esi = e->env_tf.tf_eip;
+                       }
+               #endif
+
        }
-    env_pop_tf(&e->env_tf);
+       
+       #ifndef SYSCALL_TRAP
+               env_pop_tf_sysexit(&e->env_tf);
+       #else
+               env_pop_tf(&e->env_tf);
+       #endif
 }
 
 /* This is the top-half of an interrupt handler, where the bottom half is
index 87a38f5..0018394 100644 (file)
@@ -21,7 +21,10 @@ void syscall_wrapper(struct Trapframe *tf)
 {
        env_t* curenv = curenvs[lapic_get_id()];
     curenv->env_tf = *tf;
-    tf->tf_regs.reg_eax =
+       //Re enable interrupts. sysenter disables them.
+       enable_irq();
+       
+       curenv->env_tf.tf_regs.reg_eax =
            (intreg_t) syscall(curenv,
                               tf->tf_regs.reg_eax,
                               tf->tf_regs.reg_edx,
@@ -29,7 +32,7 @@ void syscall_wrapper(struct Trapframe *tf)
                               tf->tf_regs.reg_ebx,
                               tf->tf_regs.reg_edi,
                               0);
-    return;
+       env_run(curenv);
 }
 
 //Do absolutely nothing.  Used for profiling.
index d1fa775..cab3792 100644 (file)
@@ -12,26 +12,22 @@ static intreg_t syscall_sysenter(uint16_t num, intreg_t a1,
                                  intreg_t a4, intreg_t a5)
 {
        intreg_t ret;
-    asm volatile(
-            //"pushl %%ecx\n\t"
-            //"pushl %%edx\n\t"
-            "pushl %%ebp\n\t"
-                       "pushl %%esi\n\t"
-            "movl %%esp, %%ebp\n\t"
-            "leal after_sysenter, %%esi\n\t"
-            "sysenter\n\t"
-            "after_sysenter:\n\t"
-                       "popl %%esi\n\t"
-            "popl %%ebp\n\t"
-            //"popl %%edx\n\t"
-            //"popl %%ecx"
-            :"=a" (ret)
-            : "a" (num),
-                "d" (a1),
-                "c" (a2),
-                "b" (a3),
-                "D" (a4)
-        : "cc", "memory", "%esp");
+       asm volatile(
+           "pushl %%ebp\n\t"
+           "pushl %%esi\n\t"
+           "movl %%esp, %%ebp\n\t"
+           "leal after_sysenter, %%esi\n\t"
+           "sysenter\n\t"
+           "after_sysenter:\n\t"
+           "\tpopl %%esi\n"
+           "\tpopl %%ebp\n"
+           :"=a" (ret)
+           : "a" (num),
+             "d" (a1),
+             "c" (a2),
+             "b" (a3),
+             "D" (a4)
+           : "cc", "memory", "%esp");
        return ret;
 }