Fixed bug in sysenter/sysexit
authorKevin Klues <klueska@ros-dev.(none)>
Wed, 24 Mar 2010 07:18:22 +0000 (00:18 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Thu, 3 Nov 2011 00:35:37 +0000 (17:35 -0700)
Registers ecx and edx are (intentionally) clobbered by sysexit code.
However, the sysenter implementation does not assume this, leading
to incorrect code generation.  We now push them to the stack before
sysenter.

A better implementation would simply add them to the clobber list,
but the lack of GPRs in x86 made glibc compilation encounter register
allocation failures using this approach.

kern/arch/i686/ros/syscall.h

index 46fd488..0535ed3 100644 (file)
@@ -14,19 +14,22 @@ static inline intreg_t syscall_sysenter(uint16_t num, intreg_t a1,
                                  intreg_t a2, intreg_t a3,
                                  intreg_t a4, intreg_t a5)
 {
-       // TODO: Maybe think about this a little more.
-       // We just added code to push and pop 'ebx' because 
-       // when compiling glibc we were getting register allocation 
-       // errors.  Not happy with this, but it works.
+       // The kernel clobbers ecx and edx => put them in clobber list.
+       // ebx is handled specially because of a glibc register
+       // allocation problem (not enough registers).
        intreg_t ret;
        asm volatile ("  pushl %%ebp;        "
                      "  pushl %%esi;        "
                      "  pushl %%ebx;        "
+                     "  pushl %%ecx;        "
+                     "  pushl %%edx;        "
                      "  movl %%esp, %%ebp;  "
                      "  movl %4, %%ebx;     "
                      "  leal 1f, %%esi;     "
                      "  sysenter;           "
                      "1:                    "
+                     "  popl %%edx;         "
+                     "  popl %%ecx;         "
                      "  popl %%ebx;         "
                      "  popl %%esi;         "
                      "  popl %%ebp;         "