x86: fix switch_to() clobbers
authorIngo Molnar <mingo@elte.hu>
Wed, 5 Mar 2008 09:46:38 +0000 (10:46 +0100)
committerIngo Molnar <mingo@elte.hu>
Thu, 17 Apr 2008 15:40:52 +0000 (17:40 +0200)
Liu Pingfan noticed that switch_to() clobbers more registers than its
asm constraints specify.

We get away with this due to luck mostly - schedule()
by its nature only has 'local' state which gets reloaded
automatically. Fix it nevertheless, we could hit this anytime.

it turns out that with the extra constraints gcc manages to make
schedule() even more compact:

   text    data     bss     dec     hex filename
  28626     684    2640   31950    7cce sched.o.before
  28613     684    2640   31937    7cc1 sched.o.after

Reported-by: Liu Pingfan <kernelfans@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
include/asm-x86/system.h

index 299ae9605cb1631f2a3f871213f2455f5173dd3e..33b0017156a7fae07db3f80a62b3b14afd4e95ec 100644 (file)
@@ -29,7 +29,14 @@ struct task_struct *__switch_to(struct task_struct *prev,
  */
 #define switch_to(prev, next, last)                                    \
 do {                                                                   \
-       unsigned long esi, edi;                                         \
+       /*                                                              \
+        * Context-switching clobbers all registers, so we clobber      \
+        * them explicitly, via unused output variables.                \
+        * (EAX and EBP is not listed because EBP is saved/restored     \
+        * explicitly for wchan access and EAX is the return value of   \
+        * __switch_to())                                               \
+        */                                                             \
+       unsigned long ebx, ecx, edx, esi, edi;                          \
                                                                        \
        asm volatile(                                                   \
                "pushfl                 \n\t"   /* save    flags */     \
@@ -49,6 +56,7 @@ do {                                                                  \
                            "=a" (last),                                \
                                                                        \
                  /* clobbered output registers: */                     \
+                 "=b" (ebx), "=c" (ecx), "=d" (edx),                   \
                  "=S" (esi), "=D" (edi)                                \
                                                                        \
                  /* input parameters: */                               \