Re: [PATCH] i386-pda UP optimization

From: Eric Dumazet
Date: Wed Nov 15 2006 - 12:46:45 EST


On Wednesday 15 November 2006 18:24, Andi Kleen wrote:
> On Wednesday 15 November 2006 18:20, Ingo Molnar wrote:
> > * Andi Kleen <ak@xxxxxxx> wrote:
> > > On Wednesday 15 November 2006 12:27, Eric Dumazet wrote:
> > > > Seeing %gs prefixes used now by i386 port, I recalled seeing strange
> > > > oprofile results on Opteron machines.
> > > >
> > > > I really think %gs prefixes can be expensive in some (most ?) cases,
> > > > even if the Intel/AMD docs say they are free.
> > >
> > > They aren't free, just very cheap.
> >
> > Eric's test shows a 5% slowdown. That's far from cheap.
>
> I have my doubts about the accuracy of his test results. That is why I
> asked him to double check.

Fair enough :)

I plan doing *lot* of tests as soon as possible (not possible during daytime
unfortunately, I miss a dev machine)

By the way, I tried this patch to avoid reload %gs at syscall start. Since %gs
is not anymore used inside kernel (after i386-pda UP optimization is
applied) : We can let in %gs the User Program %gs value. (I still force a
reload of %gs before syscall exit of course)

Machine boots but freeze when init starts. Any idea ?

Thank you
Eric
--- linux-2.6.19-rc5-mm2/arch/i386/kernel/entry.S 2006-11-15 11:21:25.000000000 +0100
+++ linux-2.6.19-rc5-mm2-ed/arch/i386/kernel/entry.S 2006-11-15 18:40:53.000000000 +0100
@@ -97,6 +97,16 @@
#define resume_userspace_sig resume_userspace
#endif

+/*
+ * On UP, we dont need to change %gs since PDA accesses dont use %gs
+ */
+#if defined(CONFIG_SMP)
+#define LOAD_KERNEL_GS(reg) movl $(__KERNEL_PDA), reg; \
+ movl reg, %gs
+#else
+#define LOAD_KERNEL_GS(reg)
+#endif
+
#define SAVE_ALL \
cld; \
pushl %gs; \
@@ -132,8 +142,7 @@
movl $(__USER_DS), %edx; \
movl %edx, %ds; \
movl %edx, %es; \
- movl $(__KERNEL_PDA), %edx; \
- movl %edx, %gs
+ LOAD_KERNEL_GS(%edx);

#define RESTORE_INT_REGS \
popl %ebx; \
@@ -544,9 +553,15 @@
jmp resume_userspace
CFI_ENDPROC

+#ifdef CONFIG_SMP
+# define GET_CPU_NUM(reg) movl %gs:PDA_cpu, reg;
+#else
+# define GET_CPU_NUM(reg)
+#endif
+
#define FIXUP_ESPFIX_STACK \
/* since we are on a wrong stack, we cant make it a C code :( */ \
- movl %gs:PDA_cpu, %ebx; \
+ GET_CPU_NUM(%ebx) \
PER_CPU(cpu_gdt_descr, %ebx); \
movl GDS_address(%ebx), %ebx; \
GET_DESC_BASE(GDT_ENTRY_ESPFIX_SS, %ebx, %eax, %ax, %al, %ah); \
@@ -660,8 +675,7 @@
pushl %gs
CFI_ADJUST_CFA_OFFSET 4
/*CFI_REL_OFFSET gs, 0*/
- movl $(__KERNEL_PDA), %ecx
- movl %ecx, %gs
+ LOAD_KERNEL_GS(%ecx)
UNWIND_ESPFIX_STACK
popl %ecx
CFI_ADJUST_CFA_OFFSET -4