Merge branch 'x86/boot' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 boot changes from Peter Anvin:
 "This patchset is a set of cleanups aiming at librarize some of the
  common code from the boot environments.  We currently have three
  different "little environments" (boot, boot/compressed, and
  realmode/rm) in x86, and we are likely to soon get a fourth one
  (kexec/purgatory, which will have to be integrated in the kernel to
  support secure kexec).  This is primarily a cleanup in the
  anticipation of the latter.

  While Vivek implemented this, he ran into some bugs, in particular the
  memcmp implementation for when gcc punts from using the builtin would
  have a misnamed symbol, causing compilation errors if we were ever
  unlucky enough that gcc didn't want to inline the test"

* 'x86/boot' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86, boot: Move memset() definition in compressed/string.c
  x86, boot: Move memcmp() into string.h and string.c
  x86, boot: Move optimized memcpy() 32/64 bit versions to compressed/string.c
  x86, boot: Create a separate string.h file to provide standard string functions
  x86, boot: Undef memcmp before providing a new definition
This commit is contained in:
Linus Torvalds 2014-04-02 12:23:49 -07:00
commit 9447dc4394
10 changed files with 91 additions and 65 deletions

View File

@ -177,14 +177,6 @@ static inline void wrgs32(u32 v, addr_t addr)
} }
/* Note: these only return true/false, not a signed return value! */ /* 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) static inline int memcmp_fs(const void *s1, addr_t s2, size_t len)
{ {
u8 diff; u8 diff;
@ -228,11 +220,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_from_fs(void *dst, addr_t src, size_t len);
void copy_to_gs(addr_t dst, void *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 *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 */ /* a20.c */
int enable_a20(void); int enable_a20(void);

View File

@ -10,6 +10,7 @@
*/ */
#include "misc.h" #include "misc.h"
#include "../string.h"
/* WARNING!! /* WARNING!!
* This code is compiled with -fPIC and it is relocated dynamically * This code is compiled with -fPIC and it is relocated dynamically
@ -97,8 +98,14 @@
*/ */
#define STATIC static #define STATIC static
#undef memset
#undef memcpy #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)) #define memzero(s, n) memset((s), 0, (n))
@ -109,9 +116,6 @@ static void error(char *m);
*/ */
struct boot_params *real_mode; /* Pointer to real-mode data */ 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_ptr;
memptr free_mem_end_ptr; memptr free_mem_end_ptr;
@ -216,45 +220,6 @@ void __putstr(const char *s)
outb(0xff & (pos >> 1), vidport+1); 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;
}
#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) static void error(char *x)
{ {
error_putstr("\n\n"); error_putstr("\n\n");

View File

@ -1,11 +1,45 @@
#include "misc.h" #include "misc.h"
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" #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
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;
}

View File

@ -27,6 +27,7 @@
#include <asm/processor-flags.h> #include <asm/processor-flags.h>
#include <asm/required-features.h> #include <asm/required-features.h>
#include <asm/msr-index.h> #include <asm/msr-index.h>
#include "string.h"
static u32 err_flags[NCAPINTS]; static u32 err_flags[NCAPINTS];

View File

@ -15,6 +15,7 @@
#include "boot.h" #include "boot.h"
#include <linux/edd.h> #include <linux/edd.h>
#include "string.h"
#if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE) #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)

View File

@ -14,6 +14,7 @@
*/ */
#include "boot.h" #include "boot.h"
#include "string.h"
struct boot_params boot_params __attribute__((aligned(16))); struct boot_params boot_params __attribute__((aligned(16)));

View File

@ -17,6 +17,7 @@
*/ */
#include "boot.h" #include "boot.h"
#include "string.h"
void initregs(struct biosregs *reg) void initregs(struct biosregs *reg)
{ {

View File

@ -14,6 +14,20 @@
#include "boot.h" #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) int strcmp(const char *str1, const char *str2)
{ {
const unsigned char *s1 = (const unsigned char *)str1; const unsigned char *s1 = (const unsigned char *)str1;

21
arch/x86/boot/string.h Normal file
View File

@ -0,0 +1,21 @@
#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);
int memcmp(const void *s1, const void *s2, 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)
#define memcmp __builtin_memcmp
#endif /* BOOT_STRING_H */

View File

@ -16,6 +16,7 @@
#include "boot.h" #include "boot.h"
#include "video.h" #include "video.h"
#include "vesa.h" #include "vesa.h"
#include "string.h"
/* VESA information */ /* VESA information */
static struct vesa_general_info vginfo; static struct vesa_general_info vginfo;