x86/mem changes for v2.6.40
Linus,
Please pull the latest x86-mem-for-linus git tree from:
git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip.git x86-mem-for-linus
Thanks,
Ingo
------------------>
Fenghua Yu (10):
x86, cpufeature: Fix cpuid leaf 7 feature detection
x86, cpufeature: Add CPU feature bit for enhanced REP MOVSB/STOSB x86, mem, intel: Initialize Enhanced REP MOVSB/STOSB
x86, alternative, doc: Add comment for applying alternatives order x86, alternative: Add altinstruction_entry macro
x86, mem: clear_page_64.S: Support clear_page() with enhanced REP MOVSB/STOSB x86, mem: copy_user_64.S: Support copy_to/from_user by enhanced REP MOVSB/STOSB x86, mem: memcpy_64.S: Optimize memcpy by enhanced REP MOVSB/STOSB x86, mem: memmove_64.S: Optimize memmove by enhanced REP MOVSB/STOSB x86, mem: memset_64.S: Optimize memset by enhanced REP MOVSB/STOSB
Jiri Olsa (1):
x86, 64-bit: Fix copy_[to/from]_user() checks for the userspace address limit
arch/x86/include/asm/alternative-asm.h | 9 ++++ arch/x86/include/asm/cpufeature.h | 1 + arch/x86/include/asm/uaccess.h | 2 +- arch/x86/kernel/alternative.c | 9 ++++ arch/x86/kernel/cpu/common.c | 3 +- arch/x86/kernel/cpu/intel.c | 19 +++++++-- arch/x86/lib/clear_page_64.S | 33 +++++++++++---- arch/x86/lib/copy_user_64.S | 69 ++++++++++++++++++++++++++------ arch/x86/lib/memcpy_64.S | 45 +++++++++++++++------ arch/x86/lib/memmove_64.S | 29 +++++++++++++- arch/x86/lib/memset_64.S | 54 +++++++++++++++++++------ 11 files changed, 219 insertions(+), 54 deletions(-)
arch/x86/include/asm/alternative-asm.h +9 -0
@@ -15,4 +15,13 @@ .endm #endif +.macro altinstruction_entry orig alt feature orig_len alt_len + .align 8 + .quad \orig + .quad \alt + .word \feature + .byte \orig_len + .byte \alt_len +.endm +#endif /* __ASSEMBLY__ */
arch/x86/include/asm/cpufeature.h +1 -0
@@ -195,6 +195,7 @@/* Intel-defined CPU features, CPUID level 0x00000007:0 (ebx), word 9 */ #define X86_FEATURE_FSGSBASE (9*32+ 0)/* {RD/WR}{FS/GS}BASE instructions*/ +#define X86_FEATURE_ERMS (9*32+ 9)/* Enhanced REP MOVSB/STOSB */ #if defined(__KERNEL__) && !defined(__ASSEMBLY__)
arch/x86/include/asm/uaccess.h +1 -1
@@ -42,7 +42,7 @@* Returns 0 if the range is valid, nonzero otherwise. * * This is equivalent to the following test: -* (u33)addr + (u33)size >= (u33)current->addr_limit.seg (u65 for x86_64) +* (u33)addr + (u33)size > (u33)current->addr_limit.seg (u65 for x86_64) * * This needs 33-bit (65-bit for x86_64) arithmetic. We have a carry... */
arch/x86/kernel/alternative.c +9 -0
@@ -210,6 +210,15 @@ void __init_or_module apply_alternatives(struct alt_instr *start,u8 insnbuf[MAX_PATCH_LEN ];DPRINTK ("%s: alt table %p -> %p\n" , __func__, start, end); +/* +* The scan order should be from start to end. A later scanned +* alternative code can overwrite a previous scanned alternative code. +* Some kernel functions (e.g. memcpy, memset, etc) use this order to +* patch code. +* +* So be careful if you want to change the scan order to any other +* order. +*/ for (a = start; a < end; a++) {u8 *instr = a->instr;BUG_ON (a->replacementlen > a->instrlen);
arch/x86/kernel/cpu/common.c +1 -2
@@ -565,8 +565,7 @@ void __cpuinit get_cpu_cap(struct cpuinfo_x86 *c)cpuid_count (0x00000007 ,0 , &eax, &ebx, &ecx, &edx); -if (eax >0 ) - c->x86_capability[9 ] = ebx; + c->x86_capability[9 ] = ebx; }/* AMD-defined flags: level 0x80000001 */
arch/x86/kernel/cpu/intel.c +15 -4
@@ -29,10 +29,10 @@static void __cpuinit early_init_intel (struct cpuinfo_x86 *c) { +u64 misc_enable; +/* Unmask CPUID levels if masked: */ if (c->x86 >6 || (c->x86 ==6 && c->x86_model >=0xd )) { -u64 misc_enable; -rdmsrl (MSR_IA32_MISC_ENABLE , misc_enable);if (misc_enable &MSR_IA32_MISC_ENABLE_LIMIT_CPUID ) {
@@ -118,8 +118,6 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c)* (model 2) with the same problem. */ if (c->x86 ==15 ) { -u64 misc_enable; -rdmsrl (MSR_IA32_MISC_ENABLE , misc_enable);if (misc_enable &MSR_IA32_MISC_ENABLE_FAST_STRING ) {
@@ -130,6 +128,19 @@ static void __cpuinit early_init_intel(struct cpuinfo_x86 *c) } }#endif + +/* +* If fast string is not enabled in IA32_MISC_ENABLE for any reason, +* clear the fast string and enhanced fast string CPU capabilities. +*/ +if (c->x86 >6 || (c->x86 ==6 && c->x86_model >=0xd )) { +rdmsrl (MSR_IA32_MISC_ENABLE , misc_enable); +if (!(misc_enable &MSR_IA32_MISC_ENABLE_FAST_STRING )) { +printk (KERN_INFO "Disabled fast string operations\n" ); +setup_clear_cpu_cap (X86_FEATURE_REP_GOOD ); +setup_clear_cpu_cap (X86_FEATURE_ERMS ); + } + } }#ifdef CONFIG_X86_32
arch/x86/lib/clear_page_64.S +24 -9
@@ -1,5 +1,6 @@ #include <linux/linkage.h> #include <asm/dwarf2.h> +#include <asm/alternative-asm.h> /* * Zero a page.
@@ -14,6 +15,15 @@ ENTRY(clear_page_c) CFI_ENDPROC ENDPROC(clear_page_c) +ENTRY(clear_page_c_e) + CFI_STARTPROC + movl $4096,%ecx + xorl %eax,%eax + rep stosb + ret + CFI_ENDPROC +ENDPROC(clear_page_c_e) + ENTRY(clear_page) CFI_STARTPROC xorl %eax,%eax
@@ -38,21 +48,26 @@ ENTRY(clear_page) .Lclear_page_end: ENDPROC(clear_page) - /* Some CPUs run faster using the string instructions. - It is also a lot simpler. Use this when possible */ + /* + * Some CPUs support enhanced REP MOVSB/STOSB instructions. + * It is recommended to use this when possible. + * If enhanced REP MOVSB/STOSB is not available, try to use fast string. + * Otherwise, use original function. + * + */ #include <asm/cpufeature.h> .section .altinstr_replacement,"ax" 1: .byte 0xeb /* jmp <disp8> */ .byte (clear_page_c - clear_page) - (2f - 1b) /* offset */ -2: +2: .byte 0xeb /* jmp <disp8> */ + .byte (clear_page_c_e - clear_page) - (3f - 2b) /* offset */ +3: .previous .section .altinstructions,"a" - .align 8 - .quad clear_page - .quad 1b - .word X86_FEATURE_REP_GOOD - .byte .Lclear_page_end - clear_page - .byte 2b - 1b + altinstruction_entry clear_page,1b,X86_FEATURE_REP_GOOD,\ + .Lclear_page_end-clear_page, 2b-1b + altinstruction_entry clear_page,2b,X86_FEATURE_ERMS, \ + .Lclear_page_end-clear_page,3b-2b .previous
arch/x86/lib/copy_user_64.S +57 -12
99 lines not on this page · raw message
arch/x86/lib/memcpy_64.S +32 -13
65 lines not on this page · raw message
arch/x86/lib/memmove_64.S +28 -1
@@ -8,6 +8,7 @@ #define _STRING_C #include <linux/linkage.h> #include <asm/dwarf2.h> +#include <asm/cpufeature.h> #undef memmove
@@ -24,6 +25,7 @@ */ ENTRY(memmove) CFI_STARTPROC + /* Handle more 32bytes in loop */ mov %rdi, %rax cmp $0x20, %rdx
@@ -31,8 +33,13 @@ ENTRY(memmove) /* Decide forward/backward copy mode */ cmp %rdi, %rsi - jb 2f + jge .Lmemmove_begin_forward + mov %rsi, %r8 + add %rdx, %r8 + cmp %rdi, %r8 + jg 2f +.Lmemmove_begin_forward: /* * movsq instruction have many startup latency * so we handle small size by general register.
@@ -78,6 +85,8 @@ ENTRY(memmove) rep movsq movq %r11, (%r10) jmp 13f +.Lmemmove_end_forward: + /* * Handle data backward by movsq. */
@@ -194,4 +203,22 @@ ENTRY(memmove) 13: retq CFI_ENDPROC + + .section .altinstr_replacement,"ax" +.Lmemmove_begin_forward_efs: + /* Forward moving data. */ + movq %rdx, %rcx + rep movsb + retq +.Lmemmove_end_forward_efs: + .previous + + .section .altinstructions,"a" + .align 8 + .quad .Lmemmove_begin_forward + .quad .Lmemmove_begin_forward_efs + .word X86_FEATURE_ERMS + .byte .Lmemmove_end_forward-.Lmemmove_begin_forward + .byte .Lmemmove_end_forward_efs-.Lmemmove_begin_forward_efs + .previous ENDPROC(memmove)
arch/x86/lib/memset_64.S +42 -12
73 lines not on this page · raw message