Messages in this thread Patch in this message | | | Date | Sat, 04 Jan 2003 17:01:04 -0800 | From | Andrew Morton <> | Subject | Re: [BENCHMARK] Lmbench 2.5.54-mm2 (impressive improvements) |
| |
Andi Kleen wrote: > > P.S.: regarding recent lmbench slow downs: I'm a bit > worried about the two wrmsrs which are in the i386 context switch > in load_esp0 for sysenter now. Last time I benchmarked WRMSRs on > Athlon they were really slow and knowing the P4 it is probably > even slower there. Imho it would be better to undo that patch > and use Linus' original trampoline stack. >
Looks like you're right. The indications are that this change has slowed context switches by ~5% on a PIII. The backout patch against 2.5.54 is below. Testing on a P4 would be useful.
2.5.54, stock:
lmbench:
Context switching - times in microseconds - smaller is better ------------------------------------------------------------- Host OS 2p/0K 2p/16K 2p/64K 8p/16K 8p/64K 16p/16K 16p/64K ctxsw ctxsw ctxsw ctxsw ctxsw ctxsw ctxsw --------- ------------- ----- ------ ------ ------ ------ ------- ------- i686-linu Linux 2.5.54 3 16 44 18 47 20 77
*Local* Communication latencies in microseconds - smaller is better ------------------------------------------------------------------- Host OS 2p/0K Pipe AF UDP RPC/ TCP RPC/ TCP ctxsw UNIX UDP TCP conn --------- ------------- ----- ----- ---- ----- ----- ----- ----- ---- i686-linu Linux 2.5.54 3 16 26 65 78 231
AIM9:
3 tcp_test 10.00 2767 276.70000 24903.00 TCP/IP Messages/second 4 udp_test 10.00 4658 465.80000 46580.00 UDP/IP DataGrams/second 5 fifo_test 10.01 6507 650.04995 65005.00 FIFO Messages/second 6 dgram_pipe 10.00 11228 1122.80000 112280.00 DataGram Pipe Messages/second 7 pipe_cpy 10.00 15463 1546.30000 154630.00 Pipe Messages/second
pollbench: pollbench 1 100 5000 result with handles 1 processes 100 loops 5000:time 9.609487 sec. pollbench 2 100 2000 result with handles 2 processes 100 loops 2000:time 4.016496 sec. pollbench 5 100 2000 result with handles 5 processes 100 loops 2000:time 4.917921 sec.
2.5.54, with the below backout patch:
Context switching - times in microseconds - smaller is better ------------------------------------------------------------- Host OS 2p/0K 2p/16K 2p/64K 8p/16K 8p/64K 16p/16K 16p/64K ctxsw ctxsw ctxsw ctxsw ctxsw ctxsw ctxsw --------- ------------- ----- ------ ------ ------ ------ ------- ------- i686-linu Linux 2.5.54 3 14 47 18 50 20 61
*Local* Communication latencies in microseconds - smaller is better ------------------------------------------------------------------- Host OS 2p/0K Pipe AF UDP RPC/ TCP RPC/ TCP ctxsw UNIX UDP TCP conn --------- ------------- ----- ----- ---- ----- ----- ----- ----- ---- i686-linu Linux 2.5.54 3 15 25 64 69 231
3 tcp_test 10.00 2908 290.80000 26172.00 TCP/IP Messages/second 4 udp_test 10.00 4971 497.10000 49710.00 UDP/IP DataGrams/second 5 fifo_test 10.01 6642 663.53646 66353.65 FIFO Messages/second 6 dgram_pipe 10.00 11516 1151.60000 115160.00 DataGram Pipe Messages/second 7 pipe_cpy 10.00 15930 1593.00000 159300.00 Pipe Messages/second
pollbench 1 100 5000 result with handles 1 processes 100 loops 5000:time 9.106732 sec. pollbench 2 100 2000 result with handles 2 processes 100 loops 2000:time 3.853814 sec. pollbench 5 100 2000 result with handles 5 processes 100 loops 2000:time 4.533519 sec.
arch/i386/kernel/cpu/common.c | 2 +- arch/i386/kernel/process.c | 2 +- arch/i386/kernel/sysenter.c | 34 ++++++++++++++++++++++++++++++---- arch/i386/kernel/vm86.c | 4 +--- include/asm-i386/cpufeature.h | 3 --- include/asm-i386/msr.h | 4 ---- include/asm-i386/processor.h | 16 ---------------- 7 files changed, 33 insertions(+), 32 deletions(-)
--- 25/arch/i386/kernel/cpu/common.c~bad3 Fri Jan 3 16:36:48 2003 +++ 25-akpm/arch/i386/kernel/cpu/common.c Fri Jan 3 16:36:48 2003 @@ -484,7 +484,7 @@ void __init cpu_init (void) BUG(); enter_lazy_tlb(&init_mm, current, cpu); - load_esp0(t, thread->esp0); + t->esp0 = thread->esp0; set_tss_desc(cpu,t); cpu_gdt_table[cpu][GDT_ENTRY_TSS].b &= 0xfffffdff; load_TR_desc(); --- 25/arch/i386/kernel/process.c~bad3 Fri Jan 3 16:36:48 2003 +++ 25-akpm/arch/i386/kernel/process.c Fri Jan 3 16:36:48 2003 @@ -437,7 +437,7 @@ void __switch_to(struct task_struct *pre /* * Reload esp0, LDT and the page table pointer: */ - load_esp0(tss, next->esp0); + tss->esp0 = next->esp0; /* * Load the per-thread Thread-Local Storage descriptor. --- 25/arch/i386/kernel/sysenter.c~bad3 Fri Jan 3 16:36:48 2003 +++ 25-akpm/arch/i386/kernel/sysenter.c Fri Jan 3 16:36:48 2003 @@ -34,14 +34,40 @@ struct fake_sep_struct { unsigned char stack[0]; } __attribute__((aligned(8192))); +static struct fake_sep_struct *alloc_sep_thread(int cpu) +{ + struct fake_sep_struct *entry; + + entry = (struct fake_sep_struct *) __get_free_pages(GFP_ATOMIC, 1); + if (!entry) + return NULL; + + memset(entry, 0, PAGE_SIZE<<1); + entry->thread.task = &entry->task; + entry->task.thread_info = &entry->thread; + entry->thread.preempt_count = 1; + entry->thread.cpu = cpu; + + return entry; +} + static void __init enable_sep_cpu(void *info) { int cpu = get_cpu(); - struct tss_struct *tss = init_tss + cpu; + struct fake_sep_struct *sep = alloc_sep_thread(cpu); + unsigned long *esp0_ptr = &(init_tss + cpu)->esp0; + unsigned long rel32; + + rel32 = (unsigned long) sysenter_entry - (unsigned long) (sep->trampoline+11); + + *(short *) (sep->trampoline+0) = 0x258b; /* movl xxxxx,%esp */ + *(long **) (sep->trampoline+2) = esp0_ptr; + *(char *) (sep->trampoline+6) = 0xe9; /* jmp rl32 */ + *(long *) (sep->trampoline+7) = rel32; - wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); - wrmsr(MSR_IA32_SYSENTER_ESP, tss->esp0, 0); - wrmsr(MSR_IA32_SYSENTER_EIP, (unsigned long) sysenter_entry, 0); + wrmsr(0x174, __KERNEL_CS, 0); /* SYSENTER_CS_MSR */ + wrmsr(0x175, PAGE_SIZE*2 + (unsigned long) sep, 0); /* SYSENTER_ESP_MSR */ + wrmsr(0x176, (unsigned long) &sep->trampoline, 0); /* SYSENTER_EIP_MSR */ printk("Enabling SEP on CPU %d\n", cpu); put_cpu(); --- 25/arch/i386/kernel/vm86.c~bad3 Fri Jan 3 16:36:48 2003 +++ 25-akpm/arch/i386/kernel/vm86.c Fri Jan 3 16:36:48 2003 @@ -113,8 +113,7 @@ struct pt_regs * save_v86_state(struct k do_exit(SIGSEGV); } tss = init_tss + smp_processor_id(); - current->thread.esp0 = current->thread.saved_esp0; - load_esp0(tss, current->thread.esp0); + tss->esp0 = current->thread.esp0 = current->thread.saved_esp0; current->thread.saved_esp0 = 0; loadsegment(fs, current->thread.saved_fs); loadsegment(gs, current->thread.saved_gs); @@ -290,7 +289,6 @@ static void do_sys_vm86(struct kernel_vm tss = init_tss + smp_processor_id(); tss->esp0 = tsk->thread.esp0 = (unsigned long) &info->VM86_TSS_ESP0; - disable_sysenter(); tsk->thread.screen_bitmap = info->screen_bitmap; if (info->flags & VM86_SCREEN_BITMAP) --- 25/include/asm-i386/cpufeature.h~bad3 Fri Jan 3 16:36:48 2003 +++ 25-akpm/include/asm-i386/cpufeature.h Fri Jan 3 16:36:48 2003 @@ -7,8 +7,6 @@ #ifndef __ASM_I386_CPUFEATURE_H #define __ASM_I386_CPUFEATURE_H -#include <linux/bitops.h> - #define NCAPINTS 4 /* Currently we have 4 32-bit words worth of info */ /* Intel-defined CPU features, CPUID level 0x00000001, word 0 */ @@ -77,7 +75,6 @@ #define cpu_has_pge boot_cpu_has(X86_FEATURE_PGE) #define cpu_has_sse2 boot_cpu_has(X86_FEATURE_XMM2) #define cpu_has_apic boot_cpu_has(X86_FEATURE_APIC) -#define cpu_has_sep boot_cpu_has(X86_FEATURE_SEP) #define cpu_has_mtrr boot_cpu_has(X86_FEATURE_MTRR) #define cpu_has_mmx boot_cpu_has(X86_FEATURE_MMX) #define cpu_has_fxsr boot_cpu_has(X86_FEATURE_FXSR) --- 25/include/asm-i386/msr.h~bad3 Fri Jan 3 16:36:48 2003 +++ 25-akpm/include/asm-i386/msr.h Fri Jan 3 16:36:48 2003 @@ -53,10 +53,6 @@ #define MSR_IA32_BBL_CR_CTL 0x119 -#define MSR_IA32_SYSENTER_CS 0x174 -#define MSR_IA32_SYSENTER_ESP 0x175 -#define MSR_IA32_SYSENTER_EIP 0x176 - #define MSR_IA32_MCG_CAP 0x179 #define MSR_IA32_MCG_STATUS 0x17a #define MSR_IA32_MCG_CTL 0x17b --- 25/include/asm-i386/processor.h~bad3 Fri Jan 3 16:36:48 2003 +++ 25-akpm/include/asm-i386/processor.h Fri Jan 3 16:36:48 2003 @@ -14,7 +14,6 @@ #include <asm/types.h> #include <asm/sigcontext.h> #include <asm/cpufeature.h> -#include <asm/msr.h> #include <linux/cache.h> #include <linux/config.h> #include <linux/threads.h> @@ -411,21 +410,6 @@ struct thread_struct { .io_bitmap = { [ 0 ... IO_BITMAP_SIZE ] = ~0 }, \ } -static inline void load_esp0(struct tss_struct *tss, unsigned long esp0) -{ - tss->esp0 = esp0; - if (cpu_has_sep) { - wrmsr(MSR_IA32_SYSENTER_CS, __KERNEL_CS, 0); - wrmsr(MSR_IA32_SYSENTER_ESP, esp0, 0); - } -} - -static inline void disable_sysenter(void) -{ - if (cpu_has_sep) - wrmsr(MSR_IA32_SYSENTER_CS, 0, 0); -} - #define start_thread(regs, new_eip, new_esp) do { \ __asm__("movl %0,%%fs ; movl %0,%%gs": :"r" (0)); \ set_fs(USER_DS); \ _ - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |