[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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |