[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] Slightly disgusting hack to avoid using lots of lock instructions on a uniprocessor



ChangeSet 1.1713.1.13, 2005/06/16 12:44:16+01:00, sos22@xxxxxxxxxxxxxxxxxxxx

        Slightly disgusting hack to avoid using lots of lock instructions on a 
uniprocessor
        machine just because we happened to compile with CONFIG_SMP.  
Essentially, we
        make a big table of all of the instruction sequences which differ in 
``easy''
        ways between UP and SMP kernels, and then select which one to use at 
run time.
        
        Signed-off-by: Steven Smith <sos22@xxxxxxxxx>



 linux-2.6.11-xen-sparse/arch/xen/i386/Kconfig             |   13 
 linux-2.6.11-xen-sparse/arch/xen/i386/kernel/Makefile     |    1 
 linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c    |   17 
 linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/system.h |   57 ++
 patches/linux-2.6.11/smp-alts.patch                       |  302 ++++++++++++++
 5 files changed, 384 insertions(+), 6 deletions(-)


diff -Nru a/linux-2.6.11-xen-sparse/arch/xen/i386/Kconfig 
b/linux-2.6.11-xen-sparse/arch/xen/i386/Kconfig
--- a/linux-2.6.11-xen-sparse/arch/xen/i386/Kconfig     2005-06-17 21:02:25 
-04:00
+++ b/linux-2.6.11-xen-sparse/arch/xen/i386/Kconfig     2005-06-17 21:02:25 
-04:00
@@ -372,6 +372,19 @@
 
          If you don't know what to do here, say N.
 
+config SMP_ALTERNATIVES
+        bool "SMP alternatives support (EXPERIMENTAL)"
+        depends on SMP && EXPERIMENTAL
+        help
+          Try to reduce the overhead of running an SMP kernel on a uniprocessor
+          host slightly by replacing certain key instruction sequences
+          according to whether we currently have more than one CPU available.
+          This should provide a noticeable boost to performance when
+          running SMP kernels on UP machines, and have negligible impact
+          when running on an true SMP host.
+
+          If unsure, say N.
+
 config NR_CPUS
        int "Maximum number of CPUs (2-255)"
        range 2 255
diff -Nru a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/Makefile 
b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/Makefile
--- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/Makefile     2005-06-17 
21:02:25 -04:00
+++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/Makefile     2005-06-17 
21:02:25 -04:00
@@ -42,6 +42,7 @@
 c-obj-$(CONFIG_HPET_TIMER)     += time_hpet.o
 c-obj-$(CONFIG_EFI)            += efi.o efi_stub.o
 c-obj-$(CONFIG_EARLY_PRINTK)   += early_printk.o
+c-obj-$(CONFIG_SMP_ALTERNATIVES)+= smpalts.o
 
 EXTRA_AFLAGS   := -traditional
 
diff -Nru a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c 
b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c
--- a/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c    2005-06-17 
21:02:25 -04:00
+++ b/linux-2.6.11-xen-sparse/arch/xen/i386/kernel/smpboot.c    2005-06-17 
21:02:25 -04:00
@@ -54,6 +54,8 @@
 #include <asm/desc.h>
 #include <asm/arch_hooks.h>
 
+#include <asm/smp_alt.h>
+
 #ifndef CONFIG_X86_IO_APIC
 #define Dprintk(args...)
 #endif
@@ -1186,6 +1188,10 @@
                if (max_cpus <= cpucount+1)
                        continue;
 
+#ifdef CONFIG_SMP_ALTERNATIVES
+               if (kicked == 1)
+                       prepare_for_smp();
+#endif
                if (do_boot_cpu(cpu))
                        printk("CPU #%d not responding - cannot use it.\n",
                                                                cpu);
@@ -1301,6 +1307,11 @@
 /* must be called with the cpucontrol mutex held */
 static int __devinit cpu_enable(unsigned int cpu)
 {
+#ifdef CONFIG_SMP_ALTERNATIVES
+       if (num_online_cpus() == 1)
+               prepare_for_smp();
+#endif
+
        /* get the target out of its holding state */
        per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
        wmb();
@@ -1340,6 +1351,12 @@
        fixup_irqs(map);
        /* It's now safe to remove this processor from the online map */
        cpu_clear(cpu, cpu_online_map);
+
+#ifdef CONFIG_SMP_ALTERNATIVES
+       if (num_online_cpus() == 1)
+               unprepare_for_smp();
+#endif
+
        return 0;
 }
 
