linux/arch/x86/include/asm
Jeremy Fitzhardinge b4ecc12699 x86: Fix performance regression caused by paravirt_ops on native kernels
Xiaohui Xin and some other folks at Intel have been looking into what's
behind the performance hit of paravirt_ops when running native.

It appears that the hit is entirely due to the paravirtualized
spinlocks introduced by:

 | commit 8efcbab674
 | Date:   Mon Jul 7 12:07:51 2008 -0700
 |
 |     paravirt: introduce a "lock-byte" spinlock implementation

The extra call/return in the spinlock path is somehow
causing an increase in the cycles/instruction of somewhere around 2-7%
(seems to vary quite a lot from test to test).  The working theory is
that the CPU's pipeline is getting upset about the
call->call->locked-op->return->return, and seems to be failing to
speculate (though I haven't seen anything definitive about the precise
reasons).  This doesn't entirely make sense, because the performance
hit is also visible on unlock and other operations which don't involve
locked instructions.  But spinlock operations clearly swamp all the
other pvops operations, even though I can't imagine that they're
nearly as common (there's only a .05% increase in instructions
executed).

If I disable just the pv-spinlock calls, my tests show that pvops is
identical to non-pvops performance on native (my measurements show that
it is actually about .1% faster, but Xiaohui shows a .05% slowdown).

Summary of results, averaging 10 runs of the "mmperf" test, using a
no-pvops build as baseline:

		nopv		Pv-nospin	Pv-spin
CPU cycles	100.00%		99.89%		102.18%
instructions	100.00%		100.10%		100.15%
CPI		100.00%		99.79%		102.03%
cache ref	100.00%		100.84%		100.28%
cache miss	100.00%		90.47%		88.56%
cache miss rate	100.00%		89.72%		88.31%
branches	100.00%		99.93%		100.04%
branch miss	100.00%		103.66%		107.72%
branch miss rt	100.00%		103.73%		107.67%
wallclock	100.00%		99.90%		102.20%

The clear effect here is that the 2% increase in CPI is
directly reflected in the final wallclock time.

(The other interesting effect is that the more ops are
out of line calls via pvops, the lower the cache access
and miss rates.  Not too surprising, but it suggests that
the non-pvops kernel is over-inlined.  On the flipside,
the branch misses go up correspondingly...)

So, what's the fix?

Paravirt patching turns all the pvops calls into direct calls, so
_spin_lock etc do end up having direct calls.  For example, the compiler
generated code for paravirtualized _spin_lock is:

<_spin_lock+0>:		mov    %gs:0xb4c8,%rax
<_spin_lock+9>:		incl   0xffffffffffffe044(%rax)
<_spin_lock+15>:	callq  *0xffffffff805a5b30
<_spin_lock+22>:	retq

The indirect call will get patched to:
<_spin_lock+0>:		mov    %gs:0xb4c8,%rax
<_spin_lock+9>:		incl   0xffffffffffffe044(%rax)
<_spin_lock+15>:	callq <__ticket_spin_lock>
<_spin_lock+20>:	nop; nop		/* or whatever 2-byte nop */
<_spin_lock+22>:	retq

One possibility is to inline _spin_lock, etc, when building an
optimised kernel (ie, when there's no spinlock/preempt
instrumentation/debugging enabled).  That will remove the outer
call/return pair, returning the instruction stream to a single
call/return, which will presumably execute the same as the non-pvops
case.  The downsides arel 1) it will replicate the
preempt_disable/enable code at eack lock/unlock callsite; this code is
fairly small, but not nothing; and 2) the spinlock definitions are
already a very heavily tangled mass of #ifdefs and other preprocessor
magic, and making any changes will be non-trivial.

The other obvious answer is to disable pv-spinlocks.  Making them a
separate config option is fairly easy, and it would be trivial to
enable them only when Xen is enabled (as the only non-default user).
But it doesn't really address the common case of a distro build which
is going to have Xen support enabled, and leaves the open question of
whether the native performance cost of pv-spinlocks is worth the
performance improvement on a loaded Xen system (10% saving of overall
system CPU when guests block rather than spin).  Still it is a
reasonable short-term workaround.

[ Impact: fix pvops performance regression when running native ]

