From aad830938ed8ba175d8060751654f78d4115ea0a Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Tue, 18 Mar 2014 15:26:36 -0400 Subject: [PATCH 1/5] x86, boot: Undef memcmp before providing a new definition With CONFIG_X86_32=y, string_32.h gets pulled in compressed/string.c by "misch.h". string_32.h defines a macro to map memcmp to __builtin_memcmp(). And that macro in turn changes the name of memcmp() defined here and converts it to __builtin_memcmp(). I thought that's not the intention though. We probably want to provide our own optimized definition of memcmp(). If yes, then undef the memcmp before we define a new memcmp. Signed-off-by: Vivek Goyal Link: http://lkml.kernel.org/r/1395170800-11059-2-git-send-email-vgoyal@redhat.com Signed-off-by: H. Peter Anvin --- arch/x86/boot/compressed/string.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c index ffb9c5c9d748..212004ec787d 100644 --- a/arch/x86/boot/compressed/string.c +++ b/arch/x86/boot/compressed/string.c @@ -1,5 +1,7 @@ #include "misc.h" +/* Avoid intereference from any defines in string_32.h */ +#undef memcmp int memcmp(const void *s1, const void *s2, size_t len) { u8 diff; From c041b5ad8640dd89ccf1411cd2636ef7c1cfee92 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Tue, 18 Mar 2014 15:26:37 -0400 Subject: [PATCH 2/5] x86, boot: Create a separate string.h file to provide standard string functions Create a separate arch/x86/boot/string.h file to provide declaration of some of the common string functions. By default memcpy, memset and memcmp functions will default to gcc builtin functions. If code wants to use an optimized version of any of these functions, they need to #undef the respective macro and link against a local file providing definition of undefed function. For example, arch/x86/boot/* code links against copy.S to get memcpy() and memcmp() definitions. arch/86/boot/compressed/* links against compressed/string.c. There are quite a few places in arch/x86/ where these functions are used. Idea is to try to consilidate their declaration and possibly definitions so that it can be reused. I am planning to reuse boot/string.h in arch/x86/purgatory/ and use gcc builtin functions for memcpy, memset and memcmp. Signed-off-by: Vivek Goyal Link: http://lkml.kernel.org/r/1395170800-11059-3-git-send-email-vgoyal@redhat.com Signed-off-by: H. Peter Anvin --- arch/x86/boot/boot.h | 5 ----- arch/x86/boot/cpucheck.c | 1 + arch/x86/boot/edd.c | 1 + arch/x86/boot/main.c | 1 + arch/x86/boot/regs.c | 1 + arch/x86/boot/string.h | 19 +++++++++++++++++++ arch/x86/boot/video-vesa.c | 1 + 7 files changed, 24 insertions(+), 5 deletions(-) create mode 100644 arch/x86/boot/string.h diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h index 50f8c5e0f37e..bed9665cc7e0 100644 --- a/arch/x86/boot/boot.h +++ b/arch/x86/boot/boot.h @@ -228,11 +228,6 @@ void copy_to_fs(addr_t dst, void *src, size_t len); void *copy_from_fs(void *dst, addr_t src, size_t len); void copy_to_gs(addr_t dst, void *src, size_t len); void *copy_from_gs(void *dst, addr_t src, size_t len); -void *memcpy(void *dst, void *src, size_t len); -void *memset(void *dst, int c, size_t len); - -#define memcpy(d,s,l) __builtin_memcpy(d,s,l) -#define memset(d,c,l) __builtin_memset(d,c,l) /* a20.c */ int enable_a20(void); diff --git a/arch/x86/boot/cpucheck.c b/arch/x86/boot/cpucheck.c index 100a9a10076a..086c4f4ff741 100644 --- a/arch/x86/boot/cpucheck.c +++ b/arch/x86/boot/cpucheck.c @@ -27,6 +27,7 @@ #include #include #include +#include "string.h" static u32 err_flags[NCAPINTS]; diff --git a/arch/x86/boot/edd.c b/arch/x86/boot/edd.c index c501a5b466f8..223e42527077 100644 --- a/arch/x86/boot/edd.c +++ b/arch/x86/boot/edd.c @@ -15,6 +15,7 @@ #include "boot.h" #include +#include "string.h" #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) diff --git a/arch/x86/boot/main.c b/arch/x86/boot/main.c index cf6083d444f4..fd6c9f236996 100644 --- a/arch/x86/boot/main.c +++ b/arch/x86/boot/main.c @@ -14,6 +14,7 @@ */ #include "boot.h" +#include "string.h" struct boot_params boot_params __attribute__((aligned(16))); diff --git a/arch/x86/boot/regs.c b/arch/x86/boot/regs.c index 958019b1cfa5..c0fb356a3092 100644 --- a/arch/x86/boot/regs.c +++ b/arch/x86/boot/regs.c @@ -17,6 +17,7 @@ */ #include "boot.h" +#include "string.h" void initregs(struct biosregs *reg) { diff --git a/arch/x86/boot/string.h b/arch/x86/boot/string.h new file mode 100644 index 000000000000..10939d8da2e0 --- /dev/null +++ b/arch/x86/boot/string.h @@ -0,0 +1,19 @@ +#ifndef BOOT_STRING_H +#define BOOT_STRING_H + +/* Undef any of these macros coming from string_32.h. */ +#undef memcpy +#undef memset +#undef memcmp + +void *memcpy(void *dst, const void *src, size_t len); +void *memset(void *dst, int c, size_t len); + +/* + * Access builtin version by default. If one needs to use optimized version, + * do "undef memcpy" in .c file and link against right string.c + */ +#define memcpy(d,s,l) __builtin_memcpy(d,s,l) +#define memset(d,c,l) __builtin_memset(d,c,l) + +#endif /* BOOT_STRING_H */ diff --git a/arch/x86/boot/video-vesa.c b/arch/x86/boot/video-vesa.c index 11e8c6eb80a1..ba3e100654db 100644 --- a/arch/x86/boot/video-vesa.c +++ b/arch/x86/boot/video-vesa.c @@ -16,6 +16,7 @@ #include "boot.h" #include "video.h" #include "vesa.h" +#include "string.h" /* VESA information */ static struct vesa_general_info vginfo; From 820e8feca06ff744f60e5036c3178dde40b91afc Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Tue, 18 Mar 2014 15:26:38 -0400 Subject: [PATCH 3/5] x86, boot: Move optimized memcpy() 32/64 bit versions to compressed/string.c Move optimized versions of memcpy to compressed/string.c This will allow any other code to use these functions too if need be in future. Again trying to put definition in a common place instead of hiding it in misc.c Signed-off-by: Vivek Goyal Link: http://lkml.kernel.org/r/1395170800-11059-4-git-send-email-vgoyal@redhat.com Signed-off-by: H. Peter Anvin --- arch/x86/boot/compressed/misc.c | 31 +---------------------------- arch/x86/boot/compressed/string.c | 33 +++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 30 deletions(-) diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 196eaf373a06..3100092b1346 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -10,6 +10,7 @@ */ #include "misc.h" +#include "../string.h" /* WARNING!! * This code is compiled with -fPIC and it is relocated dynamically @@ -110,7 +111,6 @@ static void error(char *m); struct boot_params *real_mode; /* Pointer to real-mode data */ void *memset(void *s, int c, size_t n); -void *memcpy(void *dest, const void *src, size_t n); memptr free_mem_ptr; memptr free_mem_end_ptr; @@ -225,35 +225,6 @@ void *memset(void *s, int c, size_t n) ss[i] = c; return s; } -#ifdef CONFIG_X86_32 -void *memcpy(void *dest, const void *src, size_t n) -{ - int d0, d1, d2; - asm volatile( - "rep ; movsl\n\t" - "movl %4,%%ecx\n\t" - "rep ; movsb\n\t" - : "=&c" (d0), "=&D" (d1), "=&S" (d2) - : "0" (n >> 2), "g" (n & 3), "1" (dest), "2" (src) - : "memory"); - - return dest; -} -#else -void *memcpy(void *dest, const void *src, size_t n) -{ - long d0, d1, d2; - asm volatile( - "rep ; movsq\n\t" - "movq %4,%%rcx\n\t" - "rep ; movsb\n\t" - : "=&c" (d0), "=&D" (d1), "=&S" (d2) - : "0" (n >> 3), "g" (n & 7), "1" (dest), "2" (src) - : "memory"); - - return dest; -} -#endif static void error(char *x) { diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c index 212004ec787d..3b5a82fc6ad7 100644 --- a/arch/x86/boot/compressed/string.c +++ b/arch/x86/boot/compressed/string.c @@ -11,3 +11,36 @@ int memcmp(const void *s1, const void *s2, size_t len) } #include "../string.c" + +/* misc.h might pull in string_32.h which has a macro for memcpy. undef that */ +#undef memcpy + +#ifdef CONFIG_X86_32 +void *memcpy(void *dest, const void *src, size_t n) +{ + int d0, d1, d2; + asm volatile( + "rep ; movsl\n\t" + "movl %4,%%ecx\n\t" + "rep ; movsb\n\t" + : "=&c" (d0), "=&D" (d1), "=&S" (d2) + : "0" (n >> 2), "g" (n & 3), "1" (dest), "2" (src) + : "memory"); + + return dest; +} +#else +void *memcpy(void *dest, const void *src, size_t n) +{ + long d0, d1, d2; + asm volatile( + "rep ; movsq\n\t" + "movq %4,%%rcx\n\t" + "rep ; movsb\n\t" + : "=&c" (d0), "=&D" (d1), "=&S" (d2) + : "0" (n >> 3), "g" (n & 7), "1" (dest), "2" (src) + : "memory"); + + return dest; +} +#endif From fb4cac573ef6dce8d7543b68306566561c2e5725 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Tue, 18 Mar 2014 15:26:39 -0400 Subject: [PATCH 4/5] x86, boot: Move memcmp() into string.h and string.c Try to treat memcmp() in same way as memcpy() and memset(). Provide a declaration in boot/string.h and by default user gets a memcmp() which maps to builtin function. Move optimized definition of memcmp() in boot/string.c. Now a user can do #undef memcmp and link against string.c to use optimzied memcmp(). It also simplifies boot/compressed/string.c where we had to redefine memcmp(). That extra definition is gone now. Signed-off-by: Vivek Goyal Link: http://lkml.kernel.org/r/1395170800-11059-5-git-send-email-vgoyal@redhat.com Signed-off-by: H. Peter Anvin --- arch/x86/boot/boot.h | 8 -------- arch/x86/boot/compressed/string.c | 11 ----------- arch/x86/boot/string.c | 14 ++++++++++++++ arch/x86/boot/string.h | 2 ++ 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/arch/x86/boot/boot.h b/arch/x86/boot/boot.h index bed9665cc7e0..bd49ec61255c 100644 --- a/arch/x86/boot/boot.h +++ b/arch/x86/boot/boot.h @@ -177,14 +177,6 @@ static inline void wrgs32(u32 v, addr_t addr) } /* Note: these only return true/false, not a signed return value! */ -static inline int memcmp(const void *s1, const void *s2, size_t len) -{ - u8 diff; - asm("repe; cmpsb; setnz %0" - : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); - return diff; -} - static inline int memcmp_fs(const void *s1, addr_t s2, size_t len) { u8 diff; diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c index 3b5a82fc6ad7..920b55e3e241 100644 --- a/arch/x86/boot/compressed/string.c +++ b/arch/x86/boot/compressed/string.c @@ -1,15 +1,4 @@ #include "misc.h" - -/* Avoid intereference from any defines in string_32.h */ -#undef memcmp -int memcmp(const void *s1, const void *s2, size_t len) -{ - u8 diff; - asm("repe; cmpsb; setnz %0" - : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); - return diff; -} - #include "../string.c" /* misc.h might pull in string_32.h which has a macro for memcpy. undef that */ diff --git a/arch/x86/boot/string.c b/arch/x86/boot/string.c index 574dedfe2890..5339040ef86e 100644 --- a/arch/x86/boot/string.c +++ b/arch/x86/boot/string.c @@ -14,6 +14,20 @@ #include "boot.h" +/* + * This file gets included in compressed/string.c which might pull in + * string_32.h and which in turn maps memcmp to __builtin_memcmp(). Undo + * that first. + */ +#undef memcmp +int memcmp(const void *s1, const void *s2, size_t len) +{ + u8 diff; + asm("repe; cmpsb; setnz %0" + : "=qm" (diff), "+D" (s1), "+S" (s2), "+c" (len)); + return diff; +} + int strcmp(const char *str1, const char *str2) { const unsigned char *s1 = (const unsigned char *)str1; diff --git a/arch/x86/boot/string.h b/arch/x86/boot/string.h index 10939d8da2e0..725e820602b1 100644 --- a/arch/x86/boot/string.h +++ b/arch/x86/boot/string.h @@ -8,6 +8,7 @@ void *memcpy(void *dst, const void *src, size_t len); void *memset(void *dst, int c, size_t len); +int memcmp(const void *s1, const void *s2, size_t len); /* * Access builtin version by default. If one needs to use optimized version, @@ -15,5 +16,6 @@ void *memset(void *dst, int c, size_t len); */ #define memcpy(d,s,l) __builtin_memcpy(d,s,l) #define memset(d,c,l) __builtin_memset(d,c,l) +#define memcmp __builtin_memcmp #endif /* BOOT_STRING_H */ From 04999550f93234bf05597a9b7d26e2bfe27ba883 Mon Sep 17 00:00:00 2001 From: Vivek Goyal Date: Tue, 18 Mar 2014 15:26:40 -0400 Subject: [PATCH 5/5] x86, boot: Move memset() definition in compressed/string.c Currently compressed/misc.c needs to link against memset(). I think one of the reasons of this need is inclusion of various header files which define static inline functions and use memset() inside these. For example, include/linux/bitmap.h I think trying to include "../string.h" and using builtin version of memset does not work because by the time "#define memset" shows up, it is too late. Some other header file has already used memset() and expects to find a definition during link phase. Currently we have a C definitoin of memset() in misc.c. Move it to compressed/string.c so that others can use it if need be. Signed-off-by: Vivek Goyal Link: http://lkml.kernel.org/r/1395170800-11059-6-git-send-email-vgoyal@redhat.com Signed-off-by: H. Peter Anvin --- arch/x86/boot/compressed/misc.c | 20 +++++++------------- arch/x86/boot/compressed/string.c | 10 ++++++++++ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c index 3100092b1346..17684615374b 100644 --- a/arch/x86/boot/compressed/misc.c +++ b/arch/x86/boot/compressed/misc.c @@ -98,8 +98,14 @@ */ #define STATIC static -#undef memset #undef memcpy + +/* + * Use a normal definition of memset() from string.c. There are already + * included header files which expect a definition of memset() and by + * the time we define memset macro, it is too late. + */ +#undef memset #define memzero(s, n) memset((s), 0, (n)) @@ -110,8 +116,6 @@ static void error(char *m); */ struct boot_params *real_mode; /* Pointer to real-mode data */ -void *memset(void *s, int c, size_t n); - memptr free_mem_ptr; memptr free_mem_end_ptr; @@ -216,16 +220,6 @@ void __putstr(const char *s) outb(0xff & (pos >> 1), vidport+1); } -void *memset(void *s, int c, size_t n) -{ - int i; - char *ss = s; - - for (i = 0; i < n; i++) - ss[i] = c; - return s; -} - static void error(char *x) { error_putstr("\n\n"); diff --git a/arch/x86/boot/compressed/string.c b/arch/x86/boot/compressed/string.c index 920b55e3e241..f3c57e341402 100644 --- a/arch/x86/boot/compressed/string.c +++ b/arch/x86/boot/compressed/string.c @@ -33,3 +33,13 @@ void *memcpy(void *dest, const void *src, size_t n) return dest; } #endif + +void *memset(void *s, int c, size_t n) +{ + int i; + char *ss = s; + + for (i = 0; i < n; i++) + ss[i] = c; + return s; +}