diff -Nru a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/system.h 
b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/system.h
--- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/system.h 2005-06-17 
21:02:25 -04:00
+++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/system.h 2005-06-17 
21:02:25 -04:00
@@ -8,6 +8,7 @@
 #include <asm/segment.h>
 #include <asm/cpufeature.h>
 #include <asm-xen/hypervisor.h>
+#include <asm/smp_alt.h>
 
 #ifdef __KERNEL__
 
@@ -251,19 +252,19 @@
        unsigned long prev;
        switch (size) {
        case 1:
-               __asm__ __volatile__(LOCK_PREFIX "cmpxchgb %b1,%2"
+               __asm__ __volatile__(LOCK "cmpxchgb %b1,%2"
                                     : "=a"(prev)
                                     : "q"(new), "m"(*__xg(ptr)), "0"(old)
                                     : "memory");
                return prev;
        case 2:
-               __asm__ __volatile__(LOCK_PREFIX "cmpxchgw %w1,%2"
+               __asm__ __volatile__(LOCK "cmpxchgw %w1,%2"
                                     : "=a"(prev)
                                     : "q"(new), "m"(*__xg(ptr)), "0"(old)
                                     : "memory");
                return prev;
        case 4:
-               __asm__ __volatile__(LOCK_PREFIX "cmpxchgl %1,%2"
+               __asm__ __volatile__(LOCK "cmpxchgl %1,%2"
                                     : "=a"(prev)
                                     : "q"(new), "m"(*__xg(ptr)), "0"(old)
                                     : "memory");
@@ -427,11 +428,55 @@
 #endif
 
 #ifdef CONFIG_SMP
-#define smp_mb()       mb()
-#define smp_rmb()      rmb()
 #define smp_wmb()      wmb()
-#define smp_read_barrier_depends()     read_barrier_depends()
+#if defined(CONFIG_SMP_ALTERNATIVES) && !defined(MODULE)
+#define smp_alt_mb(instr)                                           \
+__asm__ __volatile__("6667:\nnop\nnop\nnop\nnop\nnop\nnop\n6668:\n" \
+                    ".section __smp_alternatives,\"a\"\n"          \
+                    ".long 6667b\n"                                \
+                     ".long 6673f\n"                                \
+                    ".previous\n"                                  \
+                    ".section __smp_replacements,\"a\"\n"          \
+                    "6673:.byte 6668b-6667b\n"                     \
+                    ".byte 6670f-6669f\n"                          \
+                    ".byte 6671f-6670f\n"                          \
+                     ".byte 0\n"                                    \
+                    ".byte %c0\n"                                  \
+                    "6669:lock;addl $0,0(%%esp)\n"                 \
+                    "6670:" instr "\n"                             \
+                    "6671:\n"                                      \
+                    ".previous\n"                                  \
+                    :                                              \
+                    : "i" (X86_FEATURE_XMM2)                       \
+                    : "memory")
+#define smp_rmb() smp_alt_mb("lfence")
+#define smp_mb()  smp_alt_mb("mfence")
+#define set_mb(var, value) do {                                     \
+unsigned long __set_mb_temp;                                        \
+__asm__ __volatile__("6667:movl %1, %0\n6668:\n"                    \
+                    ".section __smp_alternatives,\"a\"\n"          \
+                    ".long 6667b\n"                                \
+                    ".long 6673f\n"                                \
+                    ".previous\n"                                  \
+                    ".section __smp_replacements,\"a\"\n"          \
+                    "6673: .byte 6668b-6667b\n"                    \
+                    ".byte 6670f-6669f\n"                          \
+                    ".byte 0\n"                                    \
+                    ".byte 6671f-6670f\n"                          \
+                    ".byte -1\n"                                   \
+                    "6669: xchg %1, %0\n"                          \
+                    "6670:movl %1, %0\n"                           \
+                    "6671:\n"                                      \
+                    ".previous\n"                                  \
+                    : "=m" (var), "=r" (__set_mb_temp)             \
+                    : "1" (value)                                  \
+                    : "memory"); } while (0)
+#else
+#define smp_rmb()      rmb()
+#define smp_mb()       mb()
 #define set_mb(var, value) do { xchg(&var, value); } while (0)
+#endif
+#define smp_read_barrier_depends()     read_barrier_depends()
 #else
 #define smp_mb()       barrier()
 #define smp_rmb()      barrier()
diff -Nru a/patches/linux-2.6.11/smp-alts.patch 
b/patches/linux-2.6.11/smp-alts.patch
--- /dev/null   Wed Dec 31 16:00:00 196900
+++ b/patches/linux-2.6.11/smp-alts.patch       2005-06-17 21:02:25 -04:00
@@ -0,0 +1,554 @@
+diff -Naur linux-2.6.11/arch/i386/Kconfig linux-2.6.11.post/arch/i386/Kconfig
+--- linux-2.6.11/arch/i386/Kconfig     2005-03-02 07:37:49.000000000 +0000
++++ linux-2.6.11.post/arch/i386/Kconfig        2005-06-10 13:42:35.000000000 
+0100
+@@ -481,6 +481,19 @@
+ 
+         If you don't know what to do here, say N.
+ 
++config SMP_ALTERNATIVES
++      bool "SMP alternatives support (EXPERIMENTAL)"
++      depends on SMP && EXPERIMENTAL
++      help
++        Try to reduce the overhead of running an SMP kernel on a uniprocessor
++        host slightly by replacing certain key instruction sequences
++        according to whether we currently have more than one CPU available.
++        This should provide a noticeable boost to performance when
++        running SMP kernels on UP machines, and have negligible impact
++        when running on an true SMP host.
++
++          If unsure, say N.
++        
+ config NR_CPUS
+       int "Maximum number of CPUs (2-255)"
+       range 2 255
+diff -Naur linux-2.6.11/arch/i386/kernel/Makefile 
linux-2.6.11.post/arch/i386/kernel/Makefile
+--- linux-2.6.11/arch/i386/kernel/Makefile     2005-03-02 07:37:49.000000000 
+0000
++++ linux-2.6.11.post/arch/i386/kernel/Makefile        2005-06-16 
11:16:18.555332435 +0100
+@@ -32,6 +32,7 @@
+ obj-$(CONFIG_HPET_TIMER)      += time_hpet.o
+ obj-$(CONFIG_EFI)             += efi.o efi_stub.o
+ obj-$(CONFIG_EARLY_PRINTK)    += early_printk.o
++obj-$(CONFIG_SMP_ALTERNATIVES)  += smpalts.o
+ 
+ EXTRA_AFLAGS   := -traditional
+ 
+diff -Naur linux-2.6.11/arch/i386/kernel/smpalts.c 
linux-2.6.11.post/arch/i386/kernel/smpalts.c
+--- linux-2.6.11/arch/i386/kernel/smpalts.c    1970-01-01 01:00:00.000000000 
+0100
++++ linux-2.6.11.post/arch/i386/kernel/smpalts.c       2005-06-16 
11:23:39.300902424 +0100
+@@ -0,0 +1,76 @@
++#include <linux/kernel.h>
++#include <asm/system.h>
++#include <asm/smp_alt.h>
++#include <asm/processor.h>
++#include <asm/string.h>
++
++struct smp_replacement_record {
++      unsigned char targ_size;
++      unsigned char smp1_size;
++      unsigned char smp2_size;
++      unsigned char up_size;
++      unsigned char feature;
++      unsigned char data[0];
++};
++
++struct smp_alternative_record {
++      void *targ_start;
++      struct smp_replacement_record *repl;
++};
++
++extern struct smp_alternative_record __start_smp_alternatives_table,
++  __stop_smp_alternatives_table;
++
++void prepare_for_smp(void)
++{
++      struct smp_alternative_record *r;
++      printk(KERN_INFO "Enabling SMP...\n");
++      for (r = &__start_smp_alternatives_table;
++           r != &__stop_smp_alternatives_table;
++           r++) {
++              BUG_ON(r->repl->targ_size < r->repl->smp1_size);
++              BUG_ON(r->repl->targ_size < r->repl->smp2_size);
++              BUG_ON(r->repl->targ_size < r->repl->up_size);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.