Analysed-by: "Xin Xiaohui" <xiaohui.xin@intel.com>
Analysed-by: "Li Xin" <xin.li@intel.com>
Analysed-by: "Nakajima Jun" <jun.nakajima@intel.com>
Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Acked-by: H. Peter Anvin <hpa@zytor.com>
Cc: Nick Piggin <npiggin@suse.de>
Cc: Xen-devel <xen-devel@lists.xensource.com>
LKML-Reference: <4A0B62F7.5030802@goop.org>
[ fixed the help text ]
Signed-off-by: Ingo Molnar <mingo@elte.hu>
2009-05-15 20:07:42 +02:00
..
uv x86: UV BAU messaging timeouts 2009-04-03 18:25:27 +02:00
visws
xen Xen: Add virt_to_pfn helper function 2009-04-08 11:51:46 -07:00
a.out-core.h x86: add %gs accessors for x86_32 2009-02-10 00:41:58 +01:00
a.out.h
acpi.h x86: use early_ioremap in __acpi_map_table 2009-02-09 13:33:51 +01:00
aes.h crypto: aes - Export x86 AES encrypt/decrypt functions 2009-02-18 16:48:05 +08:00
agp.h
alternative-asm.h
alternative.h
amd_iommu_types.h
amd_iommu.h
apic.h x2apic/intr-remap: decouple interrupt remapping from x2apic 2009-04-04 10:42:28 +01:00
apicdef.h x86, mce, cmci: define MSR names and fields for new CMCI registers 2009-02-24 13:41:00 -08:00
apicnum.h
apm.h x86: move mach-default/*.h files to asm/ 2009-01-29 14:16:51 +01:00
asm.h
atomic_32.h
atomic_64.h
atomic.h
auxvec.h
bios_ebda.h
bitops.h
boot.h x86: remove zImage support 2009-03-11 11:00:00 -07:00
bootparam.h
bug.h
bugs.h
byteorder.h
cache.h
cacheflush.h Merge branch 'tracing/core-v2' into tracing-for-linus 2009-04-02 00:49:02 +02:00
calgary.h
calling.h x86: document 64-bit and 32-bit function call convention ABI 2009-02-03 19:48:18 +01:00
checksum_32.h
checksum_64.h
checksum.h
cmpxchg_32.h
cmpxchg_64.h
cmpxchg.h
compat.h
cpu_debug.h x86: cpu_debug remove execute permission 2009-04-09 06:34:02 +02:00
cpu.h x86: generalize boot_cpu_id 2009-01-29 14:17:01 +01:00
cpufeature.h x86 ACPI: Add support for Always Running APIC timer 2009-04-07 18:17:51 -04:00
cpumask.h x86: unify cpu_callin_mask/cpu_callout_mask/cpu_initialized_mask/cpu_sibling_setup_mask 2009-03-13 14:49:54 +10:30
cputime.h
current.h
debugreg.h
delay.h
desc_defs.h
desc.h FRV: Fix the section attribute on UP DECLARE_PER_CPU() 2009-04-21 19:39:59 -07:00
device.h
div64.h
dma-mapping.h dma-mapping: replace all DMA_24BIT_MASK macro with DMA_BIT_MASK(24) 2009-04-07 08:31:12 -07:00
dma.h
dmi.h x86/dmi: fix dmi_alloc() section mismatches 2009-03-23 17:20:50 +01:00
do_timer.h x86: move mach-default/*.h files to asm/ 2009-01-29 14:16:51 +01:00
ds.h
dwarf2.h
e820.h x86: e820 fix various signedness issues in setup.c and e820.c 2009-03-23 15:02:05 +05:30
edac.h
efi.h x86: EFI: Back efi_ioremap with init_memory_mapping instead of FIX_MAP 2009-03-04 19:20:16 +01:00
elf.h x86: make lazy %gs optional on x86_32 2009-02-10 00:42:00 +01:00
emergency-restart.h
entry_arch.h x86: UV, SGI RTC: add generic system vector 2009-03-04 20:25:37 +01:00
errno.h
fb.h
fcntl.h
fixmap.h x86: fix set_fixmap to use phys_addr_t 2009-04-10 20:27:13 +02:00
floppy.h
frame.h
ftrace.h tracing/syscalls: support for syscalls tracing on x86 2009-03-13 16:57:42 +01:00
futex.h
gart.h
genapic.h x86, apic: merge genapic.h into apic.h 2009-02-17 17:52:43 +01:00
geode.h
gpio.h
hardirq.h FRV: Fix the section attribute on UP DECLARE_PER_CPU() 2009-04-21 19:39:59 -07:00
highmem.h x86: unify kmap_atomic_pfn() and iomap_atomic_prot_pfn() 2009-03-11 15:47:46 +01:00
hpet.h
hugetlb.h
hw_irq.h x86: UV, SGI RTC: add generic system vector 2009-03-04 20:25:37 +01:00
hypertransport.h
hypervisor.h
i387.h x86, math-emu: fix init_fpu for task != current 2009-03-04 20:33:16 +01:00
i8253.h
i8259.h x86: refactor x86_quirks support 2009-02-23 00:08:11 +01:00
ia32_unistd.h
ia32.h generic compat_sys_ustat 2009-03-27 14:43:57 -04:00
idle.h
init.h x86: move function and variable declarations to asm/init.h 2009-03-05 14:17:18 +01:00
intel_arch_perfmon.h
io_32.h Merge branches 'x86/acpi', 'x86/asm', 'x86/cpudetect', 'x86/crashdump', 'x86/debug', 'x86/defconfig', 'x86/doc', 'x86/header-fixes', 'x86/headers' and 'x86/minor-fixes' into x86/core 2009-02-13 09:46:36 +01:00
io_64.h Merge branches 'x86/acpi', 'x86/asm', 'x86/cpudetect', 'x86/crashdump', 'x86/debug', 'x86/defconfig', 'x86/doc', 'x86/header-fixes', 'x86/headers' and 'x86/minor-fixes' into x86/core 2009-02-13 09:46:36 +01:00
io_apic.h Intel IOMMU Suspend/Resume Support - Interrupt Remapping 2009-04-03 21:45:59 +01:00
io.h x86: fix set_fixmap to use phys_addr_t 2009-04-10 20:27:13 +02:00
ioctl.h
ioctls.h
iomap.h Revert "gpu/drm, x86, PAT: PAT support for io_mapping_*" 2009-03-01 12:47:49 +01:00
iommu.h
ipcbuf.h
ipi.h x86, apic: remove duplicate asm/apic.h inclusions 2009-02-17 17:52:44 +01:00
irq_regs.h
irq_remapping.h x86, x2apic: fix clear_local_APIC() in the presence of x2apic 2009-03-17 15:43:51 -07:00
irq_vectors.h x86: UV, SGI RTC: add generic system vector 2009-03-04 20:25:37 +01:00
irq.h x86: UV, SGI RTC: add generic system vector 2009-03-04 20:25:37 +01:00
irqflags.h
ist.h
k8.h
Kbuild
kdebug.h
kexec.h x86, kexec: x86_64: add kexec jump support for x86_64 2009-03-10 18:13:25 -07:00
kgdb.h
kmap_types.h
kprobes.h
kvm_host.h KVM: Report IRQ injection status to userspace. 2009-03-24 11:03:11 +02:00
kvm_para.h
kvm_x86_emulate.h
kvm.h KVM: Avoid using CONFIG_ in userspace visible headers 2009-03-24 11:03:06 +02:00
ldt.h
lguest_hcall.h lguest: fix guest crash on non-linear addresses in gdt pvops 2009-04-19 23:14:01 +09:30
lguest.h
linkage.h x86: shrink __ALIGN and __ALIGN_STR definitions 2009-03-11 12:39:28 +01:00
local.h
mach_timer.h x86: move mach-default/*.h files to asm/ 2009-01-29 14:16:51 +01:00
mach_traps.h x86: move mach-default/*.h files to asm/ 2009-01-29 14:16:51 +01:00
math_emu.h x86: fix math_emu register frame access 2009-02-10 00:39:14 +01:00
mc146818rtc.h
mca_dma.h
mca.h
mce.h x86, mce: fix boot logging logic 2009-04-22 13:56:25 -07:00
microcode.h
mman.h
mmconfig.h
mmu_context.h x86: make lazy %gs optional on x86_32 2009-02-10 00:42:00 +01:00
mmu.h
mmx.h
mmzone_32.h bootmem, x86: further fixes for arch-specific bootmem wrapping 2009-03-01 16:06:56 +09:00
mmzone_64.h mm: clean up for early_pfn_to_nid() 2009-02-18 15:37:55 -08:00
mmzone.h
module.h
mpspec_def.h
mpspec.h x86, numaq_32: clean up, misc 2009-02-17 17:53:54 +01:00
msgbuf.h
msidef.h x86, x2apic: enable fault handling for intr-remapping 2009-03-17 15:38:59 -07:00
msr-index.h Merge branch 'linus' into x86/core 2009-03-28 22:27:45 +01:00
msr.h
mtrr.h headers_check fix: x86, mtrr.h 2009-01-31 00:17:39 +05:30
mutex_32.h
mutex_64.h
mutex.h
nmi.h
nops.h
numa_32.h x86: set_highmem_pages_init() cleanup 2009-03-03 13:13:15 +01:00
numa_64.h
numa.h
numaq.h x86, numaq: cleanups 2009-02-05 22:30:14 +01:00
olpc.h
page_32_types.h x86-32: compute initial mapping size more accurately 2009-03-14 17:23:47 -07:00
page_32.h x86 headers: protect page_32.h via __ASSEMBLY__ 2009-02-13 13:36:47 +01:00
page_64_types.h x86: move more pagetable-related definitions into pgtable*.h 2009-02-13 11:35:01 -08:00
page_64.h x86: create _types.h counterparts for page*.h 2009-02-11 14:54:09 -08:00
page_types.h x86: clean up old gcc warnings 2009-03-05 14:50:55 +01:00
page.h x86 headers: include linux/types.h 2009-02-13 13:23:02 +01:00
param.h
paravirt.h x86: Fix performance regression caused by paravirt_ops on native kernels 2009-05-15 20:07:42 +02:00
parport.h
pat.h x86, PAT: Remove duplicate memtype reserve in devmem mmap 2009-04-10 13:55:48 +02:00
pci_64.h x86/dma: unify definition of pci_unmap_addr* and pci_unmap_len macros 2009-04-03 13:13:45 +02:00
pci_x86.h
pci-direct.h
pci-functions.h x86: move mach-default/*.h files to asm/ 2009-01-29 14:16:51 +01:00
pci.h Merge git://git.kernel.org/pub/scm/linux/kernel/git/rusty/linux-2.6-cpumask 2009-04-05 10:33:07 -07:00
percpu.h x86: fix percpu_{to,from}_op() 2009-05-11 08:54:33 -07:00
pgalloc.h
pgtable_32_types.h x86-32: use specific __vmalloc_start_set flag in __virt_addr_valid 2009-03-05 14:53:10 +01:00
pgtable_32.h x86-32: use brk segment for allocating initial kernel pagetable 2009-03-14 17:23:47 -07:00
pgtable_64_types.h x86: move more pagetable-related definitions into pgtable*.h 2009-02-13 11:35:01 -08:00
pgtable_64.h Merge branches 'x86/acpi', 'x86/asm', 'x86/cpudetect', 'x86/crashdump', 'x86/debug', 'x86/defconfig', 'x86/doc', 'x86/header-fixes', 'x86/headers' and 'x86/minor-fixes' into x86/core 2009-02-13 09:46:36 +01:00
pgtable_types.h x86: move init_memory_mapping() to common mm/init.c, build fix on 32-bit PAE 2009-03-05 14:39:03 +01:00
pgtable-2level_types.h x86: move more pagetable-related definitions into pgtable*.h 2009-02-13 11:35:01 -08:00
pgtable-2level.h x86: with the last user gone, remove set_pte_present 2009-03-19 14:04:19 +01:00
pgtable-3level_types.h x86: move more pagetable-related definitions into pgtable*.h 2009-02-13 11:35:01 -08:00
pgtable-3level.h x86: with the last user gone, remove set_pte_present 2009-03-19 14:04:19 +01:00
pgtable.h x86: with the last user gone, remove set_pte_present 2009-03-19 14:04:19 +01:00
poll.h
posix_types_32.h
posix_types_64.h
posix_types.h
prctl.h headers_check fix: x86, prctl.h 2009-02-02 23:27:09 +05:30
processor-cyrix.h
processor-flags.h
processor.h FRV: Fix the section attribute on UP DECLARE_PER_CPU() 2009-04-21 19:39:59 -07:00
proto.h x86/Voyager: remove X86_BIOS_REBOOT Kconfig quirk 2009-01-29 14:17:03 +01:00
ptrace-abi.h x86, ptrace: remove CONFIG guards around declarations 2009-02-24 18:23:35 +01:00
ptrace.h x86, 32-bit: fix kernel_trap_sp() 2009-05-12 00:39:52 +02:00
pvclock-abi.h
pvclock.h
rdc321x_defs.h
reboot_fixups.h
reboot.h
required-features.h x86-64: remove PGE from must-have feature list 2009-04-08 11:51:46 -07:00
resource.h
resume-trace.h
rio.h
rtc.h
rwlock.h
rwsem.h
scatterlist.h
seccomp_32.h x86-64: seccomp: fix 32/64 syscall hole 2009-03-02 15:41:30 -08:00
seccomp_64.h x86-64: seccomp: fix 32/64 syscall hole 2009-03-02 15:41:30 -08:00
seccomp.h
sections.h x86: add brk allocation for very, very early allocations 2009-03-14 15:37:14 -07:00
segment.h x86: implement x86_32 stack protector 2009-02-10 00:42:01 +01:00
sembuf.h
serial.h
setup_arch.h x86: move mach-default/*.h files to asm/ 2009-01-29 14:16:51 +01:00
setup.h x86: headers cleanup - setup.h 2009-03-26 18:29:49 +01:00
shmbuf.h
shmparam.h
sigcontext32.h headers_check fix: x86, sigcontext32.h 2009-01-31 00:18:58 +05:30
sigcontext.h x86: add linux kernel support for YMM state 2009-04-12 13:08:56 +02:00
sigframe.h
siginfo.h
signal.h
smp.h x86: arch_send_call_function_ipi_mask 2009-03-13 14:49:51 +10:30
smpboot_hooks.h x86: move mach-default/*.h files to asm/ 2009-01-29 14:16:51 +01:00
socket.h net: new user space API for time stamping of incoming and outgoing packets 2009-02-15 22:43:33 -08:00
sockios.h
sparsemem.h
spinlock_types.h
spinlock.h x86: Fix performance regression caused by paravirt_ops on native kernels 2009-05-15 20:07:42 +02:00
srat.h
stackprotector.h x86: fix x86_32 stack protector bugs 2009-02-11 11:33:49 +01:00
stacktrace.h
stat.h
statfs.h
string_32.h
string_64.h
string.h
suspend_32.h pm: cleanup includes 2009-04-01 08:59:16 -07:00
suspend_64.h
suspend.h
svm.h KVM: SVM: Move EFER and MSR constants to generic x86 code 2009-03-24 11:02:46 +02:00
swab.h headers_check fix: x86, swab.h 2009-01-31 00:19:32 +05:30
swiotlb.h
sync_bitops.h
sys_ia32.h generic compat_sys_ustat 2009-03-27 14:43:57 -04:00
syscall.h
syscalls.h x86: syscalls.h: remove asmlinkage from declaration of sys_rt_sigreturn() 2009-02-19 12:18:54 +01:00
system_64.h
system.h x86: add forward decl for tss_struct 2009-03-02 12:07:49 +01:00
tce.h
termbits.h
termios.h
therm_throt.h
thread_info.h tracing/x86: basic implementation of syscall tracing for x86 2009-03-13 06:25:44 +01:00
time.h
timer.h x86: fix mismerge in arch/x86/include/asm/timer.h 2009-03-30 10:10:49 -07:00
timex.h
tlb.h
tlbflush.h FRV: Fix the section attribute on UP DECLARE_PER_CPU() 2009-04-21 19:39:59 -07:00
topology.h x86/PCI: set_pci_bus_resources_arch_default cleanups 2009-04-22 14:47:46 -07:00
trampoline.h
traps.h x86: use pt_regs pointer in do_device_not_available() 2009-02-11 12:40:44 +01:00
tsc.h
types.h
uaccess_32.h x86, mm: dont use non-temporal stores in pagecache accesses 2009-03-02 11:06:49 +01:00
uaccess_64.h x86, mm: dont use non-temporal stores in pagecache accesses 2009-03-02 11:06:49 +01:00
uaccess.h x86: uaccess: use errret as error value in __put_user_size() 2009-02-04 17:28:21 -08:00
ucontext.h
unaligned.h
unistd_32.h preadv/pwritev: Add preadv and pwritev system calls. 2009-04-02 19:05:08 -07:00
unistd_64.h preadv/pwritev: Add preadv and pwritev system calls. 2009-04-02 19:05:08 -07:00
unistd.h
user32.h
user_32.h
user_64.h
user.h
vdso.h
vga.h
vgtod.h
virtext.h KVM: SVM: Move EFER and MSR constants to generic x86 code 2009-03-24 11:02:46 +02:00
vm86.h
vmi_time.h
vmi.h
vmware.h
vmx.h KVM: x86: Virtualize debug registers 2009-03-24 11:02:49 +02:00
vsyscall.h
xcr.h
xor_32.h
xor_64.h
xor.h
xsave.h x86: add linux kernel support for YMM state 2009-04-12 13:08:56 +02:00